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 | 121 | below. |
| 122 | 122 | |
| 123 | 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 | 127 | CXL Flash Driver IOCTLs |
| @@ -171,11 +171,30 @@ DK_CXLFLASH_ATTACH · 43 unmodified lines | ||
| 171 | 171 | destroyed, the tokens are to be considered stale and subsequent |
| 172 | 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 | 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 | |
| 178 | − required by the user. | |
| 195 | + - At any time, a close on fd2 will invalidate the tokens. Applications | |
| 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 | 199 | DK_CXLFLASH_USER_DIRECT |
| 181 | 200 | ----------------------- |
| @@ -254,6 +273,10 @@ DK_CXLFLASH_DETACH · 72 unmodified lines | ||
| 254 | 273 | success, all "tokens" which had been provided to the user from the |
| 255 | 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 | 280 | DK_CXLFLASH_VLUN_CLONE |
| 258 | 281 | ---------------------- |
| 259 | 282 | This ioctl is responsible for cloning a previously created |
| @@ -261,7 +284,7 @@ DK_CXLFLASH_VLUN_CLONE · 1 unmodified line | ||
| 261 | 284 | support maintaining user space access to storage after a process |
| 262 | 285 | forks. Upon success, the child process (which invoked the ioctl) |
| 263 | 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 | 289 | Context sharing across processes is not supported with CXL and |
| 267 | 290 | therefore each fork must be met with establishing a new context |
| @@ -275,6 +298,12 @@ DK_CXLFLASH_VLUN_CLONE · 7 unmodified lines | ||
| 275 | 298 | translation tables are copied from the parent context to the child's |
| 276 | 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 | 307 | DK_CXLFLASH_VERIFY |
| 279 | 308 | ------------------ |
| 280 | 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 | 338 | at which time the context/resources they held will be freed as part of |
| 310 | 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 | 346 | DK_CXLFLASH_MANAGE_LUN |
| 313 | 347 | ---------------------- |
| 314 | 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 | 64 | - HP Smart Array Controller SCSI driver. |
| 65 | 65 | hptiop.txt |
| 66 | 66 | - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER |
| 67 | −in2000.txt | |
| 68 | − - info on in2000 driver | |
| 69 | 67 | libsas.txt |
| 70 | 68 | - Serial Attached SCSI management layer. |
| 71 | 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 | 34 | See drivers/scsi/BusLogic.c, comment before function |
| 35 | 35 | BusLogic_ParseDriverOptions(). |
| 36 | 36 | |
| 37 | − dtc3181e= [HW,SCSI] | |
| 38 | − See Documentation/scsi/g_NCR5380.txt. | |
| 39 | − | |
| 40 | 37 | eata= [HW,SCSI] |
| 41 | 38 | |
| 42 | 39 | fdomain= [HW,SCSI] |
| @@ -47,9 +44,6 @@ parameters may be changed at runtime by the command · 4 unmodified lines | ||
| 47 | 44 | |
| 48 | 45 | gvp11= [HW,SCSI] |
| 49 | 46 | |
| 50 | − in2000= [HW,SCSI] | |
| 51 | − See header of drivers/scsi/in2000.c. | |
| 52 | − | |
| 53 | 47 | ips= [HW,SCSI] Adaptec / IBM ServeRAID controller |
| 54 | 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 | 77 | Format: <buffer_size>,<write_threshold> |
| 84 | 78 | See also Documentation/scsi/st.txt. |
| 85 | 79 | |
| 86 | − pas16= [HW,SCSI] | |
| 87 | − See header of drivers/scsi/pas16.c. | |
| 88 | − | |
| 89 | 80 | scsi_debug_*= [SCSI] |
| 90 | 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 | 110 | sym53c416= [HW,SCSI] |
| 120 | 111 | See header of drivers/scsi/sym53c416.c. |
| 121 | 112 | |
| 122 | − t128= [HW,SCSI] | |
| 123 | − See header of drivers/scsi/t128.c. | |
| 124 | − | |
| 125 | 113 | tmscsim= [HW,SCSI] |
| 126 | 114 | See comment before function dc390_setup() in |
| 127 | 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 | 117 | wd33c93= [HW,SCSI] |
| 133 | 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 | 7973 | S: Supported |
| 7974 | 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 | 7988 | MN88472 MEDIA DRIVER |
| 7977 | 7989 | M: Antti Palosaari <crope@iki.fi> |
| 7978 | 7990 | L: linux-media@vger.kernel.org |
| @@ -8185,20 +8197,16 @@ M: Michael Schmitz <schmitzmic@gmail.com> · 206 unmodified lines | ||
| 8185 | 8197 | L: linux-scsi@vger.kernel.org |
| 8186 | 8198 | S: Maintained |
| 8187 | 8199 | F: Documentation/scsi/g_NCR5380.txt |
| 8188 | −F: Documentation/scsi/dtc3x80.txt | |
| 8189 | 8200 | F: drivers/scsi/NCR5380.* |
| 8190 | 8201 | F: drivers/scsi/arm/cumana_1.c |
| 8191 | 8202 | F: drivers/scsi/arm/oak.c |
| 8192 | 8203 | F: drivers/scsi/atari_scsi.* |
| 8193 | 8204 | F: drivers/scsi/dmx3191d.c |
| 8194 | −F: drivers/scsi/dtc.* | |
| 8195 | 8205 | F: drivers/scsi/g_NCR5380.* |
| 8196 | 8206 | F: drivers/scsi/g_NCR5380_mmio.c |
| 8197 | 8207 | F: drivers/scsi/mac_scsi.* |
| 8198 | −F: drivers/scsi/pas16.* | |
| 8199 | 8208 | F: drivers/scsi/sun3_scsi.* |
| 8200 | 8209 | F: drivers/scsi/sun3_scsi_vme.c |
| 8201 | −F: drivers/scsi/t128.* | |
| 8202 | 8210 | |
| 8203 | 8211 | NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) |
| 8204 | 8212 | M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> |
| @@ -10740,12 +10748,12 @@ S: Maintained · 2535 unmodified lines | ||
| 10740 | 10748 | F: drivers/misc/phantom.c |
| 10741 | 10749 | F: include/uapi/linux/phantom.h |
| 10742 | 10750 | |
| 10743 | −SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER | |
| 10744 | −M: Jayamohan Kallickal <jayamohan.kallickal@avagotech.com> | |
| 10745 | −M: Ketan Mukadam <ketan.mukadam@avagotech.com> | |
| 10746 | −M: John Soni Jose <sony.john@avagotech.com> | |
| 10751 | +Emulex 10Gbps iSCSI - OneConnect DRIVER | |
| 10752 | +M: Subbu Seetharaman <subbu.seetharaman@broadcom.com> | |
| 10753 | +M: Ketan Mukadam <ketan.mukadam@broadcom.com> | |
| 10754 | +M: Jitendra Bhivare <jitendra.bhivare@broadcom.com> | |
| 10747 | 10755 | L: linux-scsi@vger.kernel.org |
| 10748 | −W: http://www.avagotech.com | |
| 10756 | +W: http://www.broadcom.com | |
| 10749 | 10757 | S: Supported |
| 10750 | 10758 | F: drivers/scsi/be2iscsi/ |
| 10751 | 10759 | |
| @@ -12143,12 +12151,6 @@ S: Maintained · 1391 unmodified lines | ||
| 12143 | 12151 | F: drivers/tc/ |
| 12144 | 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 | 12154 | UBI FILE SYSTEM (UBIFS) |
| 12153 | 12155 | M: Richard Weinberger <richard@nod.at> |
| 12154 | 12156 | M: Artem Bityutskiy <dedekind1@gmail.com> |
| @@ -12876,12 +12878,6 @@ F: drivers/watchdog/ · 721 unmodified lines | ||
| 12876 | 12878 | F: include/linux/watchdog.h |
| 12877 | 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 | 12881 | WIIMOTE HID DRIVER |
| 12886 | 12882 | M: David Herrmann <dh.herrmann@googlemail.com> |
| 12887 | 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 | 1866 | snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN, |
| 1867 | 1867 | "mpt_poll_%d", ioc->id); |
| 1868 | − ioc->reset_work_q = | |
| 1869 | − create_singlethread_workqueue(ioc->reset_work_q_name); | |
| 1868 | + ioc->reset_work_q = alloc_workqueue(ioc->reset_work_q_name, | |
| 1869 | + WQ_MEM_RECLAIM, 0); | |
| 1870 | 1870 | if (!ioc->reset_work_q) { |
| 1871 | 1871 | printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", |
| 1872 | 1872 | ioc->name); |
| @@ -1992,7 +1992,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) · 119 unmodified lines | ||
| 1992 | 1992 | INIT_LIST_HEAD(&ioc->fw_event_list); |
| 1993 | 1993 | spin_lock_init(&ioc->fw_event_lock); |
| 1994 | 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 | 1997 | if (!ioc->fw_event_q) { |
| 1997 | 1998 | printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", |
| 1998 | 1999 | ioc->name); |
| @@ -1324,9 +1324,12 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 1323 unmodified lines | ||
| 1324 | 1324 | snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name), |
| 1325 | 1325 | "mptfc_wq_%d", sh->host_no); |
| 1326 | 1326 | ioc->fc_rescan_work_q = |
| 1327 | − create_singlethread_workqueue(ioc->fc_rescan_work_q_name); | |
| 1328 | − if (!ioc->fc_rescan_work_q) | |
| 1327 | + alloc_ordered_workqueue(ioc->fc_rescan_work_q_name, | |
| 1328 | + WQ_MEM_RECLAIM); | |
| 1329 | + if (!ioc->fc_rescan_work_q) { | |
| 1330 | + error = -ENOMEM; | |
| 1329 | 1331 | goto out_mptfc_probe; |
| 1332 | + } | |
| 1330 | 1333 | |
| 1331 | 1334 | /* |
| 1332 | 1335 | * Pre-fetch FC port WWN and stuff... |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * |
| 4 | 4 | * Debug traces for zfcp. |
| 5 | 5 | * |
| 6 | − * Copyright IBM Corp. 2002, 2013 | |
| 6 | + * Copyright IBM Corp. 2002, 2016 | |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 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 | 65 | * @tag: tag indicating which kind of unsolicited status has been received |
| 66 | 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 | 70 | struct zfcp_dbf *dbf = req->adapter->dbf; |
| 71 | 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 | 85 | rec->u.res.req_issued = req->issued; |
| 86 | 86 | rec->u.res.prot_status = q_pref->prot_status; |
| 87 | 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 | 91 | memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, |
| 90 | 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 | 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 | 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 | 243 | if (sdev) { |
| 242 | 244 | rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); |
| 243 | 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 | 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 | 358 | static inline |
| 324 | −void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len, | |
| 325 | − u64 req_id, u32 d_id) | |
| 359 | +void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, | |
| 360 | + char *paytag, struct scatterlist *sg, u8 id, u16 len, | |
| 361 | + u64 req_id, u32 d_id, u16 cap_len) | |
| 326 | 362 | { |
| 327 | 363 | struct zfcp_dbf_san *rec = &dbf->san_buf; |
| 328 | 364 | u16 rec_len; |
| 329 | 365 | unsigned long flags; |
| 366 | + struct zfcp_dbf_pay *payload = &dbf->pay_buf; | |
| 367 | + u16 pay_sum = 0; | |
| 330 | 368 | |
| 331 | 369 | spin_lock_irqsave(&dbf->san_lock, flags); |
| 332 | 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 | 372 | rec->id = id; |
| 335 | 373 | rec->fsf_req_id = req_id; |
| 336 | 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 | 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 | 410 | debug_event(dbf->san, 1, rec, sizeof(*rec)); |
| 342 | 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 | 423 | struct zfcp_fsf_ct_els *ct_els = fsf->data; |
| 355 | 424 | u16 length; |
| 356 | 425 | |
| 357 | − length = (u16)(ct_els->req->length + FC_CT_HDR_LEN); | |
| 358 | − zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length, | |
| 359 | − fsf->req_id, d_id); | |
| 426 | + length = (u16)zfcp_qdio_real_bytes(ct_els->req); | |
| 427 | + zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ, | |
| 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 | 492 | struct zfcp_fsf_ct_els *ct_els = fsf->data; |
| 371 | 493 | u16 length; |
| 372 | 494 | |
| 373 | − length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN); | |
| 374 | − zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length, | |
| 375 | − fsf->req_id, 0); | |
| 495 | + length = (u16)zfcp_qdio_real_bytes(ct_els->resp); | |
| 496 | + zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES, | |
| 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 | 509 | struct fsf_status_read_buffer *srb = |
| 387 | 510 | (struct fsf_status_read_buffer *) fsf->data; |
| 388 | 511 | u16 length; |
| 512 | + struct scatterlist sg; | |
| 389 | 513 | |
| 390 | 514 | length = (u16)(srb->length - |
| 391 | 515 | offsetof(struct fsf_status_read_buffer, payload)); |
| 392 | − zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length, | |
| 393 | − fsf->req_id, ntoh24(srb->d_id)); | |
| 516 | + sg_init_one(&sg, srb->payload.data, length); | |
| 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 | 524 | * @sc: pointer to struct scsi_cmnd |
| 400 | 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 | 530 | struct zfcp_adapter *adapter = |
| 405 | 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 | 572 | spin_unlock_irqrestore(&dbf->scsi_lock, flags); |
| 447 | 573 | } |
| 448 | 574 | |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | * zfcp device driver |
| 3 | 3 | * debug feature declarations |
| 4 | 4 | * |
| 5 | − * Copyright IBM Corp. 2008, 2010 | |
| 5 | + * Copyright IBM Corp. 2008, 2015 | |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #ifndef ZFCP_DBF_H |
| @@ -17,6 +17,11 @@ · 8 unmodified lines | ||
| 17 | 17 | |
| 18 | 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 | 26 | * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action |
| 22 | 27 | * @ready: number of ready recovery actions |
| @@ -110,6 +115,7 @@ struct zfcp_dbf_san { · 87 unmodified lines | ||
| 110 | 115 | u32 d_id; |
| 111 | 116 | #define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32) |
| 112 | 117 | char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; |
| 118 | + u16 pl_len; | |
| 113 | 119 | } __packed; |
| 114 | 120 | |
| 115 | 121 | /** |
| @@ -126,6 +132,8 @@ struct zfcp_dbf_hba_res { · 10 unmodified lines | ||
| 126 | 132 | u8 prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; |
| 127 | 133 | u32 fsf_status; |
| 128 | 134 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; |
| 135 | + u32 port_handle; | |
| 136 | + u32 lun_handle; | |
| 129 | 137 | } __packed; |
| 130 | 138 | |
| 131 | 139 | /** |
| @@ -279,7 +287,7 @@ static inline · 147 unmodified lines | ||
| 279 | 287 | void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req) |
| 280 | 288 | { |
| 281 | 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 | 326 | scmd->device->host->hostdata[0]; |
| 319 | 327 | |
| 320 | 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 | 4 | * Error Recovery Procedures (ERP). |
| 5 | 5 | * |
| 6 | − * Copyright IBM Corp. 2002, 2010 | |
| 6 | + * Copyright IBM Corp. 2002, 2015 | |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 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 | 1217 | break; |
| 1218 | 1218 | |
| 1219 | 1219 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 1220 | − if (result == ZFCP_ERP_SUCCEEDED) | |
| 1221 | − zfcp_scsi_schedule_rport_register(port); | |
| 1220 | + /* This switch case might also happen after a forced reopen | |
| 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 | 1228 | /* fall through */ |
| 1223 | 1229 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 1224 | 1230 | put_device(&port->dev); |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * |
| 4 | 4 | * External function declarations. |
| 5 | 5 | * |
| 6 | − * Copyright IBM Corp. 2002, 2010 | |
| 6 | + * Copyright IBM Corp. 2002, 2015 | |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | #ifndef ZFCP_EXT_H |
| @@ -35,8 +35,9 @@ extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); · 25 unmodified lines | ||
| 35 | 35 | extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, |
| 36 | 36 | struct zfcp_port *, struct scsi_device *, u8, u8); |
| 37 | 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 | 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 | 41 | extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); |
| 41 | 42 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); |
| 42 | 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 | 45 | extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); |
| 45 | 46 | extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); |
| 46 | 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 | 51 | /* zfcp_erp.c */ |
| 50 | 52 | extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * |
| 4 | 4 | * Implementation of FSF commands. |
| 5 | 5 | * |
| 6 | − * Copyright IBM Corp. 2002, 2013 | |
| 6 | + * Copyright IBM Corp. 2002, 2015 | |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 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 | 508 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
| 509 | 509 | break; |
| 510 | 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 | 515 | break; |
| 513 | 516 | case FSF_TOPO_AL: |
| 514 | 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 | 617 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { |
| 615 | 618 | fc_host_permanent_port_name(shost) = bottom->wwpn; |
| 616 | − fc_host_port_type(shost) = FC_PORTTYPE_NPIV; | |
| 617 | 619 | } else |
| 618 | 620 | fc_host_permanent_port_name(shost) = fc_host_port_name(shost); |
| 619 | 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 | 984 | if (zfcp_adapter_multi_buffer_active(adapter)) { |
| 983 | 985 | if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req)) |
| 984 | 986 | return -EIO; |
| 987 | + qtcb->bottom.support.req_buf_length = | |
| 988 | + zfcp_qdio_real_bytes(sg_req); | |
| 985 | 989 | if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp)) |
| 986 | 990 | return -EIO; |
| 991 | + qtcb->bottom.support.resp_buf_length = | |
| 992 | + zfcp_qdio_real_bytes(sg_resp); | |
| 987 | 993 | |
| 988 | 994 | zfcp_qdio_set_data_div(qdio, &req->qdio_req, |
| 989 | 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 | 1080 | req->handler = zfcp_fsf_send_ct_handler; |
| 1075 | 1081 | req->qtcb->header.port_handle = wka_port->handle; |
| 1082 | + ct->d_id = wka_port->d_id; | |
| 1076 | 1083 | req->data = ct; |
| 1077 | 1084 | |
| 1078 | 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 | 1177 | hton24(req->qtcb->bottom.support.d_id, d_id); |
| 1171 | 1178 | req->handler = zfcp_fsf_send_els_handler; |
| 1179 | + els->d_id = d_id; | |
| 1172 | 1180 | req->data = els; |
| 1173 | 1181 | |
| 1174 | 1182 | zfcp_dbf_san_req("fssels1", req, d_id); |
| @@ -1575,7 +1583,7 @@ out: · 400 unmodified lines | ||
| 1575 | 1583 | int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) |
| 1576 | 1584 | { |
| 1577 | 1585 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; |
| 1578 | − struct zfcp_fsf_req *req; | |
| 1586 | + struct zfcp_fsf_req *req = NULL; | |
| 1579 | 1587 | int retval = -EIO; |
| 1580 | 1588 | |
| 1581 | 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 | 1612 | zfcp_fsf_req_free(req); |
| 1605 | 1613 | out: |
| 1606 | 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 | 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 | 1638 | int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) |
| 1629 | 1639 | { |
| 1630 | 1640 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; |
| 1631 | − struct zfcp_fsf_req *req; | |
| 1641 | + struct zfcp_fsf_req *req = NULL; | |
| 1632 | 1642 | int retval = -EIO; |
| 1633 | 1643 | |
| 1634 | 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 | 1667 | zfcp_fsf_req_free(req); |
| 1658 | 1668 | out: |
| 1659 | 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 | 1672 | return retval; |
| 1661 | 1673 | } |
| 1662 | 1674 | |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * |
| 4 | 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 | 9 | #ifndef FSF_H |
| @@ -436,6 +436,7 @@ struct zfcp_blk_drv_data { · 426 unmodified lines | ||
| 436 | 436 | * @handler_data: data passed to handler function |
| 437 | 437 | * @port: Optional pointer to port for zfcp internal ELS (only test link ADISC) |
| 438 | 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 | 441 | struct zfcp_fsf_ct_els { |
| 441 | 442 | struct scatterlist *req; |
| @@ -444,6 +445,7 @@ struct zfcp_fsf_ct_els { · 2 unmodified lines | ||
| 444 | 445 | void *handler_data; |
| 445 | 446 | struct zfcp_port *port; |
| 446 | 447 | int status; |
| 448 | + u32 d_id; | |
| 447 | 449 | }; |
| 448 | 450 | |
| 449 | 451 | #endif /* FSF_H */ |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * |
| 4 | 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 | 9 | #define KMSG_COMPONENT "zfcp" |
| @@ -556,6 +556,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) · 546 unmodified lines | ||
| 556 | 556 | ids.port_id = port->d_id; |
| 557 | 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 | 562 | rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); |
| 560 | 563 | if (!rport) { |
| 561 | 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 | 580 | struct fc_rport *rport = port->rport; |
| 578 | 581 | |
| 579 | 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 | 586 | fc_remote_port_delete(rport); |
| 581 | 587 | port->rport = NULL; |
| 582 | 588 | } |
| @@ -396,18 +396,6 @@ config SCSI_3W_SAS · 395 unmodified lines | ||
| 396 | 396 | Please read the comments at the top of |
| 397 | 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 | 399 | config SCSI_ACARD |
| 412 | 400 | tristate "ACARD SCSI support" |
| 413 | 401 | depends on PCI && SCSI |
| @@ -512,18 +500,6 @@ config SCSI_ADVANSYS · 98 unmodified lines | ||
| 512 | 500 | To compile this driver as a module, choose M here: the |
| 513 | 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 | 503 | config SCSI_ARCMSR |
| 528 | 504 | tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" |
| 529 | 505 | depends on PCI && SCSI |
| @@ -540,6 +516,7 @@ config SCSI_ARCMSR · 10 unmodified lines | ||
| 540 | 516 | source "drivers/scsi/esas2r/Kconfig" |
| 541 | 517 | source "drivers/scsi/megaraid/Kconfig.megaraid" |
| 542 | 518 | source "drivers/scsi/mpt3sas/Kconfig" |
| 519 | +source "drivers/scsi/smartpqi/Kconfig" | |
| 543 | 520 | source "drivers/scsi/ufs/Kconfig" |
| 544 | 521 | |
| 545 | 522 | config SCSI_HPTIOP |
| @@ -660,20 +637,6 @@ config SCSI_DMX3191D · 114 unmodified lines | ||
| 660 | 637 | To compile this driver as a module, choose M here: the |
| 661 | 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 | 640 | config SCSI_EATA |
| 678 | 641 | tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support" |
| 679 | 642 | depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API |
| @@ -1248,20 +1211,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT · 568 unmodified lines | ||
| 1248 | 1211 | not allow targets to disconnect is not reasonable if there is more |
| 1249 | 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 | 1214 | config SCSI_QLOGIC_FAS |
| 1266 | 1215 | tristate "Qlogic FAS SCSI support" |
| 1267 | 1216 | depends on ISA && SCSI |
| @@ -1382,89 +1331,6 @@ config SCSI_AM53C974 · 114 unmodified lines | ||
| 1382 | 1331 | To compile this driver as a module, choose M here: the |
| 1383 | 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 | 1334 | config SCSI_NSP32 |
| 1469 | 1335 | tristate "Workbit NinjaSCSI-32Bi/UDE support" |
| 1470 | 1336 | depends on PCI && SCSI && !64BIT |
| @@ -61,9 +61,7 @@ obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o · 60 unmodified lines | ||
| 61 | 61 | obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o |
| 62 | 62 | obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o |
| 63 | 63 | obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o |
| 64 | −obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o | |
| 65 | 64 | obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/ |
| 66 | −obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o | |
| 67 | 65 | obj-$(CONFIG_SCSI_AHA152X) += aha152x.o |
| 68 | 66 | obj-$(CONFIG_SCSI_AHA1542) += aha1542.o |
| 69 | 67 | obj-$(CONFIG_SCSI_AHA1740) += aha1740.o |
| @@ -75,7 +73,6 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/ · 5 unmodified lines | ||
| 75 | 73 | obj-$(CONFIG_SCSI_ISCI) += isci/ |
| 76 | 74 | obj-$(CONFIG_SCSI_IPS) += ips.o |
| 77 | 75 | obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o |
| 78 | −obj-$(CONFIG_SCSI_IN2000) += in2000.o | |
| 79 | 76 | obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o |
| 80 | 77 | obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o |
| 81 | 78 | obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o |
| @@ -90,15 +87,12 @@ obj-$(CONFIG_SCSI_QLA_ISCSI) += libiscsi.o qla4xxx/ · 8 unmodified lines | ||
| 90 | 87 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ |
| 91 | 88 | obj-$(CONFIG_SCSI_BFA_FC) += bfa/ |
| 92 | 89 | obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/ |
| 93 | −obj-$(CONFIG_SCSI_PAS16) += pas16.o | |
| 94 | −obj-$(CONFIG_SCSI_T128) += t128.o | |
| 95 | 90 | obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o |
| 96 | 91 | obj-$(CONFIG_SCSI_HPSA) += hpsa.o |
| 97 | −obj-$(CONFIG_SCSI_DTC3280) += dtc.o | |
| 92 | +obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/ | |
| 98 | 93 | obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ |
| 99 | 94 | obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o |
| 100 | 95 | obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o |
| 101 | −obj-$(CONFIG_SCSI_7000FASST) += wd7000.o | |
| 102 | 96 | obj-$(CONFIG_SCSI_EATA) += eata.o |
| 103 | 97 | obj-$(CONFIG_SCSI_DC395x) += dc395x.o |
| 104 | 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 | 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 | 233 | #if NDEBUG |
| 241 | 234 | static struct { |
| 242 | 235 | unsigned char mask; |
| @@ -1854,11 +1847,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) · 1611 unmodified lines | ||
| 1854 | 1847 | /* XXX - need to source or sink data here, as appropriate */ |
| 1855 | 1848 | } |
| 1856 | 1849 | } else { |
| 1857 | − /* Break up transfer into 3 ms chunks, | |
| 1858 | − * presuming 6 accesses per handshake. | |
| 1850 | + /* Transfer a small chunk so that the | |
| 1851 | + * irq mode lock is not held too long. | |
| 1859 | 1852 | */ |
| 1860 | − transfersize = min((unsigned long)cmd->SCp.this_residual, | |
| 1861 | − hostdata->accesses_per_ms / 2); | |
| 1853 | + transfersize = min(cmd->SCp.this_residual, | |
| 1854 | + NCR5380_PIO_CHUNK_SIZE); | |
| 1862 | 1855 | len = transfersize; |
| 1863 | 1856 | NCR5380_transfer_pio(instance, &phase, &len, |
| 1864 | 1857 | (unsigned char **)&cmd->SCp.ptr); |
| @@ -250,6 +250,8 @@ struct NCR5380_cmd { · 249 unmodified lines | ||
| 250 | 250 | |
| 251 | 251 | #define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd)) |
| 252 | 252 | |
| 253 | +#define NCR5380_PIO_CHUNK_SIZE 256 | |
| 254 | + | |
| 253 | 255 | static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) |
| 254 | 256 | { |
| 255 | 257 | return ((struct scsi_cmnd *)ncmd_ptr) - 1; |
| @@ -292,8 +294,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance); · 36 unmodified lines | ||
| 292 | 294 | static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); |
| 293 | 295 | static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); |
| 294 | 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 | 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 | 306 | #endif /* __KERNEL__ */ |
| 299 | 307 | #endif /* NCR5380_H */ |
| @@ -613,7 +613,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) · 612 unmodified lines | ||
| 613 | 613 | * @dev: Adapter |
| 614 | 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 | 618 | switch (comm) { |
| 619 | 619 | case AAC_COMM_MESSAGE: |
| @@ -632,7 +632,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha) · 631 unmodified lines | ||
| 632 | 632 | pci_name(asd_ha->pcidev)); |
| 633 | 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 | 636 | v | SC_TMR_DIS); |
| 637 | 637 | if (err) { |
| 638 | 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 | 2389 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { |
| 2390 | 2390 | unsigned char *ver_addr; |
| 2391 | − int32_t user_len, cnt2end; | |
| 2391 | + uint32_t user_len; | |
| 2392 | + int32_t cnt2end; | |
| 2392 | 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 | 2401 | ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); |
| 2394 | 2402 | if (!ver_addr) { |
| 2395 | 2403 | retvalue = ARCMSR_MESSAGE_FAIL; |
| 2396 | 2404 | goto message_out; |
| 2397 | 2405 | } |
| 2398 | 2406 | ptmpuserbuffer = ver_addr; |
| 2399 | − user_len = pcmdmessagefld->cmdmessage.Length; | |
| 2407 | + | |
| 2400 | 2408 | memcpy(ptmpuserbuffer, |
| 2401 | 2409 | pcmdmessagefld->messagedatabuffer, user_len); |
| 2402 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -8,7 +8,7 @@ · 2 unmodified lines | ||
| 8 | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | 9 | * |
| 10 | 10 | * Contact Information: |
| 11 | − * linux-drivers@avagotech.com | |
| 11 | + * linux-drivers@broadcom.com | |
| 12 | 12 | * |
| 13 | 13 | * Emulex |
| 14 | 14 | * 3333 Susan Street |
| @@ -89,7 +89,7 @@ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ · 74 unmodified lines | ||
| 89 | 89 | u32 max_eqd; /* in usecs */ |
| 90 | 90 | u32 prev_eqd; /* in usecs */ |
| 91 | 91 | u32 et_eqd; /* configured val when aic is off */ |
| 92 | − ulong jiffs; | |
| 92 | + ulong jiffies; | |
| 93 | 93 | u64 eq_prev; /* Used to calculate eqe */ |
| 94 | 94 | }; |
| 95 | 95 | |
| @@ -100,7 +100,7 @@ struct be_eq_obj { · 4 unmodified lines | ||
| 100 | 100 | struct be_queue_info q; |
| 101 | 101 | struct beiscsi_hba *phba; |
| 102 | 102 | struct be_queue_info *cq; |
| 103 | − struct work_struct work_cqs; /* Work Item */ | |
| 103 | + struct work_struct mcc_work; /* Work Item */ | |
| 104 | 104 | struct irq_poll iopoll; |
| 105 | 105 | }; |
| 106 | 106 | |
| @@ -111,8 +111,11 @@ struct be_mcc_obj { · 4 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | struct beiscsi_mcc_tag_state { |
| 113 | 113 | unsigned long tag_state; |
| 114 | −#define MCC_TAG_STATE_RUNNING 1 | |
| 115 | −#define MCC_TAG_STATE_TIMEOUT 2 | |
| 114 | +#define MCC_TAG_STATE_RUNNING 0 | |
| 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 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -8,7 +8,7 @@ · 2 unmodified lines | ||
| 8 | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | 9 | * |
| 10 | 10 | * Contact Information: |
| 11 | − * linux-drivers@avagotech.com | |
| 11 | + * linux-drivers@broadcom.com | |
| 12 | 12 | * |
| 13 | 13 | * Emulex |
| 14 | 14 | * 3333 Susan Street |
| @@ -21,110 +21,77 @@ · 6 unmodified lines | ||
| 21 | 21 | #include "be.h" |
| 22 | 22 | #include "be_mgmt.h" |
| 23 | 23 | |
| 24 | −int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) | |
| 25 | −{ | |
| 26 | − u32 sreset; | |
| 27 | − u8 *pci_reset_offset = 0; | |
| 28 | − u8 *pci_online0_offset = 0; | |
| 29 | − u8 *pci_online1_offset = 0; | |
| 30 | − u32 pconline0 = 0; | |
| 31 | − u32 pconline1 = 0; | |
| 32 | − u32 i; | |
| 33 | − | |
| 34 | − pci_reset_offset = (u8 *)phba->pci_va + BE2_SOFT_RESET; | |
| 35 | − pci_online0_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE0; | |
| 36 | − pci_online1_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE1; | |
| 37 | − sreset = readl((void *)pci_reset_offset); | |
| 38 | − sreset |= BE2_SET_RESET; | |
| 39 | − writel(sreset, (void *)pci_reset_offset); | |
| 40 | − | |
| 41 | − i = 0; | |
| 42 | − while (sreset & BE2_SET_RESET) { | |
| 43 | − if (i > 64) | |
| 44 | − break; | |
| 45 | − msleep(100); | |
| 46 | − sreset = readl((void *)pci_reset_offset); | |
| 47 | − i++; | |
| 48 | − } | |
| 49 | − | |
| 50 | − if (sreset & BE2_SET_RESET) { | |
| 51 | − printk(KERN_ERR DRV_NAME | |
| 52 | − " Soft Reset did not deassert\n"); | |
| 53 | − return -EIO; | |
| 54 | − } | |
| 55 | − pconline1 = BE2_MPU_IRAM_ONLINE; | |
| 56 | − writel(pconline0, (void *)pci_online0_offset); | |
| 57 | − writel(pconline1, (void *)pci_online1_offset); | |
| 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; | |
| 24 | +/* UE Status Low CSR */ | |
| 25 | +static const char * const desc_ue_status_low[] = { | |
| 26 | + "CEV", | |
| 27 | + "CTX", | |
| 28 | + "DBUF", | |
| 29 | + "ERX", | |
| 30 | + "Host", | |
| 31 | + "MPU", | |
| 32 | + "NDMA", | |
| 33 | + "PTC ", | |
| 34 | + "RDMA ", | |
| 35 | + "RXF ", | |
| 36 | + "RXIPS ", | |
| 37 | + "RXULP0 ", | |
| 38 | + "RXULP1 ", | |
| 39 | + "RXULP2 ", | |
| 40 | + "TIM ", | |
| 41 | + "TPOST ", | |
| 42 | + "TPRE ", | |
| 43 | + "TXIPS ", | |
| 44 | + "TXULP0 ", | |
| 45 | + "TXULP1 ", | |
| 46 | + "UC ", | |
| 47 | + "WDMA ", | |
| 48 | + "TXULP2 ", | |
| 49 | + "HOST1 ", | |
| 50 | + "P0_OB_LINK ", | |
| 51 | + "P1_OB_LINK ", | |
| 52 | + "HOST_GPIO ", | |
| 53 | + "MBOX ", | |
| 54 | + "AXGMAC0", | |
| 55 | + "AXGMAC1", | |
| 56 | + "JTAG", | |
| 57 | + "MPU_INTPEND" | |
| 58 | +}; | |
| 110 | 59 | |
| 111 | − spin_lock(&phba->ctrl.mcc_lock); | |
| 112 | − if (phba->ctrl.mcc_tag_available) { | |
| 113 | − tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; | |
| 114 | − phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; | |
| 115 | − phba->ctrl.mcc_tag_status[tag] = 0; | |
| 116 | − phba->ctrl.ptag_state[tag].tag_state = 0; | |
| 117 | − } | |
| 118 | − if (tag) { | |
| 119 | − phba->ctrl.mcc_tag_available--; | |
| 120 | − if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) | |
| 121 | − phba->ctrl.mcc_alloc_index = 0; | |
| 122 | − else | |
| 123 | − phba->ctrl.mcc_alloc_index++; | |
| 124 | − } | |
| 125 | − spin_unlock(&phba->ctrl.mcc_lock); | |
| 126 | − return tag; | |
| 127 | −} | |
| 60 | +/* UE Status High CSR */ | |
| 61 | +static const char * const desc_ue_status_hi[] = { | |
| 62 | + "LPCMEMHOST", | |
| 63 | + "MGMT_MAC", | |
| 64 | + "PCS0ONLINE", | |
| 65 | + "MPU_IRAM", | |
| 66 | + "PCS1ONLINE", | |
| 67 | + "PCTL0", | |
| 68 | + "PCTL1", | |
| 69 | + "PMEM", | |
| 70 | + "RR", | |
| 71 | + "TXPB", | |
| 72 | + "RXPP", | |
| 73 | + "XAUI", | |
| 74 | + "TXP", | |
| 75 | + "ARM", | |
| 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 | 96 | struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, |
| 130 | 97 | unsigned int *ref_tag) |
| @@ -133,7 +100,7 @@ struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, · 2 unmodified lines | ||
| 133 | 100 | struct be_mcc_wrb *wrb = NULL; |
| 134 | 101 | unsigned int tag; |
| 135 | 102 | |
| 136 | − spin_lock_bh(&phba->ctrl.mcc_lock); | |
| 103 | + spin_lock(&phba->ctrl.mcc_lock); | |
| 137 | 104 | if (mccq->used == mccq->len) { |
| 138 | 105 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | |
| 139 | 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 | 127 | phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; |
| 161 | 128 | phba->ctrl.mcc_tag_status[tag] = 0; |
| 162 | 129 | phba->ctrl.ptag_state[tag].tag_state = 0; |
| 130 | + phba->ctrl.ptag_state[tag].cbfn = NULL; | |
| 163 | 131 | phba->ctrl.mcc_tag_available--; |
| 164 | 132 | if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) |
| 165 | 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 | 142 | mccq->used++; |
| 175 | 143 | |
| 176 | 144 | alloc_failed: |
| 177 | − spin_unlock_bh(&phba->ctrl.mcc_lock); | |
| 145 | + spin_unlock(&phba->ctrl.mcc_lock); | |
| 178 | 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 | 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 | 154 | tag = tag & MCC_Q_CMD_TAG_MASK; |
| 187 | 155 | ctrl->mcc_tag[ctrl->mcc_free_index] = tag; |
| 188 | 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 | 159 | ctrl->mcc_free_index++; |
| 192 | 160 | ctrl->mcc_tag_available++; |
| 193 | 161 | mccq->used--; |
| 194 | − spin_unlock_bh(&ctrl->mcc_lock); | |
| 162 | + spin_unlock(&ctrl->mcc_lock); | |
| 195 | 163 | } |
| 196 | 164 | |
| 197 | −/** | |
| 198 | − * beiscsi_fail_session(): Closing session with appropriate error | |
| 199 | − * @cls_session: ptr to session | |
| 200 | − **/ | |
| 201 | −void beiscsi_fail_session(struct iscsi_cls_session *cls_session) | |
| 165 | +/* | |
| 166 | + * beiscsi_mcc_compl_status - Return the status of MCC completion | |
| 167 | + * @phba: Driver private structure | |
| 168 | + * @tag: Tag for the MBX Command | |
| 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 | 240 | * Failure: Non-Zero |
| 218 | 241 | **/ |
| 219 | 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 | 245 | struct be_dma_mem *mbx_cmd_mem) |
| 222 | 246 | { |
| 223 | 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)) | |
| 232 | − return -EPERM; | |
| 249 | + if (beiscsi_hba_in_error(phba)) { | |
| 250 | + clear_bit(MCC_TAG_STATE_RUNNING, | |
| 251 | + &phba->ctrl.ptag_state[tag].tag_state); | |
| 252 | + return -EIO; | |
| 253 | + } | |
| 233 | 254 | |
| 234 | 255 | /* wait for the mccq completion */ |
| 235 | − rc = wait_event_interruptible_timeout( | |
| 236 | − phba->ctrl.mcc_wait[tag], | |
| 237 | − phba->ctrl.mcc_tag_status[tag], | |
| 238 | − msecs_to_jiffies( | |
| 239 | − BEISCSI_HOST_MBX_TIMEOUT)); | |
| 256 | + rc = wait_event_interruptible_timeout(phba->ctrl.mcc_wait[tag], | |
| 257 | + phba->ctrl.mcc_tag_status[tag], | |
| 258 | + msecs_to_jiffies( | |
| 259 | + 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 | 272 | * If MBOX cmd timeout expired, tag and resource allocated |
| 242 | 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 | 301 | return -EBUSY; |
| 271 | 302 | } |
| 272 | 303 | |
| 273 | − rc = 0; | |
| 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 | − } | |
| 304 | + rc = __beiscsi_mcc_compl_status(phba, tag, wrb, mbx_cmd_mem); | |
| 314 | 305 | |
| 315 | 306 | free_mcc_wrb(&phba->ctrl, tag); |
| 316 | 307 | return rc; |
| @@ -330,11 +321,10 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, · 13 unmodified lines | ||
| 330 | 321 | static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, |
| 331 | 322 | struct be_mcc_compl *compl) |
| 332 | 323 | { |
| 333 | − u16 compl_status, extd_status; | |
| 334 | 324 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 335 | 325 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); |
| 336 | 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 | 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 | 358 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
| 369 | 359 | "BC_%d : error in cmd completion: Subsystem : %d Opcode : %d status(compl/extd)=%d/%d\n", |
| 370 | 360 | hdr->subsystem, hdr->opcode, compl_status, extd_status); |
| 371 | − | |
| 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; | |
| 361 | + return compl_status; | |
| 379 | 362 | } |
| 380 | 363 | |
| 381 | 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 | 374 | * This has been newly introduced in SKH-R Firmware 10.0.338.45. |
| 392 | 375 | **/ |
| 393 | 376 | if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { |
| 394 | − phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT; | |
| 395 | − phba->get_boot = BE_GET_BOOT_RETRIES; | |
| 377 | + set_bit(BEISCSI_HBA_LINK_UP, &phba->state); | |
| 378 | + if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state)) | |
| 379 | + beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE); | |
| 396 | 380 | __beiscsi_log(phba, KERN_ERR, |
| 397 | 381 | "BC_%d : Link Up on Port %d tag 0x%x\n", |
| 398 | 382 | evt->physical_port, evt->event_tag); |
| 399 | 383 | } else { |
| 400 | − phba->state = BE_ADAPTER_LINK_DOWN; | |
| 384 | + clear_bit(BEISCSI_HBA_LINK_UP, &phba->state); | |
| 401 | 385 | __beiscsi_log(phba, KERN_ERR, |
| 402 | 386 | "BC_%d : Link Down on Port %d tag 0x%x\n", |
| 403 | 387 | evt->physical_port, evt->event_tag); |
| 404 | 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 | 466 | beiscsi_process_async_link(phba, compl); |
| 483 | 467 | break; |
| 484 | 468 | case ASYNC_EVENT_CODE_ISCSI: |
| 485 | − phba->state |= BE_ADAPTER_CHECK_BOOT; | |
| 486 | − phba->get_boot = BE_GET_BOOT_RETRIES; | |
| 469 | + if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state)) | |
| 470 | + beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE); | |
| 487 | 471 | sev = KERN_ERR; |
| 488 | 472 | break; |
| 489 | 473 | case ASYNC_EVENT_CODE_SLI: |
| @@ -519,6 +503,9 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, · 29 unmodified lines | ||
| 519 | 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 | 509 | if (test_bit(MCC_TAG_STATE_TIMEOUT, &ctrl->ptag_state[tag].tag_state)) { |
| 523 | 510 | beiscsi_log(phba, KERN_WARNING, |
| 524 | 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 | 516 | * Only for non-embedded cmd, PCI resource is allocated. |
| 530 | 517 | **/ |
| 531 | 518 | tag_mem = &ctrl->ptag_state[tag].tag_mem_state; |
| 532 | − if (tag_mem->size) | |
| 519 | + if (tag_mem->size) { | |
| 533 | 520 | pci_free_consistent(ctrl->pdev, tag_mem->size, |
| 534 | 521 | tag_mem->va, tag_mem->dma); |
| 522 | + tag_mem->size = 0; | |
| 523 | + } | |
| 535 | 524 | free_mcc_wrb(ctrl, tag); |
| 536 | 525 | return 0; |
| 537 | 526 | } |
| @@ -550,57 +539,25 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, · 12 unmodified lines | ||
| 550 | 539 | CQE_STATUS_ADDL_MASK; |
| 551 | 540 | ctrl->mcc_tag_status[tag] |= (compl_status & CQE_STATUS_MASK); |
| 552 | 541 | |
| 553 | − /* write ordering forced in wake_up_interruptible */ | |
| 554 | − clear_bit(MCC_TAG_STATE_RUNNING, &ctrl->ptag_state[tag].tag_state); | |
| 555 | − wake_up_interruptible(&ctrl->mcc_wait[tag]); | |
| 556 | − return 0; | |
| 557 | −} | |
| 558 | − | |
| 559 | −/* | |
| 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); | |
| 542 | + if (test_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state)) { | |
| 543 | + if (ctrl->ptag_state[tag].cbfn) | |
| 544 | + ctrl->ptag_state[tag].cbfn(phba, tag); | |
| 545 | + else | |
| 546 | + __beiscsi_log(phba, KERN_ERR, | |
| 547 | + "BC_%d : MBX ASYNC command with no callback\n"); | |
| 548 | + free_mcc_wrb(ctrl, tag); | |
| 580 | 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); | |
| 587 | − /* after polling, wrb and tag need to be released */ | |
| 588 | − if (!test_bit(MCC_TAG_STATE_RUNNING, | |
| 589 | − &ctrl->ptag_state[tag].tag_state)) { | |
| 590 | − free_mcc_wrb(ctrl, tag); | |
| 591 | − break; | |
| 592 | − } | |
| 593 | − udelay(100); | |
| 594 | − } | |
| 595 | − | |
| 596 | − if (i < mcc_timeout) | |
| 552 | + if (test_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state)) { | |
| 553 | + /* just check completion status and free wrb */ | |
| 554 | + __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); | |
| 555 | + free_mcc_wrb(ctrl, tag); | |
| 597 | 556 | return 0; |
| 557 | + } | |
| 598 | 558 | |
| 599 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | |
| 600 | − "BC_%d : FW Timed Out\n"); | |
| 601 | − phba->fw_timeout = true; | |
| 602 | − beiscsi_ue_detect(phba); | |
| 603 | − return -EBUSY; | |
| 559 | + wake_up_interruptible(&ctrl->mcc_wait[tag]); | |
| 560 | + return 0; | |
| 604 | 561 | } |
| 605 | 562 | |
| 606 | 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 | 600 | timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); |
| 644 | 601 | do { |
| 645 | − if (beiscsi_error(phba)) | |
| 602 | + if (beiscsi_hba_in_error(phba)) | |
| 646 | 603 | return -EIO; |
| 647 | 604 | |
| 648 | 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 | 613 | if (time_after(jiffies, timeout)) |
| 657 | 614 | break; |
| 658 | − msleep(20); | |
| 615 | + /* 1ms sleep is enough in most cases */ | |
| 616 | + schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | |
| 659 | 617 | } while (!ready); |
| 660 | 618 | |
| 661 | 619 | beiscsi_log(phba, KERN_ERR, |
| 662 | 620 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
| 663 | 621 | "BC_%d : FW Timed Out\n"); |
| 664 | − | |
| 665 | − phba->fw_timeout = true; | |
| 666 | − beiscsi_ue_detect(phba); | |
| 667 | − | |
| 622 | + set_bit(BEISCSI_HBA_FW_TIMEOUT, &phba->state); | |
| 668 | 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 | 634 | * Success: 0 |
| 680 | 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 | 639 | int status; |
| 685 | 640 | u32 val = 0; |
| @@ -819,87 +774,6 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, · 133 unmodified lines | ||
| 819 | 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 | 777 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, |
| 904 | 778 | struct be_queue_info *cq, struct be_queue_info *eq, |
| 905 | 779 | bool sol_evts, bool no_delay, int coalesce_wm) |
| @@ -1343,25 +1217,6 @@ error: · 437 unmodified lines | ||
| 1343 | 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 | 1221 | * be_cmd_set_vlan()- Configure VLAN paramters on the adapter |
| 1367 | 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 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -8,7 +8,7 @@ · 2 unmodified lines | ||
| 8 | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | 9 | * |
| 10 | 10 | * Contact Information: |
| 11 | − * linux-drivers@avagotech.com | |
| 11 | + * linux-drivers@broadcom.com | |
| 12 | 12 | * |
| 13 | 13 | * Emulex |
| 14 | 14 | * 3333 Susan Street |
| @@ -57,6 +57,7 @@ struct be_mcc_wrb { · 42 unmodified lines | ||
| 57 | 57 | #define MCC_STATUS_ILLEGAL_REQUEST 0x2 |
| 58 | 58 | #define MCC_STATUS_ILLEGAL_FIELD 0x3 |
| 59 | 59 | #define MCC_STATUS_INSUFFICIENT_BUFFER 0x4 |
| 60 | +#define MCC_STATUS_INVALID_LENGTH 0x74 | |
| 60 | 61 | |
| 61 | 62 | #define CQE_STATUS_COMPL_MASK 0xFFFF |
| 62 | 63 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ |
| @@ -97,11 +98,23 @@ struct be_mcc_compl { · 34 unmodified lines | ||
| 97 | 98 | #define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ |
| 98 | 99 | #define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ |
| 99 | 100 | |
| 100 | −/********** MPU semphore ******************/ | |
| 101 | −#define MPU_EP_SEMAPHORE_OFFSET 0xac | |
| 102 | −#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF | |
| 103 | −#define EP_SEMAPHORE_POST_ERR_MASK 0x1 | |
| 104 | −#define EP_SEMAPHORE_POST_ERR_SHIFT 31 | |
| 101 | +/********** MPU semphore: used for SH & BE ******************/ | |
| 102 | +#define SLIPORT_SOFTRESET_OFFSET 0x5c /* CSR BAR offset */ | |
| 103 | +#define SLIPORT_SEMAPHORE_OFFSET_BEx 0xac /* CSR BAR offset */ | |
| 104 | +#define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 /* PCI-CFG offset */ | |
| 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 | 119 | /********** MCC door bell ************/ |
| 107 | 120 | #define DB_MCCQ_OFFSET 0x140 |
| @@ -109,9 +122,6 @@ struct be_mcc_compl { · 1 unmodified line | ||
| 109 | 122 | /* Number of entries posted */ |
| 110 | 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 | 126 | * When the async bit of mcc_compl is set, the last 4 bytes of |
| 117 | 127 | * mcc_compl is interpreted as follows: |
| @@ -217,6 +227,7 @@ struct be_mcc_mailbox { · 99 unmodified lines | ||
| 217 | 227 | #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 |
| 218 | 228 | #define OPCODE_COMMON_FUNCTION_RESET 61 |
| 219 | 229 | #define OPCODE_COMMON_GET_PORT_NAME 77 |
| 230 | +#define OPCODE_COMMON_SET_FEATURES 191 | |
| 220 | 231 | |
| 221 | 232 | /** |
| 222 | 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 | 357 | struct be_cmd_resp_logout_fw_sess { |
| 347 | 358 | struct be_cmd_resp_hdr hdr; /* dw[4] */ |
| 348 | −#define BEISCSI_MGMT_SESSION_CLOSE 0x20 | |
| 349 | 359 | uint32_t session_status; |
| 360 | +#define BE_SESS_STATUS_CLOSE 0x20 | |
| 350 | 361 | } __packed; |
| 351 | 362 | |
| 352 | 363 | struct mgmt_conn_login_options { |
| @@ -365,6 +376,14 @@ struct ip_addr_format { · 12 unmodified lines | ||
| 365 | 376 | u16 size_of_structure; |
| 366 | 377 | u8 reserved; |
| 367 | 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 | 387 | u8 addr[16]; |
| 369 | 388 | u32 rsvd0; |
| 370 | 389 | } __packed; |
| @@ -430,8 +449,13 @@ struct be_cmd_get_boot_target_req { · 59 unmodified lines | ||
| 430 | 449 | |
| 431 | 450 | struct be_cmd_get_boot_target_resp { |
| 432 | 451 | struct be_cmd_resp_hdr hdr; |
| 433 | − u32 boot_session_count; | |
| 434 | − int boot_session_handle; | |
| 452 | + u32 boot_session_count; | |
| 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 | 461 | struct be_cmd_reopen_session_req { |
| @@ -699,16 +723,59 @@ struct be_cmd_get_nic_conf_resp { · 261 unmodified lines | ||
| 699 | 723 | u8 mac_address[ETH_ALEN]; |
| 700 | 724 | } __packed; |
| 701 | 725 | |
| 702 | −#define BEISCSI_ALIAS_LEN 32 | |
| 726 | +/******************** Get HBA NAME *******************/ | |
| 703 | 727 | |
| 704 | 728 | struct be_cmd_hba_name { |
| 705 | 729 | struct be_cmd_req_hdr hdr; |
| 706 | 730 | u16 flags; |
| 707 | 731 | u16 rsvd0; |
| 708 | 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 | 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 | 779 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, |
| 713 | 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 | 790 | struct be_queue_info *mccq, |
| 724 | 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 | 793 | unsigned int be_cmd_get_initname(struct beiscsi_hba *phba); |
| 730 | 794 | |
| 731 | 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 | 798 | int num); |
| 735 | 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 | 802 | struct be_dma_mem *mbx_cmd_mem); |
| 738 | −/*ISCSI Functuions */ | |
| 739 | −int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | |
| 740 | −int be_cmd_fw_uninit(struct be_ctrl_info *ctrl); | |
| 741 | − | |
| 803 | +int __beiscsi_mcc_compl_status(struct beiscsi_hba *phba, | |
| 804 | + unsigned int tag, | |
| 805 | + struct be_mcc_wrb **wrb, | |
| 806 | + struct be_dma_mem *mbx_cmd_mem); | |
| 742 | 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 | 808 | void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag); |
| 745 | 809 | struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, |
| 746 | 810 | unsigned int *ref_tag); |
| @@ -749,9 +813,6 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, · 2 unmodified lines | ||
| 749 | 813 | int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, |
| 750 | 814 | struct be_mcc_compl *compl); |
| 751 | 815 | |
| 752 | − | |
| 753 | −int be_mbox_notify(struct be_ctrl_info *ctrl); | |
| 754 | − | |
| 755 | 816 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, |
| 756 | 817 | struct be_queue_info *cq, |
| 757 | 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 | 828 | struct be_dma_mem *q_mem, u32 page_offset, |
| 768 | 829 | u32 num_pages); |
| 769 | 830 | |
| 770 | −int beiscsi_cmd_reset_function(struct beiscsi_hba *phba); | |
| 771 | − | |
| 772 | 831 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, |
| 773 | 832 | struct be_queue_info *wrbq, |
| 774 | 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 | 836 | /* Configuration Functions */ |
| 778 | 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 | 848 | struct be_default_pdu_context { |
| 781 | 849 | u32 dw[4]; |
| 782 | 850 | } __packed; |
| @@ -999,7 +1067,16 @@ struct iscsi_cleanup_req { · 216 unmodified lines | ||
| 999 | 1067 | u16 chute; |
| 1000 | 1068 | u8 hdr_ring_id; |
| 1001 | 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 | 1080 | } __packed; |
| 1004 | 1081 | |
| 1005 | 1082 | struct eq_delay { |
| @@ -1368,14 +1445,9 @@ struct be_cmd_get_port_name { · 362 unmodified lines | ||
| 1368 | 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 | 1448 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, |
| 1375 | 1449 | bool embedded, u8 sge_cnt); |
| 1376 | 1450 | |
| 1377 | 1451 | void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, |
| 1378 | 1452 | u8 subsystem, u8 opcode, int cmd_len); |
| 1379 | − | |
| 1380 | −void beiscsi_fail_session(struct iscsi_cls_session *cls_session); | |
| 1381 | 1453 | #endif /* !BEISCSI_CMDS_H */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /** |
| 2 | − * Copyright (C) 2005 - 2015 Emulex | |
| 2 | + * Copyright (C) 2005 - 2016 Broadcom | |
| 3 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | ||
| 7 | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | 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 | 12 | * Contact Information: |
| 13 | − * linux-drivers@avagotech.com | |
| 13 | + * linux-drivers@broadcom.com | |
| 14 | 14 | * |
| 15 | 15 | * Emulex |
| 16 | 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 | 54 | if (!ep) { |
| 55 | − printk(KERN_ERR | |
| 56 | − "beiscsi_session_create: invalid ep\n"); | |
| 55 | + pr_err("beiscsi_session_create: invalid ep\n"); | |
| 57 | 56 | return NULL; |
| 58 | 57 | } |
| 59 | 58 | beiscsi_ep = ep->dd_data; |
| 60 | 59 | phba = beiscsi_ep->phba; |
| 61 | 60 | |
| 62 | − if (phba->state & BE_ADAPTER_PCI_ERR) { | |
| 63 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 64 | − "BS_%d : PCI_ERROR Recovery\n"); | |
| 65 | − return NULL; | |
| 66 | − } else { | |
| 61 | + if (!beiscsi_hba_is_online(phba)) { | |
| 67 | 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 | 69 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { |
| 72 | 70 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 73 | 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 | 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 | 131 | * beiscsi_conn_create - create an instance of iscsi connection |
| 124 | 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 | 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 | 250 | if (phba->ipv4_iface) |
| 243 | 251 | return 0; |
| @@ -256,7 +264,7 @@ static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba) · 12 unmodified lines | ||
| 256 | 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 | 269 | if (phba->ipv6_iface) |
| 262 | 270 | return 0; |
| @@ -275,79 +283,31 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) · 12 unmodified lines | ||
| 275 | 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 | 288 | struct be_cmd_get_if_info_resp *if_info; |
| 281 | 289 | |
| 282 | − if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) { | |
| 283 | − beiscsi_create_ipv4_iface(phba); | |
| 290 | + if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) { | |
| 291 | + beiscsi_iface_create_ipv4(phba); | |
| 284 | 292 | kfree(if_info); |
| 285 | 293 | } |
| 286 | 294 | |
| 287 | − if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) { | |
| 288 | − beiscsi_create_ipv6_iface(phba); | |
| 295 | + if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) { | |
| 296 | + beiscsi_iface_create_ipv6(phba); | |
| 289 | 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 | 304 | iscsi_destroy_iface(phba->ipv6_iface); |
| 297 | − if (phba->ipv4_iface) | |
| 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); | |
| 305 | + phba->ipv6_iface = NULL; | |
| 339 | 306 | } |
| 340 | − | |
| 341 | − if (!iface_ip || !iface_subnet) { | |
| 342 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 343 | − "BS_%d : IP and Subnet Mask required\n"); | |
| 344 | − return -EINVAL; | |
| 307 | + if (phba->ipv4_iface) { | |
| 308 | + iscsi_destroy_iface(phba->ipv4_iface); | |
| 309 | + phba->ipv4_iface = NULL; | |
| 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 | 323 | * Failure: Non-Zero Value |
| 364 | 324 | **/ |
| 365 | 325 | static int |
| 366 | −beiscsi_set_vlan_tag(struct Scsi_Host *shost, | |
| 367 | − struct iscsi_iface_param_info *iface_param) | |
| 326 | +beiscsi_iface_config_vlan(struct Scsi_Host *shost, | |
| 327 | + struct iscsi_iface_param_info *iface_param) | |
| 368 | 328 | { |
| 369 | 329 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 370 | − int ret; | |
| 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 | − } | |
| 330 | + int ret = -EPERM; | |
| 379 | 331 | |
| 380 | 332 | switch (iface_param->param) { |
| 381 | 333 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 334 | + ret = 0; | |
| 382 | 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 | 337 | break; |
| 385 | 338 | case ISCSI_NET_PARAM_VLAN_TAG: |
| 386 | − ret = mgmt_set_vlan(phba, | |
| 387 | − *((uint16_t *)iface_param->value)); | |
| 339 | + ret = beiscsi_if_set_vlan(phba, | |
| 340 | + *((uint16_t *)iface_param->value)); | |
| 388 | 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 | 343 | return ret; |
| 396 | 344 | } |
| 397 | 345 | |
| 398 | 346 | |
| 399 | 347 | static int |
| 400 | −beiscsi_set_ipv4(struct Scsi_Host *shost, | |
| 401 | − struct iscsi_iface_param_info *iface_param, | |
| 402 | − void *data, uint32_t dt_len) | |
| 348 | +beiscsi_iface_config_ipv4(struct Scsi_Host *shost, | |
| 349 | + struct iscsi_iface_param_info *info, | |
| 350 | + void *data, uint32_t dt_len) | |
| 403 | 351 | { |
| 404 | 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 | 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 | 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 | 370 | break; |
| 412 | 371 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: |
| 413 | − if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP) | |
| 414 | − ret = mgmt_set_ip(phba, iface_param, | |
| 415 | − NULL, ISCSI_BOOTPROTO_DHCP); | |
| 416 | − else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC) | |
| 417 | − ret = beiscsi_set_static_ip(shost, iface_param, | |
| 418 | − data, dt_len); | |
| 372 | + if (info->value[0] == ISCSI_BOOTPROTO_DHCP) | |
| 373 | + ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4); | |
| 374 | + else if (info->value[0] == ISCSI_BOOTPROTO_STATIC) | |
| 375 | + /* release DHCP IP address */ | |
| 376 | + ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, | |
| 377 | + NULL, NULL); | |
| 419 | 378 | else |
| 420 | 379 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 421 | 380 | "BS_%d : Invalid BOOTPROTO: %d\n", |
| 422 | − iface_param->value[0]); | |
| 381 | + info->value[0]); | |
| 423 | 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 | 383 | case ISCSI_NET_PARAM_IPV4_ADDR: |
| 432 | − ret = beiscsi_set_static_ip(shost, iface_param, | |
| 433 | − data, dt_len); | |
| 384 | + ip = info->value; | |
| 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 | 392 | break; |
| 435 | − case ISCSI_NET_PARAM_VLAN_ENABLED: | |
| 436 | − case ISCSI_NET_PARAM_VLAN_TAG: | |
| 437 | − ret = beiscsi_set_vlan_tag(shost, iface_param); | |
| 393 | + case ISCSI_NET_PARAM_IPV4_SUBNET: | |
| 394 | + /* | |
| 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 | 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 | 409 | return ret; |
| 446 | 410 | } |
| 447 | 411 | |
| 448 | 412 | static int |
| 449 | −beiscsi_set_ipv6(struct Scsi_Host *shost, | |
| 450 | − struct iscsi_iface_param_info *iface_param, | |
| 451 | − void *data, uint32_t dt_len) | |
| 413 | +beiscsi_iface_config_ipv6(struct Scsi_Host *shost, | |
| 414 | + struct iscsi_iface_param_info *iface_param, | |
| 415 | + void *data, uint32_t dt_len) | |
| 452 | 416 | { |
| 453 | 417 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 454 | − int ret = 0; | |
| 418 | + int ret = -EPERM; | |
| 455 | 419 | |
| 456 | 420 | switch (iface_param->param) { |
| 457 | 421 | case ISCSI_NET_PARAM_IFACE_ENABLE: |
| 458 | 422 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) |
| 459 | − ret = beiscsi_create_ipv6_iface(phba); | |
| 423 | + ret = beiscsi_iface_create_ipv6(phba); | |
| 460 | 424 | else { |
| 461 | 425 | iscsi_destroy_iface(phba->ipv6_iface); |
| 462 | − ret = 0; | |
| 426 | + phba->ipv6_iface = NULL; | |
| 463 | 427 | } |
| 464 | 428 | break; |
| 465 | 429 | case ISCSI_NET_PARAM_IPV6_ADDR: |
| 466 | − ret = mgmt_set_ip(phba, iface_param, NULL, | |
| 467 | − ISCSI_BOOTPROTO_STATIC); | |
| 430 | + ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6, | |
| 431 | + iface_param->value, NULL); | |
| 468 | 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 | 435 | return ret; |
| 480 | 436 | } |
| 481 | 437 | |
| 482 | −int be2iscsi_iface_set_param(struct Scsi_Host *shost, | |
| 483 | − void *data, uint32_t dt_len) | |
| 438 | +int beiscsi_iface_set_param(struct Scsi_Host *shost, | |
| 439 | + void *data, uint32_t dt_len) | |
| 484 | 440 | { |
| 485 | 441 | struct iscsi_iface_param_info *iface_param = NULL; |
| 486 | 442 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 487 | 443 | struct nlattr *attrib; |
| 488 | 444 | uint32_t rm_len = dt_len; |
| 489 | − int ret = 0 ; | |
| 445 | + int ret; | |
| 490 | 446 | |
| 491 | − if (phba->state & BE_ADAPTER_PCI_ERR) { | |
| 492 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 493 | − "BS_%d : In PCI_ERROR Recovery\n"); | |
| 447 | + if (!beiscsi_hba_is_online(phba)) { | |
| 448 | + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 449 | + "BS_%d : HBA in error 0x%lx\n", phba->state); | |
| 494 | 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 | 461 | nla_for_each_attr(attrib, data, dt_len, rm_len) { |
| 498 | 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 | 476 | return -EINVAL; |
| 513 | 477 | } |
| 514 | 478 | |
| 515 | − switch (iface_param->iface_type) { | |
| 516 | − case ISCSI_IFACE_TYPE_IPV4: | |
| 517 | − ret = beiscsi_set_ipv4(shost, iface_param, | |
| 518 | − data, dt_len); | |
| 519 | − break; | |
| 520 | − case ISCSI_IFACE_TYPE_IPV6: | |
| 521 | − ret = beiscsi_set_ipv6(shost, iface_param, | |
| 522 | − data, dt_len); | |
| 479 | + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 480 | + "BS_%d : %s.0 set param %d", | |
| 481 | + (iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ? | |
| 482 | + "ipv4" : "ipv6", iface_param->param); | |
| 483 | + | |
| 484 | + ret = -EPERM; | |
| 485 | + switch (iface_param->param) { | |
| 486 | + case ISCSI_NET_PARAM_VLAN_ENABLED: | |
| 487 | + case ISCSI_NET_PARAM_VLAN_TAG: | |
| 488 | + ret = beiscsi_iface_config_vlan(shost, iface_param); | |
| 523 | 489 | break; |
| 524 | 490 | default: |
| 525 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 526 | − "BS_%d : Invalid iface type :%d passed\n", | |
| 527 | − iface_param->iface_type); | |
| 528 | − break; | |
| 491 | + switch (iface_param->iface_type) { | |
| 492 | + case ISCSI_IFACE_TYPE_IPV4: | |
| 493 | + ret = beiscsi_iface_config_ipv4(shost, | |
| 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 | 513 | if (ret) |
| 532 | − return ret; | |
| 514 | + break; | |
| 533 | 515 | } |
| 534 | 516 | |
| 535 | 517 | return ret; |
| 536 | 518 | } |
| 537 | 519 | |
| 538 | −static int be2iscsi_get_if_param(struct beiscsi_hba *phba, | |
| 539 | − struct iscsi_iface *iface, int param, | |
| 540 | − char *buf) | |
| 520 | +static int __beiscsi_iface_get_param(struct beiscsi_hba *phba, | |
| 521 | + struct iscsi_iface *iface, | |
| 522 | + int param, char *buf) | |
| 541 | 523 | { |
| 542 | 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 | 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 | 531 | if (len) |
| 550 | 532 | return len; |
| 551 | 533 | |
| @@ -567,24 +549,24 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, · 15 unmodified lines | ||
| 567 | 549 | break; |
| 568 | 550 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 569 | 551 | len = sprintf(buf, "%s\n", |
| 570 | − (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) | |
| 571 | − ? "Disabled\n" : "Enabled\n"); | |
| 552 | + (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ? | |
| 553 | + "disable" : "enable"); | |
| 572 | 554 | break; |
| 573 | 555 | case ISCSI_NET_PARAM_VLAN_ID: |
| 574 | 556 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
| 575 | 557 | len = -EINVAL; |
| 576 | 558 | else |
| 577 | 559 | len = sprintf(buf, "%d\n", |
| 578 | − (if_info->vlan_priority & | |
| 579 | − ISCSI_MAX_VLAN_ID)); | |
| 560 | + (if_info->vlan_priority & | |
| 561 | + ISCSI_MAX_VLAN_ID)); | |
| 580 | 562 | break; |
| 581 | 563 | case ISCSI_NET_PARAM_VLAN_PRIORITY: |
| 582 | 564 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
| 583 | 565 | len = -EINVAL; |
| 584 | 566 | else |
| 585 | 567 | len = sprintf(buf, "%d\n", |
| 586 | − ((if_info->vlan_priority >> 13) & | |
| 587 | − ISCSI_MAX_VLAN_PRIORITY)); | |
| 568 | + ((if_info->vlan_priority >> 13) & | |
| 569 | + ISCSI_MAX_VLAN_PRIORITY)); | |
| 588 | 570 | break; |
| 589 | 571 | default: |
| 590 | 572 | WARN_ON(1); |
| @@ -594,18 +576,20 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, · 3 unmodified lines | ||
| 594 | 576 | return len; |
| 595 | 577 | } |
| 596 | 578 | |
| 597 | −int be2iscsi_iface_get_param(struct iscsi_iface *iface, | |
| 598 | − enum iscsi_param_type param_type, | |
| 599 | − int param, char *buf) | |
| 579 | +int beiscsi_iface_get_param(struct iscsi_iface *iface, | |
| 580 | + enum iscsi_param_type param_type, | |
| 581 | + int param, char *buf) | |
| 600 | 582 | { |
| 601 | 583 | struct Scsi_Host *shost = iscsi_iface_to_shost(iface); |
| 602 | 584 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 603 | 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) { | |
| 607 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 608 | − "BS_%d : In PCI_ERROR Recovery\n"); | |
| 588 | + if (param_type != ISCSI_NET_PARAM) | |
| 589 | + return 0; | |
| 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 | 593 | return -EBUSY; |
| 610 | 594 | } |
| 611 | 595 | |
| @@ -617,19 +601,22 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, · 5 unmodified lines | ||
| 617 | 601 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 618 | 602 | case ISCSI_NET_PARAM_VLAN_ID: |
| 619 | 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 | 605 | break; |
| 622 | 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 | 613 | break; |
| 625 | 614 | case ISCSI_NET_PARAM_IPV4_GW: |
| 626 | 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 | 617 | if (!len) |
| 629 | 618 | len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr); |
| 630 | 619 | break; |
| 631 | − default: | |
| 632 | − len = -ENOSYS; | |
| 633 | 620 | } |
| 634 | 621 | |
| 635 | 622 | return len; |
| @@ -647,7 +634,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep, · 11 unmodified lines | ||
| 647 | 634 | enum iscsi_param param, char *buf) |
| 648 | 635 | { |
| 649 | 636 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; |
| 650 | − int len = 0; | |
| 637 | + int len; | |
| 651 | 638 | |
| 652 | 639 | beiscsi_log(beiscsi_ep->phba, KERN_INFO, |
| 653 | 640 | BEISCSI_LOG_CONFIG, |
| @@ -659,13 +646,13 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep, · 5 unmodified lines | ||
| 659 | 646 | len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); |
| 660 | 647 | break; |
| 661 | 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 | 650 | len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); |
| 664 | 651 | else |
| 665 | 652 | len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); |
| 666 | 653 | break; |
| 667 | 654 | default: |
| 668 | − return -ENOSYS; | |
| 655 | + len = -EPERM; | |
| 669 | 656 | } |
| 670 | 657 | return len; |
| 671 | 658 | } |
| @@ -758,7 +745,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) · 86 unmodified lines | ||
| 758 | 745 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 759 | 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 | 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 | 797 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 811 | 798 | int status = 0; |
| 812 | 799 | |
| 813 | − | |
| 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 { | |
| 800 | + if (!beiscsi_hba_is_online(phba)) { | |
| 819 | 801 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 820 | − "BS_%d : In beiscsi_get_host_param," | |
| 821 | − " param = %d\n", param); | |
| 802 | + "BS_%d : HBA in error 0x%lx\n", phba->state); | |
| 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 | 808 | switch (param) { |
| 825 | 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 | 946 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; |
| 963 | 947 | |
| 964 | − if (phba->state & BE_ADAPTER_PCI_ERR) { | |
| 965 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 966 | − "BS_%d : In PCI_ERROR Recovery\n"); | |
| 948 | + if (!beiscsi_hba_is_online(phba)) { | |
| 949 | + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 950 | + "BS_%d : HBA in error 0x%lx\n", phba->state); | |
| 967 | 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 | 956 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); |
| 975 | 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 | 1168 | struct iscsi_endpoint *ep; |
| 1187 | 1169 | int ret; |
| 1188 | 1170 | |
| 1189 | − if (shost) | |
| 1190 | − phba = iscsi_host_priv(shost); | |
| 1191 | − else { | |
| 1171 | + if (!shost) { | |
| 1192 | 1172 | ret = -ENXIO; |
| 1193 | − printk(KERN_ERR | |
| 1194 | − "beiscsi_ep_connect shost is NULL\n"); | |
| 1173 | + pr_err("beiscsi_ep_connect shost is NULL\n"); | |
| 1195 | 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 | 1179 | ret = -EIO; |
| 1200 | − beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
| 1201 | − "BS_%d : The FW state Not Stable!!!\n"); | |
| 1180 | + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 1181 | + "BS_%d : HBA in error 0x%lx\n", phba->state); | |
| 1202 | 1182 | return ERR_PTR(ret); |
| 1203 | 1183 | } |
| 1204 | − | |
| 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) { | |
| 1184 | + if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) { | |
| 1211 | 1185 | ret = -EBUSY; |
| 1212 | 1186 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1213 | 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 | 1335 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; |
| 1362 | 1336 | } |
| 1363 | 1337 | |
| 1364 | − if (phba->state & BE_ADAPTER_PCI_ERR) { | |
| 1365 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | |
| 1366 | − "BS_%d : PCI_ERROR Recovery\n"); | |
| 1338 | + if (!beiscsi_hba_is_online(phba)) { | |
| 1339 | + beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | |
| 1340 | + "BS_%d : HBA in error 0x%lx\n", phba->state); | |
| 1367 | 1341 | goto free_ep; |
| 1368 | 1342 | } |
| 1369 | 1343 | |
| @@ -1386,7 +1360,7 @@ free_ep: · 16 unmodified lines | ||
| 1386 | 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 | 1365 | switch (param_type) { |
| 1392 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | ||
| 7 | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | 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 | 12 | * Contact Information: |
| 13 | − * linux-drivers@avagotech.com | |
| 13 | + * linux-drivers@broadcom.com | |
| 14 | 14 | * |
| 15 | 15 | * Avago Technologies |
| 16 | 16 | * 3333 Susan Street |
| @@ -23,25 +23,18 @@ · 6 unmodified lines | ||
| 23 | 23 | #include "be_main.h" |
| 24 | 24 | #include "be_mgmt.h" |
| 25 | 25 | |
| 26 | −#define BE2_IPV4 0x1 | |
| 27 | −#define BE2_IPV6 0x10 | |
| 28 | −#define BE2_DHCP_V4 0x05 | |
| 26 | +void beiscsi_iface_create_default(struct beiscsi_hba *phba); | |
| 29 | 27 | |
| 30 | −#define NON_BLOCKING 0x0 | |
| 31 | −#define BLOCKING 0x1 | |
| 28 | +void beiscsi_iface_destroy_default(struct beiscsi_hba *phba); | |
| 32 | 29 | |
| 33 | −void beiscsi_create_def_ifaces(struct beiscsi_hba *phba); | |
| 34 | − | |
| 35 | −void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba); | |
| 36 | − | |
| 37 | −int be2iscsi_iface_get_param(struct iscsi_iface *iface, | |
| 30 | +int beiscsi_iface_get_param(struct iscsi_iface *iface, | |
| 38 | 31 | enum iscsi_param_type param_type, |
| 39 | 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 | 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 | 39 | void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, |
| 47 | 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 | 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 | 55 | struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session |
| 61 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | ||
| 7 | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | 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 | 12 | * Contact Information: |
| 13 | − * linux-drivers@avagotech.com | |
| 13 | + * linux-drivers@broadcom.com | |
| 14 | 14 | * |
| 15 | 15 | * Emulex |
| 16 | 16 | * 3333 Susan Street |
| @@ -374,170 +374,6 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) · 357 unmodified lines | ||
| 374 | 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 | 377 | /*------------------- PCI Driver operations and data ----------------- */ |
| 542 | 378 | static const struct pci_device_id beiscsi_pci_id_table[] = { |
| 543 | 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 | 686 | static irqreturn_t be_isr_mcc(int irq, void *dev_id) |
| 851 | 687 | { |
| 852 | 688 | struct beiscsi_hba *phba; |
| 853 | − struct be_eq_entry *eqe = NULL; | |
| 689 | + struct be_eq_entry *eqe; | |
| 854 | 690 | struct be_queue_info *eq; |
| 855 | 691 | struct be_queue_info *mcc; |
| 856 | − unsigned int num_eq_processed; | |
| 692 | + unsigned int mcc_events; | |
| 857 | 693 | struct be_eq_obj *pbe_eq; |
| 858 | − unsigned long flags; | |
| 859 | 694 | |
| 860 | 695 | pbe_eq = dev_id; |
| 861 | 696 | eq = &pbe_eq->q; |
| @@ -863,27 +698,23 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) · 1 unmodified line | ||
| 863 | 698 | mcc = &phba->ctrl.mcc_obj.cq; |
| 864 | 699 | eqe = queue_tail_node(eq); |
| 865 | 700 | |
| 866 | − num_eq_processed = 0; | |
| 867 | − | |
| 701 | + mcc_events = 0; | |
| 868 | 702 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
| 869 | 703 | & EQE_VALID_MASK) { |
| 870 | 704 | if (((eqe->dw[offsetof(struct amap_eq_entry, |
| 871 | 705 | resource_id) / 32] & |
| 872 | 706 | EQE_RESID_MASK) >> 16) == mcc->id) { |
| 873 | − spin_lock_irqsave(&phba->isr_lock, flags); | |
| 874 | − pbe_eq->todo_mcc_cq = true; | |
| 875 | − spin_unlock_irqrestore(&phba->isr_lock, flags); | |
| 707 | + mcc_events++; | |
| 876 | 708 | } |
| 877 | 709 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
| 878 | 710 | queue_tail_inc(eq); |
| 879 | 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 | 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 | 733 | eq = &pbe_eq->q; |
| 903 | 734 | |
| 904 | 735 | phba = pbe_eq->phba; |
| 905 | − | |
| 906 | 736 | /* disable interrupt till iopoll completes */ |
| 907 | 737 | hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); |
| 908 | 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 | 750 | struct beiscsi_hba *phba; |
| 921 | 751 | struct hwi_controller *phwi_ctrlr; |
| 922 | 752 | struct hwi_context_memory *phwi_context; |
| 923 | − struct be_eq_entry *eqe = NULL; | |
| 753 | + struct be_eq_entry *eqe; | |
| 924 | 754 | struct be_queue_info *eq; |
| 925 | 755 | struct be_queue_info *mcc; |
| 926 | − unsigned long flags, index; | |
| 927 | − unsigned int num_mcceq_processed, num_ioeq_processed; | |
| 756 | + unsigned int mcc_events, io_events; | |
| 928 | 757 | struct be_ctrl_info *ctrl; |
| 929 | 758 | struct be_eq_obj *pbe_eq; |
| 930 | − int isr; | |
| 759 | + int isr, rearm; | |
| 931 | 760 | |
| 932 | 761 | phba = dev_id; |
| 933 | 762 | ctrl = &phba->ctrl; |
| @@ -942,44 +771,35 @@ static irqreturn_t be_isr(int irq, void *dev_id) · 8 unmodified lines | ||
| 942 | 771 | |
| 943 | 772 | eq = &phwi_context->be_eq[0].q; |
| 944 | 773 | mcc = &phba->ctrl.mcc_obj.cq; |
| 945 | − index = 0; | |
| 946 | 774 | eqe = queue_tail_node(eq); |
| 947 | 775 | |
| 948 | − num_ioeq_processed = 0; | |
| 949 | − num_mcceq_processed = 0; | |
| 776 | + io_events = 0; | |
| 777 | + mcc_events = 0; | |
| 950 | 778 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
| 951 | 779 | & EQE_VALID_MASK) { |
| 952 | 780 | if (((eqe->dw[offsetof(struct amap_eq_entry, |
| 953 | − resource_id) / 32] & | |
| 954 | − EQE_RESID_MASK) >> 16) == mcc->id) { | |
| 955 | − spin_lock_irqsave(&phba->isr_lock, flags); | |
| 956 | − pbe_eq->todo_mcc_cq = true; | |
| 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 | − } | |
| 781 | + resource_id) / 32] & EQE_RESID_MASK) >> 16) == mcc->id) | |
| 782 | + mcc_events++; | |
| 783 | + else | |
| 784 | + io_events++; | |
| 963 | 785 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
| 964 | 786 | queue_tail_inc(eq); |
| 965 | 787 | eqe = queue_tail_node(eq); |
| 966 | 788 | } |
| 967 | − if (num_ioeq_processed || num_mcceq_processed) { | |
| 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 | |
| 789 | + if (!io_events && !mcc_events) | |
| 982 | 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 | 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 | 900 | static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) |
| 1132 | 901 | { |
| 1133 | 902 | struct sgl_handle *psgl_handle; |
| @@ -1199,6 +968,9 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, · 65 unmodified lines | ||
| 1199 | 968 | pwrb_context->alloc_index++; |
| 1200 | 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 | 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 | 1212 | struct beiscsi_hba *phba, struct sol_cqe *psol) |
| 1441 | 1213 | { |
| 1442 | 1214 | struct hwi_wrb_context *pwrb_context; |
| 1443 | − struct wrb_handle *pwrb_handle = NULL; | |
| 1215 | + uint16_t wrb_index, cid, cri_index; | |
| 1444 | 1216 | struct hwi_controller *phwi_ctrlr; |
| 1217 | + struct wrb_handle *pwrb_handle; | |
| 1445 | 1218 | struct iscsi_task *task; |
| 1446 | − struct beiscsi_io_task *io_task; | |
| 1447 | − uint16_t wrb_index, cid, cri_index; | |
| 1448 | 1219 | |
| 1449 | 1220 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1450 | 1221 | if (is_chip_be2_be3r(phba)) { |
| @@ -1463,9 +1234,6 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, · 12 unmodified lines | ||
| 1463 | 1234 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1464 | 1235 | pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; |
| 1465 | 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 | 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 | 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 | |
| 1618 | − *pasync_ctx, unsigned int is_header, | |
| 1619 | − unsigned int host_write_ptr) | |
| 1385 | +/** | |
| 1386 | + * ASYNC PDUs include | |
| 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) | |
| 1622 | − return &pasync_ctx->async_entry[host_write_ptr]. | |
| 1623 | − header_busy_list; | |
| 1624 | − else | |
| 1625 | − return &pasync_ctx->async_entry[host_write_ptr].data_busy_list; | |
| 1398 | + struct beiscsi_hba *phba = beiscsi_conn->phba; | |
| 1399 | + struct iscsi_conn *conn = beiscsi_conn->conn; | |
| 1400 | + struct beiscsi_io_task *io_task; | |
| 1401 | + struct iscsi_hdr *login_hdr; | |
| 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 * | |
| 1629 | −hwi_get_async_handle(struct beiscsi_hba *phba, | |
| 1630 | − struct beiscsi_conn *beiscsi_conn, | |
| 1631 | − struct hwi_async_pdu_context *pasync_ctx, | |
| 1632 | − struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index) | |
| 1453 | +static struct hd_async_handle * | |
| 1454 | +beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, | |
| 1455 | + struct hd_async_context *pasync_ctx, | |
| 1456 | + struct i_t_dpdu_cqe *pdpdu_cqe) | |
| 1633 | 1457 | { |
| 1458 | + struct beiscsi_hba *phba = beiscsi_conn->phba; | |
| 1459 | + struct hd_async_handle *pasync_handle; | |
| 1634 | 1460 | struct be_bus_address phys_addr; |
| 1635 | − struct list_head *pbusy_list; | |
| 1636 | − struct async_pdu_handle *pasync_handle = NULL; | |
| 1637 | − unsigned char is_header = 0; | |
| 1638 | − unsigned int index, dpl; | |
| 1461 | + u8 final, error = 0; | |
| 1462 | + u16 cid, code, ci; | |
| 1463 | + u32 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 | 1474 | if (is_chip_be2_be3r(phba)) { |
| 1641 | 1475 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1642 | 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 | 1478 | index, pdpdu_cqe); |
| 1479 | + final = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | |
| 1480 | + final, pdpdu_cqe); | |
| 1645 | 1481 | } else { |
| 1646 | 1482 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, |
| 1647 | 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 | 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 = | |
| 1653 | − (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | |
| 1654 | − db_addr_lo) / 32] - dpl); | |
| 1655 | − phys_addr.u.a32.address_hi = | |
| 1656 | − pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | |
| 1657 | − db_addr_hi) / 32]; | |
| 1658 | − | |
| 1659 | − phys_addr.u.a64.address = | |
| 1660 | − *((unsigned long long *)(&phys_addr.u.a64.address)); | |
| 1661 | − | |
| 1662 | − switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32] | |
| 1663 | − & PDUCQE_CODE_MASK) { | |
| 1490 | + /** | |
| 1491 | + * DB addr Hi/Lo is same for BE and SKH. | |
| 1492 | + * Subtract the dataplacementlength to get to the base. | |
| 1493 | + */ | |
| 1494 | + phys_addr.u.a32.address_lo = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | |
| 1495 | + db_addr_lo, pdpdu_cqe); | |
| 1496 | + phys_addr.u.a32.address_lo -= dpl; | |
| 1497 | + phys_addr.u.a32.address_hi = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | |
| 1498 | + db_addr_hi, pdpdu_cqe); | |
| 1499 | + | |
| 1500 | + code = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, code, pdpdu_cqe); | |
| 1501 | + switch (code) { | |
| 1664 | 1502 | case UNSOL_HDR_NOTIFY: |
| 1665 | − is_header = 1; | |
| 1666 | − | |
| 1667 | − pbusy_list = hwi_get_async_busy_list(pasync_ctx, | |
| 1668 | − is_header, index); | |
| 1503 | + pasync_handle = pasync_ctx->async_entry[ci].header; | |
| 1669 | 1504 | break; |
| 1505 | + case UNSOL_DATA_DIGEST_ERROR_NOTIFY: | |
| 1506 | + error = 1; | |
| 1670 | 1507 | case UNSOL_DATA_NOTIFY: |
| 1671 | − pbusy_list = hwi_get_async_busy_list(pasync_ctx, | |
| 1672 | − is_header, index); | |
| 1508 | + pasync_handle = pasync_ctx->async_entry[ci].data; | |
| 1673 | 1509 | break; |
| 1510 | + /* called only for above codes */ | |
| 1674 | 1511 | default: |
| 1675 | − pbusy_list = NULL; | |
| 1676 | − beiscsi_log(phba, KERN_WARNING, | |
| 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; | |
| 1512 | + pasync_handle = NULL; | |
| 1513 | + break; | |
| 1682 | 1514 | } |
| 1683 | 1515 | |
| 1684 | − WARN_ON(list_empty(pbusy_list)); | |
| 1685 | − list_for_each_entry(pasync_handle, pbusy_list, link) { | |
| 1686 | − if (pasync_handle->pa.u.a64.address == phys_addr.u.a64.address) | |
| 1687 | − break; | |
| 1516 | + if (!pasync_handle) { | |
| 1517 | + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, | |
| 1518 | + "BM_%d : cid %d async PDU handle not found - code %d ci %d addr %llx\n", | |
| 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( | |
| 1693 | − beiscsi_conn->beiscsi_conn_cid); | |
| 1694 | − pasync_handle->is_header = is_header; | |
| 1536 | + /** | |
| 1537 | + * Each CID is associated with unique CRI. | |
| 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 | 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 | 1557 | return pasync_handle; |
| 1699 | 1558 | } |
| 1700 | 1559 | |
| 1701 | −static unsigned int | |
| 1702 | −hwi_update_async_writables(struct beiscsi_hba *phba, | |
| 1703 | − struct hwi_async_pdu_context *pasync_ctx, | |
| 1704 | − unsigned int is_header, unsigned int cq_index) | |
| 1560 | +static void | |
| 1561 | +beiscsi_hdl_purge_handles(struct beiscsi_hba *phba, | |
| 1562 | + struct hd_async_context *pasync_ctx, | |
| 1563 | + u16 cri) | |
| 1705 | 1564 | { |
| 1706 | − struct list_head *pbusy_list; | |
| 1707 | − struct async_pdu_handle *pasync_handle; | |
| 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 | − } | |
| 1565 | + struct hd_async_handle *pasync_handle, *tmp_handle; | |
| 1566 | + struct list_head *plist; | |
| 1739 | 1567 | |
| 1740 | − if (!writables) { | |
| 1741 | − beiscsi_log(phba, KERN_ERR, | |
| 1742 | − BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, | |
| 1743 | − "BM_%d : Duplicate notification received - index 0x%x!!\n", | |
| 1744 | − cq_index); | |
| 1745 | − WARN_ON(1); | |
| 1568 | + plist = &pasync_ctx->async_entry[cri].wq.list; | |
| 1569 | + list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { | |
| 1570 | + list_del(&pasync_handle->link); | |
| 1571 | + beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); | |
| 1746 | 1572 | } |
| 1747 | 1573 | |
| 1748 | − *pwritables = *pwritables + writables; | |
| 1749 | − return 0; | |
| 1574 | + INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list); | |
| 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, | |
| 1753 | − struct hwi_async_pdu_context *pasync_ctx, | |
| 1754 | − unsigned int cri) | |
| 1580 | +static unsigned int | |
| 1581 | +beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn, | |
| 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 | 1590 | struct list_head *plist; |
| 1758 | 1591 | |
| 1759 | − plist = &pasync_ctx->async_entry[cri].wait_queue.list; | |
| 1760 | − list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { | |
| 1761 | − list_del(&pasync_handle->link); | |
| 1762 | − | |
| 1763 | − if (pasync_handle->is_header) { | |
| 1764 | − list_add_tail(&pasync_handle->link, | |
| 1765 | − &pasync_ctx->async_header.free_list); | |
| 1766 | − pasync_ctx->async_header.free_entries++; | |
| 1767 | − } else { | |
| 1768 | − list_add_tail(&pasync_handle->link, | |
| 1769 | − &pasync_ctx->async_data.free_list); | |
| 1770 | − pasync_ctx->async_data.free_entries++; | |
| 1592 | + plist = &pasync_ctx->async_entry[cri].wq.list; | |
| 1593 | + plast_handle = NULL; | |
| 1594 | + list_for_each_entry(pasync_handle, plist, link) { | |
| 1595 | + plast_handle = pasync_handle; | |
| 1596 | + /* get the header, the first entry */ | |
| 1597 | + if (!phdr) { | |
| 1598 | + phdr = pasync_handle->pbuffer; | |
| 1599 | + continue; | |
| 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); | |
| 1775 | − pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0; | |
| 1776 | − pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; | |
| 1612 | + if (!plast_handle->is_final) { | |
| 1613 | + /* last handle should have final PDU notification from FW */ | |
| 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 * | |
| 1780 | −hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx, | |
| 1781 | − unsigned int is_header, unsigned int host_write_ptr) | |
| 1628 | +static unsigned int | |
| 1629 | +beiscsi_hdl_gather_pdu(struct beiscsi_conn *beiscsi_conn, | |
| 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) | |
| 1786 | − pasync_sge = pasync_ctx->async_header.ring_base; | |
| 1787 | − else | |
| 1788 | − pasync_sge = pasync_ctx->async_data.ring_base; | |
| 1640 | + phba = beiscsi_conn->phba; | |
| 1641 | + wq = &pasync_ctx->async_entry[cri].wq; | |
| 1642 | + if (pasync_handle->is_header) { | |
| 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, | |
| 1794 | − unsigned int is_header, uint8_t ulp_num) | |
| 1695 | +static void | |
| 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 | 1701 | struct hwi_controller *phwi_ctrlr; |
| 1797 | − struct hwi_async_pdu_context *pasync_ctx; | |
| 1798 | − struct async_pdu_handle *pasync_handle; | |
| 1799 | − struct list_head *pfree_link, *pbusy_list; | |
| 1702 | + struct list_head *hfree_list; | |
| 1800 | 1703 | struct phys_addr *pasync_sge; |
| 1801 | − unsigned int ring_id, num_entries; | |
| 1802 | − unsigned int host_write_num, doorbell_offset; | |
| 1803 | − unsigned int writables; | |
| 1804 | − unsigned int i = 0; | |
| 1805 | − u32 doorbell = 0; | |
| 1704 | + u32 ring_id, doorbell = 0; | |
| 1705 | + u16 index, num_entries; | |
| 1706 | + u32 doorbell_offset; | |
| 1707 | + u16 prod = 0, cons; | |
| 1806 | 1708 | |
| 1807 | 1709 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1808 | 1710 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); |
| 1809 | 1711 | num_entries = pasync_ctx->num_entries; |
| 1810 | − | |
| 1811 | − if (is_header) { | |
| 1812 | − writables = min(pasync_ctx->async_header.writables, | |
| 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; | |
| 1712 | + if (header) { | |
| 1713 | + cons = pasync_ctx->async_header.free_entries; | |
| 1714 | + hfree_list = &pasync_ctx->async_header.free_list; | |
| 1816 | 1715 | ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; |
| 1817 | 1716 | doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. |
| 1818 | − doorbell_offset; | |
| 1717 | + doorbell_offset; | |
| 1819 | 1718 | } else { |
| 1820 | − writables = min(pasync_ctx->async_data.writables, | |
| 1821 | − pasync_ctx->async_data.free_entries); | |
| 1822 | − pfree_link = pasync_ctx->async_data.free_list.next; | |
| 1823 | − host_write_num = pasync_ctx->async_data.host_write_ptr; | |
| 1719 | + cons = pasync_ctx->async_data.free_entries; | |
| 1720 | + hfree_list = &pasync_ctx->async_data.free_list; | |
| 1824 | 1721 | ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; |
| 1825 | 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; | |
| 1830 | − if (writables) { | |
| 1831 | − for (i = 0; i < writables; i++) { | |
| 1832 | − pbusy_list = | |
| 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; | |
| 1729 | + list_for_each_entry_safe(pasync_handle, tmp, hfree_list, link) { | |
| 1730 | + list_del_init(&pasync_handle->link); | |
| 1731 | + pasync_handle->is_final = 0; | |
| 1732 | + pasync_handle->buffer_len = 0; | |
| 1921 | 1733 | |
| 1922 | − list_for_each_entry(pasync_handle, plist, link) { | |
| 1923 | − if (index == 0) { | |
| 1924 | − phdr = pasync_handle->pbuffer; | |
| 1925 | − hdr_len = pasync_handle->buffer_len; | |
| 1926 | − } else { | |
| 1927 | − buf_len = pasync_handle->buffer_len; | |
| 1928 | − if (!num_buf) { | |
| 1929 | − pfirst_buffer = pasync_handle->pbuffer; | |
| 1930 | − num_buf++; | |
| 1931 | − } | |
| 1932 | − memcpy(pfirst_buffer + offset, | |
| 1933 | − pasync_handle->pbuffer, buf_len); | |
| 1934 | − offset += buf_len; | |
| 1734 | + /* handles can be consumed out of order, use index in handle */ | |
| 1735 | + index = pasync_handle->index; | |
| 1736 | + WARN_ON(pasync_handle->is_header != header); | |
| 1737 | + if (header) | |
| 1738 | + slot = &pasync_ctx->async_entry[index].header; | |
| 1739 | + else | |
| 1740 | + slot = &pasync_ctx->async_entry[index].data; | |
| 1741 | + /** | |
| 1742 | + * The slot just tracks handle's hold and release, so | |
| 1743 | + * overwriting at the same index won't do any harm but | |
| 1744 | + * needs to be caught. | |
| 1745 | + */ | |
| 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, | |
| 1940 | − phdr, hdr_len, pfirst_buffer, | |
| 1941 | − offset); | |
| 1942 | − | |
| 1943 | − hwi_free_async_msg(phba, pasync_ctx, cri); | |
| 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; | |
| 1778 | + doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK; | |
| 1779 | + doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT; | |
| 1780 | + doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT; | |
| 1781 | + doorbell |= (prod & DB_DEF_PDU_CQPROC_MASK) << DB_DEF_PDU_CQPROC_SHIFT; | |
| 1782 | + iowrite32(doorbell, phba->db_va + doorbell_offset); | |
| 2013 | 1783 | } |
| 2014 | 1784 | |
| 2015 | −static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | |
| 2016 | − struct beiscsi_hba *phba, | |
| 2017 | − struct i_t_dpdu_cqe *pdpdu_cqe) | |
| 1785 | +static void | |
| 1786 | +beiscsi_hdq_process_compl(struct beiscsi_conn *beiscsi_conn, | |
| 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 | 1792 | struct hwi_controller *phwi_ctrlr; |
| 2020 | − struct hwi_async_pdu_context *pasync_ctx; | |
| 2021 | − struct async_pdu_handle *pasync_handle = NULL; | |
| 2022 | − unsigned int cq_index = -1; | |
| 2023 | − uint16_t cri_index = BE_GET_CRI_FROM_CID( | |
| 2024 | − beiscsi_conn->beiscsi_conn_cid); | |
| 1793 | + u16 cid_cri; | |
| 1794 | + u8 ulp_num; | |
| 2025 | 1795 | |
| 2026 | 1796 | phwi_ctrlr = phba->phwi_ctrlr; |
| 2027 | − pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, | |
| 2028 | − BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | |
| 2029 | − cri_index)); | |
| 2030 | − | |
| 2031 | − pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | |
| 2032 | − pdpdu_cqe, &cq_index); | |
| 2033 | − | |
| 2034 | − if (pasync_handle->consumed == 0) | |
| 2035 | − hwi_update_async_writables(phba, pasync_ctx, | |
| 2036 | − pasync_handle->is_header, cq_index); | |
| 1797 | + cid_cri = BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid); | |
| 1798 | + ulp_num = BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cid_cri); | |
| 1799 | + pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); | |
| 1800 | + pasync_handle = beiscsi_hdl_get_handle(beiscsi_conn, pasync_ctx, | |
| 1801 | + pdpdu_cqe); | |
| 1802 | + if (!pasync_handle) | |
| 1803 | + return; | |
| 2037 | 1804 | |
| 2038 | − hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); | |
| 2039 | − hwi_post_async_buffers(phba, pasync_handle->is_header, | |
| 2040 | − BEISCSI_GET_ULP_FROM_CRI( | |
| 2041 | − phwi_ctrlr, cri_index)); | |
| 1805 | + beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle); | |
| 1806 | + beiscsi_hdq_post_handles(phba, pasync_handle->is_header, ulp_num); | |
| 2042 | 1807 | } |
| 2043 | 1808 | |
| 2044 | 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 | 1816 | mcc_compl = queue_tail_node(mcc_cq); |
| 2052 | 1817 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); |
| 2053 | 1818 | while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) { |
| 1819 | + if (beiscsi_hba_in_error(phba)) | |
| 1820 | + return; | |
| 1821 | + | |
| 2054 | 1822 | if (num_processed >= 32) { |
| 2055 | 1823 | hwi_ring_cq_db(phba, mcc_cq->id, |
| 2056 | 1824 | num_processed, 0); |
| @@ -2073,6 +1841,19 @@ void beiscsi_process_mcc_cq(struct beiscsi_hba *phba) · 16 unmodified lines | ||
| 2073 | 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 | 1858 | * beiscsi_process_cq()- Process the Completion Queue |
| 2078 | 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 | 1883 | while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & |
| 2103 | 1884 | CQE_VALID_MASK) { |
| 1885 | + if (beiscsi_hba_in_error(phba)) | |
| 1886 | + return 0; | |
| 1887 | + | |
| 2104 | 1888 | be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); |
| 2105 | 1889 | |
| 2106 | 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 | 1949 | cqe_desc[code], code, cid); |
| 2166 | 1950 | |
| 2167 | 1951 | spin_lock_bh(&phba->async_pdu_lock); |
| 2168 | − hwi_process_default_pdu_ring(beiscsi_conn, phba, | |
| 2169 | − (struct i_t_dpdu_cqe *)sol); | |
| 1952 | + beiscsi_hdq_process_compl(beiscsi_conn, | |
| 1953 | + (struct i_t_dpdu_cqe *)sol); | |
| 2170 | 1954 | spin_unlock_bh(&phba->async_pdu_lock); |
| 2171 | 1955 | break; |
| 2172 | 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 | 1960 | cqe_desc[code], code, cid); |
| 2177 | 1961 | |
| 2178 | 1962 | spin_lock_bh(&phba->async_pdu_lock); |
| 2179 | − hwi_process_default_pdu_ring(beiscsi_conn, phba, | |
| 2180 | − (struct i_t_dpdu_cqe *)sol); | |
| 1963 | + beiscsi_hdq_process_compl(beiscsi_conn, | |
| 1964 | + (struct i_t_dpdu_cqe *)sol); | |
| 2181 | 1965 | spin_unlock_bh(&phba->async_pdu_lock); |
| 2182 | 1966 | break; |
| 2183 | 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 | 1997 | "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", |
| 2214 | 1998 | cqe_desc[code], code, cid); |
| 2215 | 1999 | spin_lock_bh(&phba->async_pdu_lock); |
| 2216 | − hwi_flush_default_pdu_buffer(phba, beiscsi_conn, | |
| 2217 | − (struct i_t_dpdu_cqe *) sol); | |
| 2000 | + /* driver consumes the entry and drops the contents */ | |
| 2001 | + beiscsi_hdq_process_compl(beiscsi_conn, | |
| 2002 | + (struct i_t_dpdu_cqe *)sol); | |
| 2218 | 2003 | spin_unlock_bh(&phba->async_pdu_lock); |
| 2219 | 2004 | break; |
| 2220 | 2005 | case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: |
| @@ -2262,60 +2047,32 @@ proc_next_cqe: · 41 unmodified lines | ||
| 2262 | 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 | 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 | 2053 | struct beiscsi_hba *phba; |
| 2300 | 2054 | struct be_eq_obj *pbe_eq; |
| 2301 | 2055 | struct be_eq_entry *eqe = NULL; |
| 2302 | 2056 | struct be_queue_info *eq; |
| 2303 | 2057 | |
| 2304 | − num_eq_processed = 0; | |
| 2305 | 2058 | pbe_eq = container_of(iop, struct be_eq_obj, iopoll); |
| 2306 | 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 | 2066 | eq = &pbe_eq->q; |
| 2308 | 2067 | eqe = queue_tail_node(eq); |
| 2309 | − | |
| 2310 | 2068 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] & |
| 2311 | 2069 | EQE_VALID_MASK) { |
| 2312 | 2070 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
| 2313 | 2071 | queue_tail_inc(eq); |
| 2314 | 2072 | eqe = queue_tail_node(eq); |
| 2315 | − num_eq_processed++; | |
| 2073 | + io_events++; | |
| 2316 | 2074 | } |
| 2317 | − | |
| 2318 | − hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); | |
| 2075 | + hwi_ring_eq_db(phba, eq->id, 1, io_events, 0, 1); | |
| 2319 | 2076 | |
| 2320 | 2077 | ret = beiscsi_process_cq(pbe_eq, budget); |
| 2321 | 2078 | pbe_eq->cq_count += ret; |
| @@ -2325,7 +2082,8 @@ static int be_iopoll(struct irq_poll *iop, int budget) · 3 unmodified lines | ||
| 2325 | 2082 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, |
| 2326 | 2083 | "BM_%d : rearm pbe_eq->q.id =%d ret %d\n", |
| 2327 | 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 | 2088 | return ret; |
| 2331 | 2089 | } |
| @@ -2691,20 +2449,20 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) · 359 unmodified lines | ||
| 2691 | 2449 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2692 | 2450 | phba->mem_req[mem_descr_index] = |
| 2693 | 2451 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 2694 | − sizeof(struct async_pdu_handle); | |
| 2452 | + sizeof(struct hd_async_handle); | |
| 2695 | 2453 | |
| 2696 | 2454 | mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + |
| 2697 | 2455 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2698 | 2456 | phba->mem_req[mem_descr_index] = |
| 2699 | 2457 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 2700 | − sizeof(struct async_pdu_handle); | |
| 2458 | + sizeof(struct hd_async_handle); | |
| 2701 | 2459 | |
| 2702 | 2460 | mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + |
| 2703 | 2461 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2704 | 2462 | phba->mem_req[mem_descr_index] = |
| 2705 | − sizeof(struct hwi_async_pdu_context) + | |
| 2463 | + sizeof(struct hd_async_context) + | |
| 2706 | 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 | 2721 | uint8_t ulp_num; |
| 2964 | 2722 | struct hwi_controller *phwi_ctrlr; |
| 2965 | 2723 | struct hba_parameters *p = &phba->params; |
| 2966 | − struct hwi_async_pdu_context *pasync_ctx; | |
| 2967 | − struct async_pdu_handle *pasync_header_h, *pasync_data_h; | |
| 2724 | + struct hd_async_context *pasync_ctx; | |
| 2725 | + struct hd_async_handle *pasync_header_h, *pasync_data_h; | |
| 2968 | 2726 | unsigned int index, idx, num_per_mem, num_async_data; |
| 2969 | 2727 | struct be_mem_descriptor *mem_descr; |
| 2970 | 2728 | |
| 2971 | 2729 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
| 2972 | 2730 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 2973 | − | |
| 2731 | + /* get async_ctx for each ULP */ | |
| 2974 | 2732 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 2975 | 2733 | mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + |
| 2976 | 2734 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2977 | 2735 | |
| 2978 | 2736 | phwi_ctrlr = phba->phwi_ctrlr; |
| 2979 | 2737 | phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num] = |
| 2980 | − (struct hwi_async_pdu_context *) | |
| 2738 | + (struct hd_async_context *) | |
| 2981 | 2739 | mem_descr->mem_array[0].virtual_address; |
| 2982 | 2740 | |
| 2983 | 2741 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; |
| 2984 | 2742 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); |
| 2985 | 2743 | |
| 2986 | 2744 | pasync_ctx->async_entry = |
| 2987 | − (struct hwi_async_entry *) | |
| 2745 | + (struct hd_async_entry *) | |
| 2988 | 2746 | ((long unsigned int)pasync_ctx + |
| 2989 | − sizeof(struct hwi_async_pdu_context)); | |
| 2747 | + sizeof(struct hd_async_context)); | |
| 2990 | 2748 | |
| 2991 | 2749 | pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, |
| 2992 | 2750 | ulp_num); |
| 2993 | − pasync_ctx->buffer_size = p->defpdu_hdr_sz; | |
| 2994 | − | |
| 2751 | + /* setup header buffers */ | |
| 2995 | 2752 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 2996 | 2753 | mem_descr += HWI_MEM_ASYNC_HEADER_BUF_ULP0 + |
| 2997 | 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 | 2765 | "BM_%d : No Virtual address for ULP : %d\n", |
| 3009 | 2766 | ulp_num); |
| 3010 | 2767 | |
| 2768 | + pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz; | |
| 3011 | 2769 | pasync_ctx->async_header.va_base = |
| 3012 | 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 | 2773 | mem_descr->mem_array[0]. |
| 3016 | 2774 | bus_address.u.a64.address; |
| 3017 | 2775 | |
| 2776 | + /* setup header buffer sgls */ | |
| 3018 | 2777 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3019 | 2778 | mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + |
| 3020 | 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 | 2793 | pasync_ctx->async_header.ring_base = |
| 3035 | 2794 | mem_descr->mem_array[0].virtual_address; |
| 3036 | 2795 | |
| 2796 | + /* setup header buffer handles */ | |
| 3037 | 2797 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3038 | 2798 | mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + |
| 3039 | 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 | 2813 | pasync_ctx->async_header.handle_base = |
| 3054 | 2814 | mem_descr->mem_array[0].virtual_address; |
| 3055 | − pasync_ctx->async_header.writables = 0; | |
| 3056 | 2815 | INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); |
| 3057 | 2816 | |
| 2817 | + /* setup data buffer sgls */ | |
| 3058 | 2818 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3059 | 2819 | mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + |
| 3060 | 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 | 2834 | pasync_ctx->async_data.ring_base = |
| 3075 | 2835 | mem_descr->mem_array[0].virtual_address; |
| 3076 | 2836 | |
| 2837 | + /* setup data buffer handles */ | |
| 3077 | 2838 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3078 | 2839 | mem_descr += HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + |
| 3079 | 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 | 2847 | pasync_ctx->async_data.handle_base = |
| 3087 | 2848 | mem_descr->mem_array[0].virtual_address; |
| 3088 | − pasync_ctx->async_data.writables = 0; | |
| 3089 | 2849 | INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); |
| 3090 | 2850 | |
| 3091 | 2851 | pasync_header_h = |
| 3092 | − (struct async_pdu_handle *) | |
| 2852 | + (struct hd_async_handle *) | |
| 3093 | 2853 | pasync_ctx->async_header.handle_base; |
| 3094 | 2854 | pasync_data_h = |
| 3095 | − (struct async_pdu_handle *) | |
| 2855 | + (struct hd_async_handle *) | |
| 3096 | 2856 | pasync_ctx->async_data.handle_base; |
| 3097 | 2857 | |
| 2858 | + /* setup data buffers */ | |
| 3098 | 2859 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3099 | 2860 | mem_descr += HWI_MEM_ASYNC_DATA_BUF_ULP0 + |
| 3100 | 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 | 2873 | ulp_num); |
| 3113 | 2874 | |
| 3114 | 2875 | idx = 0; |
| 2876 | + pasync_ctx->async_data.buffer_size = p->defpdu_data_sz; | |
| 3115 | 2877 | pasync_ctx->async_data.va_base = |
| 3116 | 2878 | mem_descr->mem_array[idx].virtual_address; |
| 3117 | 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 | 2887 | for (index = 0; index < BEISCSI_GET_CID_COUNT |
| 3126 | 2888 | (phba, ulp_num); index++) { |
| 3127 | 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 | 2892 | INIT_LIST_HEAD(&pasync_header_h->link); |
| 3130 | 2893 | pasync_header_h->pbuffer = |
| 3131 | 2894 | (void *)((unsigned long) |
| @@ -3142,14 +2905,13 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 10 unmodified lines | ||
| 3142 | 2905 | free_list); |
| 3143 | 2906 | pasync_header_h++; |
| 3144 | 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 | 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 | 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 | 2915 | INIT_LIST_HEAD(&pasync_data_h->link); |
| 3154 | 2916 | |
| 3155 | 2917 | if (!num_async_data) { |
| @@ -3184,16 +2946,8 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 28 unmodified lines | ||
| 3184 | 2946 | free_list); |
| 3185 | 2947 | pasync_data_h++; |
| 3186 | 2948 | pasync_ctx->async_data.free_entries++; |
| 3187 | − pasync_ctx->async_data.writables++; | |
| 3188 | − | |
| 3189 | − INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | |
| 3190 | − data_busy_list); | |
| 2949 | + pasync_ctx->async_entry[index].data = NULL; | |
| 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 | 3019 | static int beiscsi_create_eqs(struct beiscsi_hba *phba, |
| 3266 | 3020 | struct hwi_context_memory *phwi_context) |
| 3267 | 3021 | { |
| 3022 | + int ret = -ENOMEM, eq_for_mcc; | |
| 3268 | 3023 | unsigned int i, num_eq_pages; |
| 3269 | − int ret = 0, eq_for_mcc; | |
| 3270 | 3024 | struct be_queue_info *eq; |
| 3271 | 3025 | struct be_dma_mem *mem; |
| 3272 | 3026 | void *eq_vaddress; |
| @@ -3284,8 +3038,8 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, · 11 unmodified lines | ||
| 3284 | 3038 | mem = &eq->dma_mem; |
| 3285 | 3039 | phwi_context->be_eq[i].phba = phba; |
| 3286 | 3040 | eq_vaddress = pci_alloc_consistent(phba->pcidev, |
| 3287 | − num_eq_pages * PAGE_SIZE, | |
| 3288 | − &paddr); | |
| 3041 | + num_eq_pages * PAGE_SIZE, | |
| 3042 | + &paddr); | |
| 3289 | 3043 | if (!eq_vaddress) |
| 3290 | 3044 | goto create_eq_error; |
| 3291 | 3045 | |
| @@ -3313,6 +3067,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, · 21 unmodified lines | ||
| 3313 | 3067 | phwi_context->be_eq[i].q.id); |
| 3314 | 3068 | } |
| 3315 | 3069 | return 0; |
| 3070 | + | |
| 3316 | 3071 | create_eq_error: |
| 3317 | 3072 | for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { |
| 3318 | 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 | 3084 | struct hwi_context_memory *phwi_context) |
| 3330 | 3085 | { |
| 3331 | 3086 | unsigned int i, num_cq_pages; |
| 3332 | − int ret = 0; | |
| 3333 | 3087 | struct be_queue_info *cq, *eq; |
| 3334 | 3088 | struct be_dma_mem *mem; |
| 3335 | 3089 | struct be_eq_obj *pbe_eq; |
| 3336 | 3090 | void *cq_vaddress; |
| 3091 | + int ret = -ENOMEM; | |
| 3337 | 3092 | dma_addr_t paddr; |
| 3338 | 3093 | |
| 3339 | 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 | 3102 | pbe_eq->phba = phba; |
| 3348 | 3103 | mem = &cq->dma_mem; |
| 3349 | 3104 | cq_vaddress = pci_alloc_consistent(phba->pcidev, |
| 3350 | − num_cq_pages * PAGE_SIZE, | |
| 3351 | − &paddr); | |
| 3105 | + num_cq_pages * PAGE_SIZE, | |
| 3106 | + &paddr); | |
| 3352 | 3107 | if (!cq_vaddress) |
| 3353 | 3108 | goto create_cq_error; |
| 3109 | + | |
| 3354 | 3110 | ret = be_fill_queue(cq, phba->params.num_cq_entries, |
| 3355 | 3111 | sizeof(struct sol_cqe), cq_vaddress); |
| 3356 | 3112 | if (ret) { |
| @@ -3385,7 +3141,6 @@ create_cq_error: · 28 unmodified lines | ||
| 3385 | 3141 | mem->va, mem->dma); |
| 3386 | 3142 | } |
| 3387 | 3143 | return ret; |
| 3388 | − | |
| 3389 | 3144 | } |
| 3390 | 3145 | |
| 3391 | 3146 | static int |
| @@ -3437,7 +3192,6 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba, · 45 unmodified lines | ||
| 3437 | 3192 | "BM_%d : iscsi hdr def pdu id for ULP : %d is %d\n", |
| 3438 | 3193 | ulp_num, |
| 3439 | 3194 | phwi_context->be_def_hdrq[ulp_num].id); |
| 3440 | − hwi_post_async_buffers(phba, BEISCSI_DEFQ_HDR, ulp_num); | |
| 3441 | 3195 | return 0; |
| 3442 | 3196 | } |
| 3443 | 3197 | |
| @@ -3492,11 +3246,9 @@ beiscsi_create_def_data(struct beiscsi_hba *phba, · 48 unmodified lines | ||
| 3492 | 3246 | ulp_num, |
| 3493 | 3247 | phwi_context->be_def_dataq[ulp_num].id); |
| 3494 | 3248 | |
| 3495 | − hwi_post_async_buffers(phba, BEISCSI_DEFQ_DATA, ulp_num); | |
| 3496 | 3249 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
| 3497 | 3250 | "BM_%d : DEFAULT PDU DATA RING CREATED" |
| 3498 | 3251 | "on ULP : %d\n", ulp_num); |
| 3499 | − | |
| 3500 | 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 | 3469 | static void be_mcc_queues_destroy(struct beiscsi_hba *phba) |
| 3718 | 3470 | { |
| 3719 | − struct be_queue_info *q; | |
| 3720 | 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 | 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 | 3518 | if (q->created) { |
| 3724 | 3519 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); |
| 3725 | 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 | 3530 | static int be_mcc_queues_create(struct beiscsi_hba *phba, |
| 3798 | 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 | 3725 | struct hwi_controller *phwi_ctrlr; |
| 3881 | 3726 | struct hwi_context_memory *phwi_context; |
| @@ -3887,9 +3732,8 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 5 unmodified lines | ||
| 3887 | 3732 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| 3888 | 3733 | phwi_context->max_eqd = 128; |
| 3889 | 3734 | phwi_context->min_eqd = 0; |
| 3890 | − phwi_context->cur_eqd = 0; | |
| 3891 | − be_cmd_fw_initialize(&phba->ctrl); | |
| 3892 | − /* set optic state to unknown */ | |
| 3735 | + phwi_context->cur_eqd = 32; | |
| 3736 | + /* set port optic state to unknown */ | |
| 3893 | 3737 | phba->optic_state = 0xff; |
| 3894 | 3738 | |
| 3895 | 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 | 3747 | if (status != 0) |
| 3904 | 3748 | goto error; |
| 3905 | 3749 | |
| 3906 | − status = mgmt_check_supported_fw(ctrl, phba); | |
| 3750 | + status = beiscsi_check_supported_fw(ctrl, phba); | |
| 3907 | 3751 | if (status != 0) { |
| 3908 | 3752 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 3909 | 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 | 3764 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
| 3921 | 3765 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 3922 | − | |
| 3923 | 3766 | def_pdu_ring_sz = |
| 3924 | 3767 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 3925 | 3768 | sizeof(struct phys_addr); |
| @@ -3945,6 +3788,15 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 19 unmodified lines | ||
| 3945 | 3788 | ulp_num); |
| 3946 | 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 | 3826 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 3975 | 3827 | uint16_t cri = 0; |
| 3976 | − struct hwi_async_pdu_context *pasync_ctx; | |
| 3828 | + struct hd_async_context *pasync_ctx; | |
| 3977 | 3829 | |
| 3978 | 3830 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX( |
| 3979 | 3831 | phwi_ctrlr, ulp_num); |
| @@ -3985,6 +3837,14 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 5 unmodified lines | ||
| 3985 | 3837 | phwi_ctrlr->wrb_context[cri].cid] = |
| 3986 | 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 | 3855 | error: |
| 3996 | 3856 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 3997 | 3857 | "BM_%d : hwi_init_port failed"); |
| 3998 | − hwi_cleanup(phba); | |
| 3858 | + hwi_cleanup_port(phba); | |
| 3999 | 3859 | return status; |
| 4000 | 3860 | } |
| 4001 | 3861 | |
| @@ -4354,149 +4214,6 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) · 352 unmodified lines | ||
| 4354 | 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 | 4217 | static int beiscsi_init_port(struct beiscsi_hba *phba) |
| 4501 | 4218 | { |
| 4502 | 4219 | int ret; |
| @@ -4516,7 +4233,8 @@ static int beiscsi_init_port(struct beiscsi_hba *phba) · 13 unmodified lines | ||
| 4516 | 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 | 4238 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 4521 | 4239 | "BM_%d : Failed in hba_setup_cid_tbls\n"); |
| 4522 | 4240 | kfree(phba->io_sgl_hndl_base); |
| @@ -4527,61 +4245,15 @@ static int beiscsi_init_port(struct beiscsi_hba *phba) · 4 unmodified lines | ||
| 4527 | 4245 | return ret; |
| 4528 | 4246 | |
| 4529 | 4247 | do_cleanup_ctrlr: |
| 4530 | − hwi_cleanup(phba); | |
| 4248 | + hwi_cleanup_port(phba); | |
| 4531 | 4249 | return ret; |
| 4532 | 4250 | } |
| 4533 | 4251 | |
| 4534 | −static void hwi_purge_eq(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) | |
| 4252 | +static void beiscsi_cleanup_port(struct beiscsi_hba *phba) | |
| 4568 | 4253 | { |
| 4569 | − int mgmt_status, ulp_num; | |
| 4570 | 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 | 4257 | kfree(phba->io_sgl_hndl_base); |
| 4586 | 4258 | kfree(phba->eh_sgl_hndl_base); |
| 4587 | 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 | 4296 | io_task = task->dd_data; |
| 4626 | 4297 | |
| 4627 | 4298 | if (io_task->pwrb_handle) { |
| 4628 | − memset(io_task->pwrb_handle->pwrb, 0, | |
| 4629 | − sizeof(struct iscsi_wrb)); | |
| 4630 | − free_wrb_handle(phba, pwrb_context, | |
| 4631 | − io_task->pwrb_handle); | |
| 4299 | + free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); | |
| 4632 | 4300 | io_task->pwrb_handle = NULL; |
| 4633 | 4301 | } |
| 4634 | 4302 | |
| 4635 | 4303 | if (io_task->psgl_handle) { |
| 4636 | − free_mgmt_sgl_handle(phba, | |
| 4637 | − io_task->psgl_handle); | |
| 4304 | + free_mgmt_sgl_handle(phba, io_task->psgl_handle); | |
| 4638 | 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 | 4338 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, |
| 4672 | 4339 | io_task->bhs_pa.u.a64.address); |
| 4673 | 4340 | io_task->cmd_bhs = NULL; |
| 4341 | + task->hdr = NULL; | |
| 4674 | 4342 | } |
| 4675 | 4343 | |
| 4676 | 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 | 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 | 4359 | io_task->scsi_cmnd = NULL; |
| 4691 | 4360 | } |
| 4692 | 4361 | } else { |
| @@ -5051,7 +4720,6 @@ static int beiscsi_mtask(struct iscsi_task *task) · 358 unmodified lines | ||
| 5051 | 4720 | |
| 5052 | 4721 | cid = beiscsi_conn->beiscsi_conn_cid; |
| 5053 | 4722 | pwrb = io_task->pwrb_handle->pwrb; |
| 5054 | − memset(pwrb, 0, sizeof(*pwrb)); | |
| 5055 | 4723 | |
| 5056 | 4724 | if (is_chip_be2_be3r(phba)) { |
| 5057 | 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 | 4833 | int num_sg; |
| 5166 | 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 | 4845 | if (!io_task->conn->login_in_progress) |
| 5169 | 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 | 4849 | return beiscsi_mtask(task); |
| 5173 | 4850 | |
| 5174 | 4851 | io_task->scsi_cmnd = sc; |
| 4852 | + io_task->num_sg = 0; | |
| 5175 | 4853 | num_sg = scsi_dma_map(sc); |
| 5176 | − phba = io_task->conn->phba; | |
| 5177 | 4854 | if (num_sg < 0) { |
| 5178 | 4855 | beiscsi_log(phba, KERN_ERR, |
| 5179 | 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 | 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 | 4869 | xferlen = scsi_bufflen(sc); |
| 5188 | 4870 | sg = scsi_sglist(sc); |
| 5189 | 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 | 4895 | shost = iscsi_job_to_shost(job); |
| 5214 | 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 | 4904 | switch (bsg_req->msgcode) { |
| 5217 | 4905 | case ISCSI_BSG_HST_VENDOR: |
| 5218 | 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 | 4928 | phba->ctrl.mcc_tag_status[tag], |
| 5241 | 4929 | msecs_to_jiffies( |
| 5242 | 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 | 4939 | extd_status = (phba->ctrl.mcc_tag_status[tag] & |
| 5244 | 4940 | CQE_STATUS_ADDL_MASK) >> CQE_STATUS_ADDL_SHIFT; |
| 5245 | 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 | 4979 | beiscsi_log_enable_init(phba, beiscsi_log_enable); |
| 5284 | 4980 | } |
| 5285 | 4981 | |
| 5286 | −/* | |
| 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) | |
| 4982 | +void beiscsi_start_boot_work(struct beiscsi_hba *phba, unsigned int s_handle) | |
| 5295 | 4983 | { |
| 5296 | − struct hwi_controller *phwi_ctrlr; | |
| 5297 | − struct hwi_context_memory *phwi_context; | |
| 5298 | − struct be_eq_obj *pbe_eq; | |
| 5299 | − unsigned int i, msix_vec; | |
| 4984 | + if (phba->boot_struct.boot_kset) | |
| 4985 | + return; | |
| 5300 | 4986 | |
| 5301 | − phwi_ctrlr = phba->phwi_ctrlr; | |
| 5302 | − phwi_context = phwi_ctrlr->phwi_ctxt; | |
| 5303 | − hwi_disable_intr(phba); | |
| 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); | |
| 4987 | + /* skip if boot work is already in progress */ | |
| 4988 | + if (test_and_set_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) | |
| 4989 | + return; | |
| 5315 | 4990 | |
| 5316 | − for (i = 0; i < phba->num_cpus; i++) { | |
| 5317 | − pbe_eq = &phwi_context->be_eq[i]; | |
| 5318 | − irq_poll_disable(&pbe_eq->iopoll); | |
| 4991 | + phba->boot_struct.retry = 3; | |
| 4992 | + phba->boot_struct.tag = 0; | |
| 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) { | |
| 5322 | − destroy_workqueue(phba->wq); | |
| 5323 | − beiscsi_clean_port(phba); | |
| 5324 | − beiscsi_free_mem(phba); | |
| 5062 | +static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) | |
| 5063 | +{ | |
| 5064 | + struct beiscsi_hba *phba = data; | |
| 5065 | + char *str = buf; | |
| 5066 | + int rc = -EPERM; | |
| 5325 | 5067 | |
| 5326 | − beiscsi_unmap_pci_function(phba); | |
| 5327 | − pci_free_consistent(phba->pcidev, | |
| 5328 | − phba->ctrl.mbox_mem_alloced.size, | |
| 5329 | − phba->ctrl.mbox_mem_alloced.va, | |
| 5330 | − phba->ctrl.mbox_mem_alloced.dma); | |
| 5331 | − } else { | |
| 5332 | − hwi_purge_eq(phba); | |
| 5333 | − hwi_cleanup(phba); | |
| 5068 | + switch (type) { | |
| 5069 | + case ISCSI_BOOT_INI_INITIATOR_NAME: | |
| 5070 | + rc = sprintf(str, "%s\n", | |
| 5071 | + phba->boot_struct.boot_sess.initiator_iscsiname); | |
| 5072 | + break; | |
| 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); | |
| 5343 | − if (!phba) { | |
| 5344 | − dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); | |
| 5345 | − return; | |
| 5101 | + switch (type) { | |
| 5102 | + case ISCSI_BOOT_TGT_NAME: | |
| 5103 | + case ISCSI_BOOT_TGT_IP_ADDR: | |
| 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); | |
| 5349 | − iscsi_boot_destroy_kset(phba->boot_kset); | |
| 5350 | − iscsi_host_remove(phba->shost); | |
| 5351 | − beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); | |
| 5352 | − pci_dev_put(phba->pcidev); | |
| 5353 | − iscsi_host_free(phba->shost); | |
| 5354 | − pci_disable_pcie_error_reporting(pcidev); | |
| 5355 | − pci_set_drvdata(pcidev, NULL); | |
| 5356 | − pci_release_regions(pcidev); | |
| 5357 | − pci_disable_device(pcidev); | |
| 5117 | +static umode_t beiscsi_ini_get_attr_visibility(void *data, int type) | |
| 5118 | +{ | |
| 5119 | + umode_t rc = 0; | |
| 5120 | + | |
| 5121 | + switch (type) { | |
| 5122 | + case ISCSI_BOOT_INI_INITIATOR_NAME: | |
| 5123 | + rc = S_IRUGO; | |
| 5124 | + break; | |
| 5125 | + } | |
| 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++) | |
| 5365 | − phba->msix_entries[i].entry = i; | |
| 5133 | + switch (type) { | |
| 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, | |
| 5368 | − phba->num_cpus + 1, phba->num_cpus + 1); | |
| 5369 | − if (status > 0) | |
| 5370 | − phba->msix_enabled = true; | |
| 5143 | +static void beiscsi_boot_kobj_release(void *data) | |
| 5144 | +{ | |
| 5145 | + struct beiscsi_hba *phba = data; | |
| 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 | 5258 | struct be_set_eqd set_eqd[MAX_CPUS]; |
| 5378 | − struct be_aic_obj *aic; | |
| 5379 | − struct be_eq_obj *pbe_eq; | |
| 5380 | 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 | 5264 | int eqd, i, num = 0; |
| 5383 | − ulong now; | |
| 5384 | − u32 pps, delta; | |
| 5385 | − unsigned int tag; | |
| 5265 | + unsigned long now; | |
| 5266 | + | |
| 5267 | + phba = container_of(work, struct beiscsi_hba, eqd_update.work); | |
| 5268 | + if (!beiscsi_hba_is_online(phba)) | |
| 5269 | + return; | |
| 5386 | 5270 | |
| 5387 | 5271 | phwi_ctrlr = phba->phwi_ctrlr; |
| 5388 | 5272 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| @@ -5391,13 +5275,13 @@ static void be_eqd_update(struct beiscsi_hba *phba) · 2 unmodified lines | ||
| 5391 | 5275 | aic = &phba->aic_obj[i]; |
| 5392 | 5276 | pbe_eq = &phwi_context->be_eq[i]; |
| 5393 | 5277 | now = jiffies; |
| 5394 | − if (!aic->jiffs || time_before(now, aic->jiffs) || | |
| 5278 | + if (!aic->jiffies || time_before(now, aic->jiffies) || | |
| 5395 | 5279 | pbe_eq->cq_count < aic->eq_prev) { |
| 5396 | − aic->jiffs = now; | |
| 5280 | + aic->jiffies = now; | |
| 5397 | 5281 | aic->eq_prev = pbe_eq->cq_count; |
| 5398 | 5282 | continue; |
| 5399 | 5283 | } |
| 5400 | − delta = jiffies_to_msecs(now - aic->jiffs); | |
| 5284 | + delta = jiffies_to_msecs(now - aic->jiffies); | |
| 5401 | 5285 | pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); |
| 5402 | 5286 | eqd = (pps / 1500) << 2; |
| 5403 | 5287 | |
| @@ -5406,7 +5290,7 @@ static void be_eqd_update(struct beiscsi_hba *phba) · 2 unmodified lines | ||
| 5406 | 5290 | eqd = min_t(u32, eqd, phwi_context->max_eqd); |
| 5407 | 5291 | eqd = max_t(u32, eqd, phwi_context->min_eqd); |
| 5408 | 5292 | |
| 5409 | − aic->jiffs = now; | |
| 5293 | + aic->jiffies = now; | |
| 5410 | 5294 | aic->eq_prev = pbe_eq->cq_count; |
| 5411 | 5295 | |
| 5412 | 5296 | if (eqd != aic->prev_eqd) { |
| @@ -5416,53 +5300,242 @@ static void be_eqd_update(struct beiscsi_hba *phba) · 3 unmodified lines | ||
| 5416 | 5300 | num++; |
| 5417 | 5301 | } |
| 5418 | 5302 | } |
| 5419 | − if (num) { | |
| 5420 | − tag = be_cmd_modify_eq_delay(phba, set_eqd, num); | |
| 5421 | − if (tag) | |
| 5422 | − beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); | |
| 5303 | + if (num) | |
| 5304 | + /* completion of this is ignored */ | |
| 5305 | + beiscsi_modify_eq_delay(phba, set_eqd, num); | |
| 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)) | |
| 5429 | − beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | |
| 5430 | − "BM_%d : Could not set up " | |
| 5431 | − "iSCSI boot info on async event.\n"); | |
| 5375 | + struct hwi_context_memory *phwi_context; | |
| 5376 | + struct hwi_controller *phwi_ctrlr; | |
| 5377 | + struct be_eq_obj *pbe_eq; | |
| 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 | |
| 5436 | − * @work: work item to check HW health | |
| 5473 | + * beiscsi_disable_port()- Disable port and cleanup driver resources. | |
| 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 | |
| 5441 | −beiscsi_hw_health_check(struct work_struct *work) | |
| 5480 | +static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload) | |
| 5442 | 5481 | { |
| 5443 | − struct beiscsi_hba *phba = | |
| 5444 | − container_of(work, struct beiscsi_hba, | |
| 5445 | − beiscsi_hw_check_task.work); | |
| 5482 | + struct hwi_context_memory *phwi_context; | |
| 5483 | + struct hwi_controller *phwi_ctrlr; | |
| 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) { | |
| 5450 | − if ((phba->get_boot > 0) && (!phba->boot_kset)) { | |
| 5451 | − phba->get_boot--; | |
| 5452 | − if (!(phba->get_boot % BE_GET_BOOT_TO)) | |
| 5453 | − be_check_boot_session(phba); | |
| 5454 | − } else { | |
| 5455 | − phba->state &= ~BE_ADAPTER_CHECK_BOOT; | |
| 5456 | − phba->get_boot = 0; | |
| 5490 | + phwi_ctrlr = phba->phwi_ctrlr; | |
| 5491 | + phwi_context = phwi_ctrlr->phwi_ctxt; | |
| 5492 | + hwi_disable_intr(phba); | |
| 5493 | + if (phba->msix_enabled) { | |
| 5494 | + for (i = 0; i <= phba->num_cpus; i++) { | |
| 5495 | + msix_vec = phba->msix_entries[i].vector; | |
| 5496 | + free_irq(msix_vec, &phwi_context->be_eq[i]); | |
| 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, | |
| 5463 | − msecs_to_jiffies(1000)); | |
| 5522 | + phba = container_of(work, struct beiscsi_hba, sess_work); | |
| 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 | 5540 | static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, |
| 5468 | 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 | 5543 | struct beiscsi_hba *phba = NULL; |
| 5471 | 5544 | |
| 5472 | 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 | 5548 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5476 | 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 | 5559 | if (state == pci_channel_io_perm_failure) { |
| 5481 | 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 | 5594 | pci_set_power_state(pdev, PCI_D0); |
| 5516 | 5595 | pci_restore_state(pdev); |
| 5517 | 5596 | |
| 5518 | − /* Wait for the CHIP Reset to complete */ | |
| 5519 | − status = be_chk_reset_complete(phba); | |
| 5520 | − if (!status) { | |
| 5597 | + status = beiscsi_check_fw_rdy(phba); | |
| 5598 | + if (status) { | |
| 5521 | 5599 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, |
| 5522 | 5600 | "BM_%d : EEH Reset Completed\n"); |
| 5523 | 5601 | } else { |
| @@ -5532,87 +5610,16 @@ static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) · 8 unmodified lines | ||
| 5532 | 5610 | |
| 5533 | 5611 | static void beiscsi_eeh_resume(struct pci_dev *pdev) |
| 5534 | 5612 | { |
| 5535 | − int ret = 0, i; | |
| 5536 | − struct be_eq_obj *pbe_eq; | |
| 5537 | − struct beiscsi_hba *phba = NULL; | |
| 5538 | − struct hwi_controller *phwi_ctrlr; | |
| 5539 | − struct hwi_context_memory *phwi_context; | |
| 5613 | + struct beiscsi_hba *phba; | |
| 5614 | + int ret; | |
| 5540 | 5615 | |
| 5541 | 5616 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); |
| 5542 | 5617 | pci_save_state(pdev); |
| 5543 | 5618 | |
| 5544 | − if (enable_msix) | |
| 5545 | − find_num_cpus(phba); | |
| 5546 | − else | |
| 5547 | − phba->num_cpus = 1; | |
| 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"); | |
| 5619 | + ret = beiscsi_enable_port(phba); | |
| 5620 | + if (ret) | |
| 5621 | + __beiscsi_log(phba, KERN_ERR, | |
| 5622 | + "BM_%d : AER EEH resume failed\n"); | |
| 5616 | 5623 | } |
| 5617 | 5624 | |
| 5618 | 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 | 5629 | struct hwi_controller *phwi_ctrlr; |
| 5623 | 5630 | struct hwi_context_memory *phwi_context; |
| 5624 | 5631 | struct be_eq_obj *pbe_eq; |
| 5625 | − int ret = 0, i; | |
| 5632 | + unsigned int s_handle; | |
| 5633 | + int ret, i; | |
| 5626 | 5634 | |
| 5627 | 5635 | ret = beiscsi_enable_pci(pcidev); |
| 5628 | 5636 | if (ret < 0) { |
| @@ -5635,6 +5643,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 6 unmodified lines | ||
| 5635 | 5643 | if (!phba) { |
| 5636 | 5644 | dev_err(&pcidev->dev, |
| 5637 | 5645 | "beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n"); |
| 5646 | + ret = -ENOMEM; | |
| 5638 | 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 | 5659 | /* Initialize Driver configuration Paramters */ |
| 5651 | 5660 | beiscsi_hba_attrs_init(phba); |
| 5652 | 5661 | |
| 5653 | − phba->fw_timeout = false; | |
| 5654 | 5662 | phba->mac_addr_set = false; |
| 5655 | 5663 | |
| 5656 | − | |
| 5657 | 5664 | switch (pcidev->device) { |
| 5658 | 5665 | case BE_DEVICE_ID1: |
| 5659 | 5666 | case OC_DEVICE_ID1: |
| @@ -5677,39 +5684,26 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 17 unmodified lines | ||
| 5677 | 5684 | ret = be_ctrl_init(phba, pcidev); |
| 5678 | 5685 | if (ret) { |
| 5679 | 5686 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5680 | − "BM_%d : beiscsi_dev_probe-" | |
| 5681 | − "Failed in be_ctrl_init\n"); | |
| 5687 | + "BM_%d : be_ctrl_init failed\n"); | |
| 5682 | 5688 | goto hba_free; |
| 5683 | 5689 | } |
| 5684 | 5690 | |
| 5685 | − /* | |
| 5686 | − * FUNCTION_RESET should clean up any stale info in FW for this fn | |
| 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"); | |
| 5691 | + ret = beiscsi_init_sliport(phba); | |
| 5692 | + if (ret) | |
| 5698 | 5693 | goto hba_free; |
| 5699 | − } | |
| 5700 | 5694 | |
| 5701 | 5695 | spin_lock_init(&phba->io_sgl_lock); |
| 5702 | 5696 | spin_lock_init(&phba->mgmt_sgl_lock); |
| 5703 | − spin_lock_init(&phba->isr_lock); | |
| 5704 | 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 | 5699 | if (ret != 0) { |
| 5707 | 5700 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5708 | 5701 | "BM_%d : Error getting fw config\n"); |
| 5709 | 5702 | goto free_port; |
| 5710 | 5703 | } |
| 5711 | − mgmt_get_port_name(&phba->ctrl, phba); | |
| 5704 | + beiscsi_get_port_name(&phba->ctrl, phba); | |
| 5712 | 5705 | beiscsi_get_params(phba); |
| 5706 | + beiscsi_set_uer_feature(phba); | |
| 5713 | 5707 | |
| 5714 | 5708 | if (enable_msix) |
| 5715 | 5709 | find_num_cpus(phba); |
| @@ -5754,25 +5748,24 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 38 unmodified lines | ||
| 5754 | 5748 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5755 | 5749 | "BM_%d : beiscsi_dev_probe-" |
| 5756 | 5750 | "Failed to allocate work queue\n"); |
| 5751 | + ret = -ENOMEM; | |
| 5757 | 5752 | goto free_twq; |
| 5758 | 5753 | } |
| 5759 | 5754 | |
| 5760 | − INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, | |
| 5761 | − beiscsi_hw_health_check); | |
| 5755 | + INIT_DELAYED_WORK(&phba->eqd_update, beiscsi_eqd_update_work); | |
| 5762 | 5756 | |
| 5763 | 5757 | phwi_ctrlr = phba->phwi_ctrlr; |
| 5764 | 5758 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| 5765 | 5759 | |
| 5766 | 5760 | for (i = 0; i < phba->num_cpus; i++) { |
| 5767 | 5761 | pbe_eq = &phwi_context->be_eq[i]; |
| 5768 | − irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, | |
| 5769 | − be_iopoll); | |
| 5762 | + irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll); | |
| 5770 | 5763 | } |
| 5771 | 5764 | |
| 5772 | 5765 | i = (phba->msix_enabled) ? i : 0; |
| 5773 | 5766 | /* Work item for MCC handling */ |
| 5774 | 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 | 5770 | ret = beiscsi_init_irqs(phba); |
| 5778 | 5771 | if (ret < 0) { |
| @@ -5783,22 +5776,42 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 4 unmodified lines | ||
| 5783 | 5776 | } |
| 5784 | 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 | 5781 | goto free_blkenbld; |
| 5788 | 5782 | |
| 5789 | − if (beiscsi_setup_boot_info(phba)) | |
| 5790 | − /* | |
| 5791 | − * log error but continue, because we may not be using | |
| 5792 | − * iscsi boot. | |
| 5783 | + /* set online bit after port is operational */ | |
| 5784 | + set_bit(BEISCSI_HBA_ONLINE, &phba->state); | |
| 5785 | + __beiscsi_log(phba, KERN_INFO, | |
| 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, | |
| 5795 | − "BM_%d : Could not set up " | |
| 5796 | − "iSCSI boot info.\n"); | |
| 5797 | + set_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state); | |
| 5798 | + } | |
| 5797 | 5799 | |
| 5798 | − beiscsi_create_def_ifaces(phba); | |
| 5799 | − schedule_delayed_work(&phba->beiscsi_hw_check_task, | |
| 5800 | − msecs_to_jiffies(1000)); | |
| 5800 | + beiscsi_iface_create_default(phba); | |
| 5801 | + schedule_delayed_work(&phba->eqd_update, | |
| 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 | 5815 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
| 5803 | 5816 | "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); |
| 5804 | 5817 | return 0; |
| @@ -5810,7 +5823,8 @@ free_blkenbld: · 5 unmodified lines | ||
| 5810 | 5823 | irq_poll_disable(&pbe_eq->iopoll); |
| 5811 | 5824 | } |
| 5812 | 5825 | free_twq: |
| 5813 | − beiscsi_clean_port(phba); | |
| 5826 | + hwi_cleanup_port(phba); | |
| 5827 | + beiscsi_cleanup_port(phba); | |
| 5814 | 5828 | beiscsi_free_mem(phba); |
| 5815 | 5829 | free_port: |
| 5816 | 5830 | pci_free_consistent(phba->pcidev, |
| @@ -5830,6 +5844,49 @@ disable_pci: · 13 unmodified lines | ||
| 5830 | 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 | 5890 | static struct pci_error_handlers beiscsi_eeh_handlers = { |
| 5834 | 5891 | .error_detected = beiscsi_eeh_err_detected, |
| 5835 | 5892 | .slot_reset = beiscsi_eeh_reset, |
| @@ -5846,9 +5903,9 @@ struct iscsi_transport beiscsi_iscsi_transport = { · 10 unmodified lines | ||
| 5846 | 5903 | .create_conn = beiscsi_conn_create, |
| 5847 | 5904 | .bind_conn = beiscsi_conn_bind, |
| 5848 | 5905 | .destroy_conn = iscsi_conn_teardown, |
| 5849 | − .attr_is_visible = be2iscsi_attr_is_visible, | |
| 5850 | − .set_iface_param = be2iscsi_iface_set_param, | |
| 5851 | − .get_iface_param = be2iscsi_iface_get_param, | |
| 5906 | + .attr_is_visible = beiscsi_attr_is_visible, | |
| 5907 | + .set_iface_param = beiscsi_iface_set_param, | |
| 5908 | + .get_iface_param = beiscsi_iface_get_param, | |
| 5852 | 5909 | .set_param = beiscsi_set_param, |
| 5853 | 5910 | .get_conn_param = iscsi_conn_get_param, |
| 5854 | 5911 | .get_session_param = iscsi_session_get_param, |
| @@ -5877,7 +5934,6 @@ static struct pci_driver beiscsi_pci_driver = { · 22 unmodified lines | ||
| 5877 | 5934 | .err_handler = &beiscsi_eeh_handlers |
| 5878 | 5935 | }; |
| 5879 | 5936 | |
| 5880 | − | |
| 5881 | 5937 | static int __init beiscsi_module_init(void) |
| 5882 | 5938 | { |
| 5883 | 5939 | int ret; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /** |
| 2 | − * Copyright (C) 2005 - 2015 Emulex | |
| 2 | + * Copyright (C) 2005 - 2016 Broadcom | |
| 3 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | ||
| 7 | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | 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 | 12 | * Contact Information: |
| 13 | − * linux-drivers@avagotech.com | |
| 13 | + * linux-drivers@broadcom.com | |
| 14 | 14 | * |
| 15 | 15 | * Emulex |
| 16 | 16 | * 3333 Susan Street |
| @@ -36,7 +36,7 @@ · 19 unmodified lines | ||
| 36 | 36 | #include <scsi/scsi_transport_iscsi.h> |
| 37 | 37 | |
| 38 | 38 | #define DRV_NAME "be2iscsi" |
| 39 | −#define BUILD_STR "11.0.0.0" | |
| 39 | +#define BUILD_STR "11.2.0.0" | |
| 40 | 40 | #define BE_NAME "Emulex OneConnect" \ |
| 41 | 41 | "Open-iSCSI Driver version" BUILD_STR |
| 42 | 42 | #define DRV_DESC BE_NAME " " "Driver" |
| @@ -82,36 +82,12 @@ · 39 unmodified lines | ||
| 82 | 82 | #define BEISCSI_MAX_FRAGS_INIT 192 |
| 83 | 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 | 85 | #define BE_SENSE_INFO_SIZE 258 |
| 94 | 86 | #define BE_ISCSI_PDU_HEADER_SIZE 64 |
| 95 | 87 | #define BE_MIN_MEM_SIZE 16384 |
| 96 | 88 | #define MAX_CMD_SZ 65536 |
| 97 | 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 | 92 | * hardware needs the async PDU buffers to be posted in multiples of 8 |
| 117 | 93 | * So have atleast 8 of them by default |
| @@ -378,7 +354,6 @@ struct beiscsi_hba { · 260 unmodified lines | ||
| 378 | 354 | struct sgl_handle **eh_sgl_hndl_base; |
| 379 | 355 | spinlock_t io_sgl_lock; |
| 380 | 356 | spinlock_t mgmt_sgl_lock; |
| 381 | − spinlock_t isr_lock; | |
| 382 | 357 | spinlock_t async_pdu_lock; |
| 383 | 358 | unsigned int age; |
| 384 | 359 | struct list_head hba_queue; |
| @@ -390,7 +365,6 @@ struct beiscsi_hba { · 5 unmodified lines | ||
| 390 | 365 | struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT]; |
| 391 | 366 | struct iscsi_endpoint **ep_array; |
| 392 | 367 | struct beiscsi_conn **conn_table; |
| 393 | − struct iscsi_boot_kset *boot_kset; | |
| 394 | 368 | struct Scsi_Host *shost; |
| 395 | 369 | struct iscsi_iface *ipv4_iface; |
| 396 | 370 | struct iscsi_iface *ipv6_iface; |
| @@ -418,12 +392,33 @@ struct beiscsi_hba { · 21 unmodified lines | ||
| 418 | 392 | unsigned long ulp_supported; |
| 419 | 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 | 412 | u8 optic_state; |
| 423 | − int get_boot; | |
| 424 | − bool fw_timeout; | |
| 425 | − bool ue_detected; | |
| 426 | − struct delayed_work beiscsi_hw_check_task; | |
| 413 | + struct delayed_work eqd_update; | |
| 414 | + /* update EQ delay timer every 1000ms */ | |
| 415 | +#define BEISCSI_EQD_UPDATE_INTERVAL 1000 | |
| 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 | 423 | bool mac_addr_set; |
| 429 | 424 | u8 mac_address[ETH_ALEN]; |
| @@ -435,7 +430,6 @@ struct beiscsi_hba { · 5 unmodified lines | ||
| 435 | 430 | struct be_ctrl_info ctrl; |
| 436 | 431 | unsigned int generation; |
| 437 | 432 | unsigned int interface_handle; |
| 438 | − struct mgmt_session_info boot_sess; | |
| 439 | 433 | struct invalidate_command_table inv_tbl[128]; |
| 440 | 434 | |
| 441 | 435 | struct be_aic_obj aic_obj[MAX_CPUS]; |
| @@ -444,8 +438,29 @@ struct beiscsi_hba { · 2 unmodified lines | ||
| 444 | 438 | struct scatterlist *sg, |
| 445 | 439 | uint32_t num_sg, uint32_t xferlen, |
| 446 | 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 | 464 | struct beiscsi_session { |
| 450 | 465 | struct pci_pool *bhs_pool; |
| 451 | 466 | }; |
| @@ -508,6 +523,7 @@ struct beiscsi_io_task { · 56 unmodified lines | ||
| 508 | 523 | struct sgl_handle *psgl_handle; |
| 509 | 524 | struct beiscsi_conn *conn; |
| 510 | 525 | struct scsi_cmnd *scsi_cmnd; |
| 526 | + int num_sg; | |
| 511 | 527 | struct hwi_wrb_context *pwrb_context; |
| 512 | 528 | unsigned int cmd_sn; |
| 513 | 529 | unsigned int flags; |
| @@ -592,80 +608,81 @@ struct amap_beiscsi_offload_params { · 78 unmodified lines | ||
| 592 | 608 | u8 max_recv_data_segment_length[32]; |
| 593 | 609 | }; |
| 594 | 610 | |
| 595 | −/* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | |
| 596 | − struct beiscsi_hba *phba, struct sol_cqe *psol);*/ | |
| 597 | − | |
| 598 | −struct async_pdu_handle { | |
| 611 | +struct hd_async_handle { | |
| 599 | 612 | struct list_head link; |
| 600 | 613 | struct be_bus_address pa; |
| 601 | 614 | void *pbuffer; |
| 602 | − unsigned int consumed; | |
| 603 | − unsigned char index; | |
| 604 | − unsigned char is_header; | |
| 605 | − unsigned short cri; | |
| 606 | − unsigned long buffer_len; | |
| 615 | + u32 buffer_len; | |
| 616 | + u16 index; | |
| 617 | + u16 cri; | |
| 618 | + u8 is_header; | |
| 619 | + u8 is_final; | |
| 607 | 620 | }; |
| 608 | 621 | |
| 609 | −struct hwi_async_entry { | |
| 610 | − struct { | |
| 611 | − unsigned char hdr_received; | |
| 612 | − unsigned char hdr_len; | |
| 613 | − unsigned short bytes_received; | |
| 622 | +/** | |
| 623 | + * This has list of async PDUs that are waiting to be processed. | |
| 624 | + * Buffers live in this list for a brief duration before they get | |
| 625 | + * processed and posted back to hardware. | |
| 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 | 634 | unsigned int bytes_needed; |
| 615 | 635 | struct list_head list; |
| 616 | − } wait_queue; | |
| 617 | − | |
| 618 | − struct list_head header_busy_list; | |
| 619 | − struct list_head data_busy_list; | |
| 636 | + } wq; | |
| 637 | + /* handles posted to FW resides here */ | |
| 638 | + struct hd_async_handle *header; | |
| 639 | + struct hd_async_handle *data; | |
| 620 | 640 | }; |
| 621 | 641 | |
| 622 | −struct hwi_async_pdu_context { | |
| 623 | − struct { | |
| 624 | − struct be_bus_address pa_base; | |
| 625 | − void *va_base; | |
| 626 | − void *ring_base; | |
| 627 | − struct async_pdu_handle *handle_base; | |
| 628 | − | |
| 629 | − unsigned int host_write_ptr; | |
| 630 | − unsigned int ep_read_ptr; | |
| 631 | − unsigned int writables; | |
| 632 | − | |
| 633 | − unsigned int free_entries; | |
| 634 | − unsigned int busy_entries; | |
| 635 | − | |
| 636 | − struct list_head free_list; | |
| 637 | − } async_header; | |
| 642 | +struct hd_async_buf_context { | |
| 643 | + struct be_bus_address pa_base; | |
| 644 | + void *va_base; | |
| 645 | + void *ring_base; | |
| 646 | + struct hd_async_handle *handle_base; | |
| 647 | + u16 free_entries; | |
| 648 | + u32 buffer_size; | |
| 649 | + /** | |
| 650 | + * Once iSCSI layer finishes processing an async PDU, the | |
| 651 | + * handles used for the PDU are added to this list. | |
| 652 | + * They are posted back to FW in groups of 8. | |
| 653 | + */ | |
| 654 | + struct list_head free_list; | |
| 655 | +}; | |
| 638 | 656 | |
| 639 | − struct { | |
| 640 | − struct be_bus_address pa_base; | |
| 641 | − void *va_base; | |
| 642 | − void *ring_base; | |
| 643 | − struct async_pdu_handle *handle_base; | |
| 644 | − | |
| 645 | − unsigned int host_write_ptr; | |
| 646 | − unsigned int ep_read_ptr; | |
| 647 | − unsigned int writables; | |
| 648 | − | |
| 649 | − unsigned int free_entries; | |
| 650 | − unsigned int busy_entries; | |
| 651 | − struct list_head free_list; | |
| 652 | − } async_data; | |
| 653 | − | |
| 654 | − unsigned int buffer_size; | |
| 655 | − unsigned int num_entries; | |
| 657 | +/** | |
| 658 | + * hd_async_context is declared for each ULP supporting iSCSI function. | |
| 659 | + */ | |
| 660 | +struct hd_async_context { | |
| 661 | + struct hd_async_buf_context async_header; | |
| 662 | + struct hd_async_buf_context async_data; | |
| 663 | + u16 num_entries; | |
| 664 | + /** | |
| 665 | + * When unsol PDU is in, it needs to be chained till all the bytes are | |
| 666 | + * received and then processing is done. hd_async_entry is created | |
| 667 | + * based on the cid_count for each ULP. When unsol PDU comes in based | |
| 668 | + * on the conn_id it needs to be added to the correct async_entry wq. | |
| 669 | + * Below defined cid_to_async_cri_map is used to reterive the | |
| 670 | + * async_cri_map for a particular connection. | |
| 671 | + * | |
| 672 | + * This array is initialized after beiscsi_create_wrb_rings returns. | |
| 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 | 678 | #define BE_GET_ASYNC_CRI_FROM_CID(cid) (pasync_ctx->cid_to_async_cri_map[cid]) |
| 657 | 679 | unsigned short cid_to_async_cri_map[BE_MAX_SESSION]; |
| 658 | 680 | /** |
| 659 | − * This is a varying size list! Do not add anything | |
| 660 | − * after this entry!! | |
| 681 | + * This is a variable size array. Don`t add anything after this field!! | |
| 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 | 686 | struct i_t_dpdu_cqe { |
| 670 | 687 | u32 dw[4]; |
| 671 | 688 | } __packed; |
| @@ -845,7 +862,6 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, · 173 unmodified lines | ||
| 845 | 862 | void |
| 846 | 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 | 865 | void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, |
| 850 | 866 | struct iscsi_task *task); |
| 851 | 867 | |
| @@ -856,11 +872,6 @@ void hwi_ring_cq_db(struct beiscsi_hba *phba, · 4 unmodified lines | ||
| 856 | 872 | unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget); |
| 857 | 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 | 875 | struct pdu_nop_out { |
| 865 | 876 | u32 dw[12]; |
| 866 | 877 | }; |
| @@ -1067,11 +1078,18 @@ struct hwi_context_memory { · 200 unmodified lines | ||
| 1067 | 1078 | struct be_queue_info be_cq[MAX_CPUS - 1]; |
| 1068 | 1079 | |
| 1069 | 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 | 1086 | struct be_queue_info be_def_hdrq[BEISCSI_ULP_COUNT]; |
| 1071 | 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 | 1093 | /* Logging related definitions */ |
| 1076 | 1094 | #define BEISCSI_LOG_INIT 0x0001 /* Initialization events */ |
| 1077 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | ||
| 7 | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | 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 | 12 | * Contact Information: |
| 13 | − * linux-drivers@avagotech.com | |
| 13 | + * linux-drivers@broadcom.com | |
| 14 | 14 | * |
| 15 | 15 | * Emulex |
| 16 | 16 | * 3333 Susan Street |
| @@ -24,139 +24,9 @@ · 7 unmodified lines | ||
| 24 | 24 | #include "be_iscsi.h" |
| 25 | 25 | #include "be_main.h" |
| 26 | 26 | |
| 27 | −/* UE Status Low CSR */ | |
| 28 | −static const char * const desc_ue_status_low[] = { | |
| 29 | − "CEV", | |
| 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) | |
| 27 | +int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, | |
| 28 | + struct be_set_eqd *set_eqd, | |
| 29 | + int num) | |
| 160 | 30 | { |
| 161 | 31 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 162 | 32 | struct be_mcc_wrb *wrb; |
| @@ -174,7 +44,7 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, · 11 unmodified lines | ||
| 174 | 44 | req = embedded_payload(wrb); |
| 175 | 45 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| 176 | 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 | 49 | req->num_eq = cpu_to_le32(num); |
| 180 | 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 | 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 | 59 | be_mcc_notify(phba, tag); |
| 188 | 60 | mutex_unlock(&ctrl->mbox_lock); |
| 189 | 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 | 64 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, |
| 568 | 65 | struct beiscsi_hba *phba, |
| 569 | 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 | 106 | bsg_req->rqst_data.h_vendor.vendor_cmd[0]); |
| 610 | 107 | |
| 611 | 108 | mutex_unlock(&ctrl->mbox_lock); |
| 612 | − return -ENOSYS; | |
| 109 | + return -EPERM; | |
| 613 | 110 | } |
| 614 | 111 | |
| 615 | 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 | 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 | 131 | unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, |
| 677 | 132 | struct invalidate_command_table *inv_tbl, |
| 678 | 133 | unsigned int num_invalidate, unsigned int cid, |
| @@ -844,7 +299,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 165 unmodified lines | ||
| 844 | 299 | nonemb_cmd->size); |
| 845 | 300 | if (dst_addr->sa_family == PF_INET) { |
| 846 | 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 | 303 | req->ip_address.addr[0] = s_addr & 0x000000ff; |
| 849 | 304 | req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; |
| 850 | 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 | 307 | req->tcp_port = ntohs(daddr_in->sin_port); |
| 853 | 308 | beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; |
| 854 | 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 | 311 | } else { |
| 857 | 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 | 314 | memcpy(&req->ip_address.addr, |
| 860 | 315 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); |
| 861 | 316 | req->tcp_port = ntohs(daddr_in6->sin6_port); |
| 862 | 317 | beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); |
| 863 | 318 | memcpy(&beiscsi_ep->dst6_addr, |
| 864 | 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 | 322 | req->cid = cid; |
| 868 | 323 | i = phba->nxt_cqid++; |
| @@ -883,7 +338,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 14 unmodified lines | ||
| 883 | 338 | |
| 884 | 339 | if (!is_chip_be2_be3r(phba)) { |
| 885 | 340 | req->hdr.version = MBX_CMD_VER1; |
| 886 | − req->tcp_window_size = 0; | |
| 341 | + req->tcp_window_size = 0x8000; | |
| 887 | 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 | 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 | 351 | * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd |
| 935 | 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 | 419 | cmd->size = size; |
| 1003 | 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 | 424 | return 0; |
| 1005 | 425 | } |
| 1006 | 426 | |
| 1007 | −static int | |
| 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) | |
| 427 | +unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba) | |
| 1013 | 428 | { |
| 1014 | − struct be_cmd_set_ip_addr_req *req; | |
| 1015 | − struct be_dma_mem nonemb_cmd; | |
| 1016 | − uint32_t ip_type; | |
| 1017 | − int rc; | |
| 429 | + struct be_ctrl_info *ctrl = &phba->ctrl; | |
| 430 | + struct be_mcc_wrb *wrb; | |
| 431 | + struct be_cmd_get_all_if_id_req *req; | |
| 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, | |
| 1020 | − OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, | |
| 1021 | − sizeof(*req)); | |
| 1022 | − if (rc) | |
| 1023 | − return rc; | |
| 436 | + if (mutex_lock_interruptible(&ctrl->mbox_lock)) | |
| 437 | + return -EINTR; | |
| 438 | + wrb = alloc_mcc_wrb(phba, &tag); | |
| 439 | + if (!wrb) { | |
| 440 | + mutex_unlock(&ctrl->mbox_lock); | |
| 441 | + return -ENOMEM; | |
| 442 | + } | |
| 1024 | 443 | |
| 1025 | − ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | |
| 1026 | − BE2_IPV6 : BE2_IPV4 ; | |
| 444 | + req = embedded_payload(wrb); | |
| 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; | |
| 1029 | − req->ip_params.record_entry_count = 1; | |
| 1030 | − req->ip_params.ip_record.action = ip_action; | |
| 1031 | − req->ip_params.ip_record.interface_hndl = | |
| 1032 | − phba->interface_handle; | |
| 1033 | − req->ip_params.ip_record.ip_addr.size_of_structure = | |
| 1034 | − sizeof(struct be_ip_addr_subnet_format); | |
| 1035 | − req->ip_params.ip_record.ip_addr.ip_type = ip_type; | |
| 452 | + status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | |
| 453 | + if (status) { | |
| 454 | + beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
| 455 | + "BG_%d : %s failed: %d\n", __func__, status); | |
| 456 | + return -EBUSY; | |
| 457 | + } | |
| 1036 | 458 | |
| 1037 | − if (ip_action == IP_ACTION_ADD) { | |
| 1038 | − memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value, | |
| 1039 | − sizeof(req->ip_params.ip_record.ip_addr.addr)); | |
| 459 | + pbe_allid = embedded_payload(wrb); | |
| 460 | + /* we now support only one interface per function */ | |
| 461 | + phba->interface_handle = pbe_allid->if_hndl_list[0]; | |
| 1040 | 462 | |
| 1041 | − if (subnet_param) | |
| 1042 | − memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | |
| 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)); | |
| 463 | + return status; | |
| 464 | +} | |
| 1049 | 465 | |
| 1050 | − memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | |
| 1051 | − if_info->ip_addr.subnet_mask, | |
| 1052 | − sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); | |
| 1053 | − } | |
| 466 | +static inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type) | |
| 467 | +{ | |
| 468 | + u32 len; | |
| 1054 | 469 | |
| 1055 | − rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | |
| 1056 | − if (rc < 0) | |
| 1057 | − beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
| 1058 | − "BG_%d : Failed to Modify existing IP Address\n"); | |
| 1059 | − return rc; | |
| 470 | + len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; | |
| 471 | + while (len && !ip[len - 1]) | |
| 472 | + len--; | |
| 473 | + return (len == 0); | |
| 1060 | 474 | } |
| 1061 | 475 | |
| 1062 | −static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, | |
| 1063 | − uint32_t gtway_action, uint32_t param_len) | |
| 476 | +static int beiscsi_if_mod_gw(struct beiscsi_hba *phba, | |
| 477 | + u32 action, u32 ip_type, u8 *gw) | |
| 1064 | 478 | { |
| 1065 | 479 | struct be_cmd_set_def_gateway_req *req; |
| 1066 | 480 | struct be_dma_mem nonemb_cmd; |
| 1067 | 481 | int rt_val; |
| 1068 | 482 | |
| 1069 | − | |
| 1070 | 483 | rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
| 1071 | 484 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY, |
| 1072 | 485 | sizeof(*req)); |
| @@ -1074,200 +487,300 @@ static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, · 1 unmodified line | ||
| 1074 | 487 | return rt_val; |
| 1075 | 488 | |
| 1076 | 489 | req = nonemb_cmd.va; |
| 1077 | − req->action = gtway_action; | |
| 1078 | − req->ip_addr.ip_type = BE2_IPV4; | |
| 490 | + req->action = action; | |
| 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, | |
| 1086 | − struct iscsi_iface_param_info *ip_param, | |
| 1087 | − struct iscsi_iface_param_info *subnet_param, | |
| 1088 | − uint32_t boot_proto) | |
| 528 | +int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type, | |
| 529 | + struct be_cmd_get_def_gateway_resp *resp) | |
| 1089 | 530 | { |
| 1090 | − struct be_cmd_get_def_gateway_resp gtway_addr_set; | |
| 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; | |
| 531 | + struct be_cmd_get_def_gateway_req *req; | |
| 1094 | 532 | struct be_dma_mem nonemb_cmd; |
| 1095 | − uint8_t *gtway_addr; | |
| 1096 | − uint32_t ip_type; | |
| 1097 | 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 | 538 | if (rc) |
| 1101 | 539 | return rc; |
| 1102 | 540 | |
| 1103 | − ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | |
| 1104 | − BE2_IPV6 : BE2_IPV4 ; | |
| 541 | + req = nonemb_cmd.va; | |
| 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 | 559 | if (rc) |
| 1108 | 560 | return rc; |
| 1109 | 561 | |
| 1110 | − if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | |
| 1111 | − if (if_info->dhcp_state) { | |
| 1112 | − beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
| 1113 | − "BG_%d : DHCP Already Enabled\n"); | |
| 1114 | − goto exit; | |
| 1115 | − } | |
| 1116 | − /* The ip_param->len is 1 in DHCP case. Setting | |
| 1117 | − proper IP len as this it is used while | |
| 1118 | − freeing the Static IP. | |
| 1119 | − */ | |
| 1120 | − ip_param->len = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | |
| 1121 | − IP_V6_LEN : IP_V4_LEN; | |
| 1122 | − | |
| 1123 | − } else { | |
| 1124 | − if (if_info->dhcp_state) { | |
| 562 | + req = nonemb_cmd.va; | |
| 563 | + req->ip_params.record_entry_count = 1; | |
| 564 | + req->ip_params.ip_record.action = IP_ACTION_DEL; | |
| 565 | + req->ip_params.ip_record.interface_hndl = | |
| 566 | + phba->interface_handle; | |
| 567 | + req->ip_params.ip_record.ip_addr.size_of_structure = | |
| 568 | + sizeof(struct be_ip_addr_subnet_format); | |
| 569 | + req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type; | |
| 570 | + memcpy(req->ip_params.ip_record.ip_addr.addr, | |
| 571 | + if_info->ip_addr.addr, | |
| 572 | + sizeof(if_info->ip_addr.addr)); | |
| 573 | + memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | |
| 574 | + if_info->ip_addr.subnet_mask, | |
| 575 | + sizeof(if_info->ip_addr.subnet_mask)); | |
| 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)); | |
| 1127 | − rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
| 1128 | − OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, | |
| 1129 | − sizeof(*reldhcp)); | |
| 585 | +static int | |
| 586 | +beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip, | |
| 587 | + u8 *subnet, u32 ip_type) | |
| 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) | |
| 1132 | − goto exit; | |
| 594 | + rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
| 595 | + OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, | |
| 596 | + sizeof(*req)); | |
| 597 | + if (rc) | |
| 598 | + return rc; | |
| 1133 | 599 | |
| 1134 | − reldhcp = nonemb_cmd.va; | |
| 1135 | − reldhcp->interface_hndl = phba->interface_handle; | |
| 1136 | − reldhcp->ip_type = ip_type; | |
| 600 | + req = nonemb_cmd.va; | |
| 601 | + req->ip_params.record_entry_count = 1; | |
| 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); | |
| 1139 | − if (rc < 0) { | |
| 1140 | − beiscsi_log(phba, KERN_WARNING, | |
| 1141 | − BEISCSI_LOG_CONFIG, | |
| 1142 | − "BG_%d : Failed to Delete existing dhcp\n"); | |
| 1143 | − goto exit; | |
| 1144 | − } | |
| 1145 | − } | |
| 614 | + rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | |
| 615 | + /** | |
| 616 | + * In some cases, host needs to look into individual record status | |
| 617 | + * even though FW reported success for that IOCTL. | |
| 618 | + */ | |
| 619 | + if (rc < 0 || req->ip_params.ip_record.status) { | |
| 620 | + __beiscsi_log(phba, KERN_ERR, | |
| 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 */ | |
| 1149 | − if (if_info->ip_addr.addr[0]) { | |
| 1150 | − rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL, | |
| 1151 | − IP_ACTION_DEL); | |
| 629 | +int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type, | |
| 630 | + u8 *ip, u8 *subnet) | |
| 631 | +{ | |
| 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 | 645 | if (rc) |
| 1153 | 646 | goto exit; |
| 1154 | − } | |
| 1155 | 647 | |
| 1156 | − /* Delete the Gateway settings if mode change is to DHCP */ | |
| 1157 | − if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | |
| 1158 | − memset(>way_addr_set, 0, sizeof(gtway_addr_set)); | |
| 1159 | − rc = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set); | |
| 1160 | − if (rc) { | |
| 648 | + reldhcp = nonemb_cmd.va; | |
| 649 | + reldhcp->interface_hndl = phba->interface_handle; | |
| 650 | + reldhcp->ip_type = ip_type; | |
| 651 | + rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | |
| 652 | + if (rc < 0) { | |
| 1161 | 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 | 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 */ | |
| 1181 | − if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | |
| 1182 | − rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
| 1183 | − OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, | |
| 1184 | − sizeof(*dhcpreq)); | |
| 660 | + /* first delete any IP set */ | |
| 661 | + if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { | |
| 662 | + rc = beiscsi_if_clr_ip(phba, if_info); | |
| 1185 | 663 | if (rc) |
| 1186 | 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 | 670 | exit: |
| 1201 | 671 | kfree(if_info); |
| 1202 | 672 | return rc; |
| 1203 | 673 | } |
| 1204 | 674 | |
| 1205 | −int mgmt_set_gateway(struct beiscsi_hba *phba, | |
| 1206 | − struct iscsi_iface_param_info *gateway_param) | |
| 675 | +int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) | |
| 1207 | 676 | { |
| 1208 | − struct be_cmd_get_def_gateway_resp gtway_addr_set; | |
| 1209 | − uint8_t *gtway_addr; | |
| 1210 | − int rt_val; | |
| 677 | + struct be_cmd_get_def_gateway_resp gw_resp; | |
| 678 | + struct be_cmd_get_if_info_resp *if_info; | |
| 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)); | |
| 1213 | − rt_val = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set); | |
| 1214 | − if (rt_val) { | |
| 684 | + rc = beiscsi_if_get_info(phba, ip_type, &if_info); | |
| 685 | + if (rc) | |
| 686 | + return rc; | |
| 687 | + | |
| 688 | + if (if_info->dhcp_state) { | |
| 1215 | 689 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1216 | − "BG_%d : Failed to Get Gateway Addr\n"); | |
| 1217 | − return rt_val; | |
| 690 | + "BG_%d : DHCP Already Enabled\n"); | |
| 691 | + goto exit; | |
| 1218 | 692 | } |
| 1219 | 693 | |
| 1220 | − if (gtway_addr_set.ip_addr.addr[0]) { | |
| 1221 | − gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr; | |
| 1222 | − rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_DEL, | |
| 1223 | − gateway_param->len); | |
| 1224 | − if (rt_val) { | |
| 694 | + /* first delete any IP set */ | |
| 695 | + if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { | |
| 696 | + rc = beiscsi_if_clr_ip(phba, if_info); | |
| 697 | + if (rc) | |
| 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 | 715 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1226 | 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; | |
| 1232 | − rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_ADD, | |
| 1233 | − gateway_param->len); | |
| 721 | + rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
| 722 | + OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, | |
| 723 | + sizeof(*dhcpreq)); | |
| 724 | + if (rc) | |
| 725 | + goto exit; | |
| 1234 | 726 | |
| 1235 | − if (rt_val) | |
| 1236 | − beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | |
| 1237 | − "BG_%d : Failed to Set Gateway Addr\n"); | |
| 727 | + dhcpreq = nonemb_cmd.va; | |
| 728 | + dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */ | |
| 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, | |
| 1243 | − struct be_cmd_get_def_gateway_resp *gateway) | |
| 739 | +/** | |
| 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 | 753 | int rc; |
| 754 | + unsigned int tag; | |
| 1248 | 755 | |
| 1249 | − rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | |
| 1250 | − OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY, | |
| 1251 | − sizeof(*gateway)); | |
| 1252 | − if (rc) | |
| 1253 | − return rc; | |
| 1254 | − | |
| 1255 | − req = nonemb_cmd.va; | |
| 1256 | − req->ip_type = ip_type; | |
| 756 | + tag = be_cmd_set_vlan(phba, vlan_tag); | |
| 757 | + if (!tag) { | |
| 758 | + beiscsi_log(phba, KERN_ERR, | |
| 759 | + (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | |
| 760 | + "BG_%d : VLAN Setting Failed\n"); | |
| 761 | + return -EBUSY; | |
| 762 | + } | |
| 1257 | 763 | |
| 1258 | − return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, gateway, | |
| 1259 | − sizeof(*gateway)); | |
| 764 | + rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); | |
| 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, | |
| 1263 | − struct be_cmd_get_if_info_resp **if_info) | |
| 774 | + | |
| 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 | 778 | struct be_cmd_get_if_info_req *req; |
| 1266 | 779 | struct be_dma_mem nonemb_cmd; |
| 1267 | 780 | uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); |
| 1268 | 781 | int rc; |
| 1269 | 782 | |
| 1270 | − rc = mgmt_get_all_if_id(phba); | |
| 783 | + rc = beiscsi_if_get_handle(phba); | |
| 1271 | 784 | if (rc) |
| 1272 | 785 | return rc; |
| 1273 | 786 | |
| @@ -1364,123 +877,317 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba) · 90 unmodified lines | ||
| 1364 | 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 | |
| 1369 | − * @phba: device priv structure instance | |
| 1370 | − * @s_handle: session handle returned for boot session. | |
| 979 | + * beiscsi_boot_logout_sess()- Logout from boot FW session | |
| 980 | + * @phba: Device priv structure instance | |
| 981 | + * | |
| 982 | + * return | |
| 983 | + * the TAG used for MBOX Command | |
| 1371 | 984 | * |
| 1372 | − * Get the boot target session handle. In case of | |
| 1373 | − * crashdump mode driver has to issue and MBX Cmd | |
| 1374 | − * for FW to login to boot target | |
| 985 | + */ | |
| 986 | +unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba) | |
| 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 | 1021 | * return |
| 1377 | − * Success: 0 | |
| 1378 | − * Failure: Non-Zero value | |
| 1022 | + * the TAG used for MBOX Command | |
| 1379 | 1023 | * |
| 1380 | 1024 | **/ |
| 1381 | −int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, | |
| 1382 | − unsigned int *s_handle) | |
| 1025 | +unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba) | |
| 1383 | 1026 | { |
| 1384 | − struct be_cmd_get_boot_target_resp *boot_resp; | |
| 1027 | + struct be_ctrl_info *ctrl = &phba->ctrl; | |
| 1385 | 1028 | struct be_mcc_wrb *wrb; |
| 1029 | + struct be_cmd_reopen_session_req *req; | |
| 1386 | 1030 | unsigned int tag; |
| 1387 | − uint8_t boot_retry = 3; | |
| 1388 | − int rc; | |
| 1389 | 1031 | |
| 1390 | − do { | |
| 1391 | − /* Get the Boot Target Session Handle and Count*/ | |
| 1392 | − tag = mgmt_get_boot_target(phba); | |
| 1393 | − if (!tag) { | |
| 1394 | − beiscsi_log(phba, KERN_ERR, | |
| 1395 | − BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | |
| 1396 | − "BG_%d : Getting Boot Target Info Failed\n"); | |
| 1397 | − return -EAGAIN; | |
| 1398 | − } | |
| 1032 | + mutex_lock(&ctrl->mbox_lock); | |
| 1033 | + wrb = alloc_mcc_wrb(phba, &tag); | |
| 1034 | + if (!wrb) { | |
| 1035 | + mutex_unlock(&ctrl->mbox_lock); | |
| 1036 | + return 0; | |
| 1037 | + } | |
| 1399 | 1038 | |
| 1400 | − rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | |
| 1401 | − if (rc) { | |
| 1402 | − beiscsi_log(phba, KERN_ERR, | |
| 1403 | − BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
| 1404 | − "BG_%d : MBX CMD get_boot_target Failed\n"); | |
| 1405 | − return -EBUSY; | |
| 1406 | − } | |
| 1039 | + req = embedded_payload(wrb); | |
| 1040 | + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | |
| 1041 | + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | |
| 1042 | + OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS, | |
| 1043 | + sizeof(struct be_cmd_reopen_session_resp)); | |
| 1044 | + req->reopen_type = BE_REOPEN_BOOT_SESSIONS; | |
| 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 */ | |
| 1411 | − if (!boot_resp->boot_session_count) { | |
| 1412 | − beiscsi_log(phba, KERN_INFO, | |
| 1413 | − BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
| 1414 | − "BG_%d ;No boot targets configured\n"); | |
| 1415 | − return -ENXIO; | |
| 1416 | − } | |
| 1051 | + be_mcc_notify(phba, tag); | |
| 1052 | + mutex_unlock(&ctrl->mbox_lock); | |
| 1053 | + return tag; | |
| 1054 | +} | |
| 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 */ | |
| 1425 | − tag = mgmt_reopen_session(phba, BE_REOPEN_BOOT_SESSIONS, | |
| 1426 | − INVALID_SESS_HANDLE); | |
| 1427 | − if (!tag) { | |
| 1428 | − beiscsi_log(phba, KERN_ERR, | |
| 1429 | − BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
| 1430 | − "BG_%d : mgmt_reopen_session Failed\n"); | |
| 1431 | − return -EAGAIN; | |
| 1432 | − } | |
| 1057 | +/** | |
| 1058 | + * beiscsi_boot_get_sinfo()- Get boot session info | |
| 1059 | + * @phba: device priv structure instance | |
| 1060 | + * | |
| 1061 | + * Fetches the boot_struct.s_handle info from FW. | |
| 1062 | + * return | |
| 1063 | + * the TAG used for MBOX Command | |
| 1064 | + * | |
| 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); | |
| 1435 | − if (rc) { | |
| 1436 | − beiscsi_log(phba, KERN_ERR, | |
| 1437 | − BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
| 1438 | − "BG_%d : mgmt_reopen_session Failed"); | |
| 1439 | − return rc; | |
| 1440 | − } | |
| 1441 | − } while (--boot_retry); | |
| 1076 | + mutex_lock(&ctrl->mbox_lock); | |
| 1077 | + wrb = alloc_mcc_wrb(phba, &tag); | |
| 1078 | + if (!wrb) { | |
| 1079 | + mutex_unlock(&ctrl->mbox_lock); | |
| 1080 | + return 0; | |
| 1081 | + } | |
| 1082 | + | |
| 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 */ | |
| 1444 | − beiscsi_log(phba, KERN_ERR, | |
| 1445 | − BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
| 1446 | − "BG_%d : Login to Boot Target Failed\n"); | |
| 1447 | − return -ENXIO; | |
| 1134 | + if (async) { | |
| 1135 | + phba->boot_struct.tag = tag; | |
| 1136 | + set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | |
| 1137 | + ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | |
| 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 | |
| 1452 | − * @phba: device private structure instance | |
| 1453 | − * @vlan_tag: VLAN tag | |
| 1146 | + * beiscsi_boot_get_shandle()- Get boot session handle | |
| 1147 | + * @phba: device priv structure instance | |
| 1148 | + * @s_handle: session handle returned for boot session. | |
| 1454 | 1149 | * |
| 1455 | − * Issue the MBX Cmd and wait for the completion of the | |
| 1456 | − * command. | |
| 1150 | + * return | |
| 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, | |
| 1463 | − uint16_t vlan_tag) | |
| 1155 | +int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle) | |
| 1464 | 1156 | { |
| 1465 | − int rc; | |
| 1157 | + struct be_cmd_get_boot_target_resp *boot_resp; | |
| 1158 | + struct be_mcc_wrb *wrb; | |
| 1466 | 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 | 1165 | if (!tag) { |
| 1470 | 1166 | beiscsi_log(phba, KERN_ERR, |
| 1471 | − (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | |
| 1472 | − "BG_%d : VLAN Setting Failed\n"); | |
| 1473 | − return -EBUSY; | |
| 1167 | + BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | |
| 1168 | + "BG_%d : Getting Boot Target Info Failed\n"); | |
| 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 | 1173 | if (rc) { |
| 1478 | 1174 | beiscsi_log(phba, KERN_ERR, |
| 1479 | − (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | |
| 1480 | − "BS_%d : VLAN MBX Cmd Failed\n"); | |
| 1481 | − return rc; | |
| 1175 | + BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | |
| 1176 | + "BG_%d : MBX CMD get_boot_target Failed\n"); | |
| 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 | 1353 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; |
| 1647 | 1354 | |
| 1648 | − memset(pwrb, 0, sizeof(*pwrb)); | |
| 1649 | 1355 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, |
| 1650 | 1356 | max_send_data_segment_length, pwrb, |
| 1651 | 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 | 1424 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; |
| 1719 | 1425 | |
| 1720 | − memset(pwrb, 0, sizeof(*pwrb)); | |
| 1721 | − | |
| 1722 | 1426 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
| 1723 | 1427 | max_burst_length, pwrb, params->dw[offsetof |
| 1724 | 1428 | (struct amap_beiscsi_offload_params, |
| @@ -1790,70 +1494,3 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, · 65 unmodified lines | ||
| 1790 | 1494 | (params->dw[offsetof(struct amap_beiscsi_offload_params, |
| 1791 | 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 | 3 | * All rights reserved. |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | ||
| 7 | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | 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 | 12 | * Contact Information: |
| 13 | − * linux-drivers@avagotech.com | |
| 13 | + * linux-drivers@broadcom.com | |
| 14 | 14 | * |
| 15 | 15 | * Emulex |
| 16 | 16 | * 3333 Susan Street |
| @@ -96,7 +96,6 @@ struct mcc_wrb { · 79 unmodified lines | ||
| 96 | 96 | struct mcc_wrb_payload payload; |
| 97 | 97 | }; |
| 98 | 98 | |
| 99 | −int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); | |
| 100 | 99 | int mgmt_open_connection(struct beiscsi_hba *phba, |
| 101 | 100 | struct sockaddr *dst_addr, |
| 102 | 101 | struct beiscsi_endpoint *beiscsi_ep, |
| @@ -266,50 +265,41 @@ struct beiscsi_endpoint { · 163 unmodified lines | ||
| 266 | 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 | 268 | unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, |
| 275 | 269 | struct beiscsi_endpoint *beiscsi_ep, |
| 276 | 270 | unsigned short cid, |
| 277 | 271 | unsigned short issue_reset, |
| 278 | 272 | unsigned short savecfg_flag); |
| 279 | 273 | |
| 280 | −int mgmt_set_ip(struct beiscsi_hba *phba, | |
| 281 | − struct iscsi_iface_param_info *ip_param, | |
| 282 | − struct iscsi_iface_param_info *subnet_param, | |
| 283 | − uint32_t boot_proto); | |
| 274 | +int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type); | |
| 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, | |
| 288 | − unsigned int reopen_type, | |
| 289 | − unsigned sess_handle); | |
| 279 | +int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw); | |
| 290 | 280 | |
| 291 | −unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, | |
| 292 | − u32 boot_session_handle, | |
| 293 | − struct be_dma_mem *nonemb_cmd); | |
| 281 | +int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type, | |
| 282 | + struct be_cmd_get_def_gateway_resp *resp); | |
| 294 | 283 | |
| 295 | 284 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, |
| 296 | 285 | struct be_cmd_get_nic_conf_resp *mac); |
| 297 | 286 | |
| 298 | −int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | |
| 299 | − struct be_cmd_get_if_info_resp **if_info); | |
| 287 | +int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type, | |
| 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, | |
| 302 | − struct be_cmd_get_def_gateway_resp *gateway); | |
| 294 | +unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba); | |
| 303 | 295 | |
| 304 | −int mgmt_set_gateway(struct beiscsi_hba *phba, | |
| 305 | − struct iscsi_iface_param_info *gateway_param); | |
| 296 | +unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba); | |
| 306 | 297 | |
| 307 | −int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, | |
| 308 | − unsigned int *s_handle); | |
| 298 | +unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba); | |
| 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 | 304 | ssize_t beiscsi_drvr_ver_disp(struct device *dev, |
| 315 | 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 | 329 | struct wrb_handle *pwrb_handle, |
| 340 | 330 | struct hwi_wrb_context *pwrb_context); |
| 341 | 331 | |
| 342 | −void beiscsi_ue_detect(struct beiscsi_hba *phba); | |
| 343 | 332 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, |
| 344 | 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 | 5827 | bfa_port_speed_t max_speed = 0; |
| 5828 | 5828 | struct bfa_port_attr_s port_attr; |
| 5829 | 5829 | bfa_port_speed_t port_speed, rport_speed; |
| 5830 | − bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); | |
| 5831 | − | |
| 5830 | + bfa_boolean_t trl_enabled; | |
| 5832 | 5831 | |
| 5833 | 5832 | if (port == NULL) |
| 5834 | 5833 | return 0; |
| 5835 | 5834 | |
| 5836 | 5835 | fcs = port->fcs; |
| 5836 | + trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); | |
| 5837 | 5837 | |
| 5838 | 5838 | /* Get Physical port's current speed */ |
| 5839 | 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 | 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 | 259 | struct bnx2fc_mp_req *mp_req; |
| 260 | 260 | struct fc_frame_header *fc_hdr, *fh; |
| @@ -364,7 +364,7 @@ srr_compl_done: · 103 unmodified lines | ||
| 364 | 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 | 369 | struct bnx2fc_cmd *orig_io_req, *new_io_req; |
| 370 | 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 | 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 | 630 | struct bnx2fc_percpu_s *p = arg; |
| 631 | 631 | struct bnx2fc_work *work, *tmp; |
| @@ -1410,9 +1410,10 @@ bind_err: · 778 unmodified lines | ||
| 1410 | 1410 | return NULL; |
| 1411 | 1411 | } |
| 1412 | 1412 | |
| 1413 | −struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, | |
| 1414 | − struct net_device *netdev, | |
| 1415 | − enum fip_state fip_mode) | |
| 1413 | +static struct bnx2fc_interface * | |
| 1414 | +bnx2fc_interface_create(struct bnx2fc_hba *hba, | |
| 1415 | + struct net_device *netdev, | |
| 1416 | + enum fip_state fip_mode) | |
| 1416 | 1417 | { |
| 1417 | 1418 | struct fcoe_ctlr_device *ctlr_dev; |
| 1418 | 1419 | struct bnx2fc_interface *interface; |
| @@ -2765,8 +2766,7 @@ static void __exit bnx2fc_mod_exit(void) · 1346 unmodified lines | ||
| 2765 | 2766 | * held. |
| 2766 | 2767 | */ |
| 2767 | 2768 | mutex_lock(&bnx2fc_dev_lock); |
| 2768 | − list_splice(&adapter_list, &to_be_deleted); | |
| 2769 | − INIT_LIST_HEAD(&adapter_list); | |
| 2769 | + list_splice_init(&adapter_list, &to_be_deleted); | |
| 2770 | 2770 | adapter_count = 0; |
| 2771 | 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 | 999 | struct bnx2fc_work *work; |
| 1000 | 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 | 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 | 1084 | struct bnx2fc_rport *tgt = io_req->tgt; |
| 1085 | 1085 | int rc = SUCCESS; |
| @@ -1721,7 +1721,7 @@ out: · 1720 unmodified lines | ||
| 1721 | 1721 | |
| 1722 | 1722 | /* Wake up waiting threads */ |
| 1723 | 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 | 1945 | ready = csio_is_lnode_ready(ln); |
| 1946 | 1946 | tmo = CSIO_SCSI_ABRT_TMO_MS; |
| 1947 | 1947 | |
| 1948 | + reinit_completion(&ioreq->cmplobj); | |
| 1948 | 1949 | spin_lock_irq(&hw->lock); |
| 1949 | 1950 | rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE)); |
| 1950 | 1951 | spin_unlock_irq(&hw->lock); |
| @@ -1964,8 +1965,6 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd) · 13 unmodified lines | ||
| 1964 | 1965 | goto inval_scmnd; |
| 1965 | 1966 | } |
| 1966 | 1967 | |
| 1967 | − /* Wait for completion */ | |
| 1968 | − init_completion(&ioreq->cmplobj); | |
| 1969 | 1968 | wait_for_completion_timeout(&ioreq->cmplobj, msecs_to_jiffies(tmo)); |
| 1970 | 1969 | |
| 1971 | 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 | 826 | * cxlflash_remove() - PCI entry point to tear down host |
| 838 | 827 | * @pdev: PCI device associated with the host. |
| @@ -844,6 +833,11 @@ static void cxlflash_remove(struct pci_dev *pdev) · 5 unmodified lines | ||
| 844 | 833 | struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); |
| 845 | 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 | 841 | /* If a Task Management Function is active, wait for it to complete |
| 848 | 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 | 1040 | do { |
| 1047 | 1041 | msleep(delay_us / 1000); |
| 1048 | 1042 | status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); |
| 1043 | + if (status == U64_MAX) | |
| 1044 | + nretry /= 2; | |
| 1049 | 1045 | } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE && |
| 1050 | 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 | 1073 | do { |
| 1078 | 1074 | msleep(delay_us / 1000); |
| 1079 | 1075 | status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); |
| 1076 | + if (status == U64_MAX) | |
| 1077 | + nretry /= 2; | |
| 1080 | 1078 | } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE && |
| 1081 | 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 | 1093 | * online. This toggling action can cause this routine to delay up to a few |
| 1096 | 1094 | * seconds. When configured to use the internal LUN feature of the AFU, a |
| 1097 | 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, | |
| 1104 | − u64 wwpn) | |
| 1097 | +static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, | |
| 1098 | + u64 wwpn) | |
| 1105 | 1099 | { |
| 1106 | − int rc = 0; | |
| 1107 | − | |
| 1108 | 1100 | set_port_offline(fc_regs); |
| 1109 | − | |
| 1110 | 1101 | if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 1111 | 1102 | FC_PORT_STATUS_RETRY_CNT)) { |
| 1112 | 1103 | pr_debug("%s: wait on port %d to go offline timed out\n", |
| 1113 | 1104 | __func__, port); |
| 1114 | − rc = -1; /* but continue on to leave the port back online */ | |
| 1115 | 1105 | } |
| 1116 | 1106 | |
| 1117 | − if (rc == 0) | |
| 1118 | − writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); | |
| 1119 | − | |
| 1120 | − /* Always return success after programming WWPN */ | |
| 1121 | − rc = 0; | |
| 1107 | + writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); | |
| 1122 | 1108 | |
| 1123 | 1109 | set_port_online(fc_regs); |
| 1124 | − | |
| 1125 | 1110 | if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 1126 | 1111 | FC_PORT_STATUS_RETRY_CNT)) { |
| 1127 | − pr_err("%s: wait on port %d to go online timed out\n", | |
| 1128 | − __func__, port); | |
| 1112 | + pr_debug("%s: wait on port %d to go online timed out\n", | |
| 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 | 1168 | {SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR}, |
| 1188 | 1169 | {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST}, |
| 1189 | 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 | 1172 | {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET}, |
| 1192 | 1173 | {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0}, |
| 1193 | 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 | 1176 | {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR}, |
| 1196 | 1177 | {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST}, |
| 1197 | 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 | 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 | 1612 | [FC_CRC_THRESH / 8]); |
| 1632 | 1613 | |
| 1633 | 1614 | /* Set WWPNs. If already programmed, wwpn[i] is 0 */ |
| 1634 | − if (wwpn[i] != 0 && | |
| 1635 | − afu_set_wwpn(afu, i, | |
| 1636 | − &afu->afu_map->global.fc_regs[i][0], | |
| 1637 | − 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 | − } | |
| 1615 | + if (wwpn[i] != 0) | |
| 1616 | + afu_set_wwpn(afu, i, | |
| 1617 | + &afu->afu_map->global.fc_regs[i][0], | |
| 1618 | + wwpn[i]); | |
| 1643 | 1619 | /* Programming WWPN back to back causes additional |
| 1644 | 1620 | * offline/online transitions and a PLOGI |
| 1645 | 1621 | */ |
| @@ -2048,6 +2024,11 @@ retry: · 402 unmodified lines | ||
| 2048 | 2024 | * cxlflash_eh_host_reset_handler() - reset the host adapter |
| 2049 | 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 | 2032 | * Return: |
| 2052 | 2033 | * SUCCESS as defined in scsi/scsi.h |
| 2053 | 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 | 2061 | } else |
| 2081 | 2062 | cfg->state = STATE_NORMAL; |
| 2082 | 2063 | wake_up_all(&cfg->reset_waitq); |
| 2083 | − break; | |
| 2064 | + ssleep(1); | |
| 2065 | + /* fall through */ | |
| 2084 | 2066 | case STATE_RESET: |
| 2085 | 2067 | wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); |
| 2086 | 2068 | if (cfg->state == STATE_NORMAL) |
| @@ -2596,6 +2578,9 @@ out_remove: · 509 unmodified lines | ||
| 2596 | 2578 | * @pdev: PCI device struct. |
| 2597 | 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 | 2584 | * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT |
| 2600 | 2585 | */ |
| 2601 | 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 | 2595 | switch (state) { |
| 2611 | 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 | 2601 | cfg->state = STATE_RESET; |
| 2613 | 2602 | scsi_block_requests(cfg->host); |
| 2614 | 2603 | drain_ioctls(cfg); |
| @@ -2685,7 +2674,7 @@ static struct pci_driver cxlflash_driver = { · 70 unmodified lines | ||
| 2685 | 2674 | .id_table = cxlflash_pci_table, |
| 2686 | 2675 | .probe = cxlflash_probe, |
| 2687 | 2676 | .remove = cxlflash_remove, |
| 2688 | − .shutdown = cxlflash_shutdown, | |
| 2677 | + .shutdown = cxlflash_remove, | |
| 2689 | 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 | 709 | * @cfg: Internal structure associated with the host. |
| 710 | 710 | * @ctxi: Context to release. |
| 711 | 711 | * |
| 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 | |
| 714 | − * will be unlocked if necessary before freeing). Also note that the | |
| 715 | − * routine conditionally checks for the existence of the context control | |
| 716 | − * map before clearing the RHT registers and context capabilities because | |
| 717 | − * it is possible to destroy a context while the context is in the error | |
| 718 | − * state (previous mapping was removed [so there is no need to worry about | |
| 719 | − * clearing] and context is waiting for a new mapping). | |
| 712 | + * This routine is safe to be called with a a non-initialized context. | |
| 713 | + * Also note that the routine conditionally checks for the existence | |
| 714 | + * of the context control map before clearing the RHT registers and | |
| 715 | + * context capabilities because it is possible to destroy a context | |
| 716 | + * while the context is in the error state (previous mapping was | |
| 717 | + * removed [so there is no need to worry about clearing] and context | |
| 718 | + * is waiting for a new mapping). | |
| 720 | 719 | */ |
| 721 | 720 | static void destroy_context(struct cxlflash_cfg *cfg, |
| 722 | 721 | struct ctx_info *ctxi) |
| @@ -732,9 +731,6 @@ static void destroy_context(struct cxlflash_cfg *cfg, · 9 unmodified lines | ||
| 732 | 731 | writeq_be(0, &ctxi->ctrl_map->rht_cnt_id); |
| 733 | 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 | 736 | /* Free memory associated with context */ |
| @@ -792,32 +788,58 @@ err: · 51 unmodified lines | ||
| 792 | 788 | * @cfg: Internal structure associated with the host. |
| 793 | 789 | * @ctx: Previously obtained CXL context reference. |
| 794 | 790 | * @ctxid: Previously obtained process element associated with CXL context. |
| 795 | − * @adap_fd: Previously obtained adapter fd associated with CXL context. | |
| 796 | 791 | * @file: Previously obtained file associated with CXL context. |
| 797 | 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 | 794 | static void init_context(struct ctx_info *ctxi, struct cxlflash_cfg *cfg, |
| 803 | − struct cxl_context *ctx, int ctxid, int adap_fd, | |
| 804 | − struct file *file, u32 perms) | |
| 795 | + struct cxl_context *ctx, int ctxid, struct file *file, | |
| 796 | + u32 perms) | |
| 805 | 797 | { |
| 806 | 798 | struct afu *afu = cfg->afu; |
| 807 | 799 | |
| 808 | 800 | ctxi->rht_perms = perms; |
| 809 | 801 | ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl; |
| 810 | 802 | ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); |
| 811 | − ctxi->lfd = adap_fd; | |
| 812 | 803 | ctxi->pid = current->tgid; /* tgid = pid */ |
| 813 | 804 | ctxi->ctx = ctx; |
| 805 | + ctxi->cfg = cfg; | |
| 814 | 806 | ctxi->file = file; |
| 815 | 807 | ctxi->initialized = true; |
| 816 | 808 | mutex_init(&ctxi->mutex); |
| 809 | + kref_init(&ctxi->kref); | |
| 817 | 810 | INIT_LIST_HEAD(&ctxi->luns); |
| 818 | 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 | 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 | 868 | int i; |
| 847 | 869 | int rc = 0; |
| 848 | − int lfd; | |
| 849 | 870 | u64 ctxid = DECODE_CTXID(detach->context_id), |
| 850 | 871 | rctxid = detach->context_id; |
| 851 | 872 | |
| @@ -887,40 +908,13 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev, · 35 unmodified lines | ||
| 887 | 908 | break; |
| 888 | 909 | } |
| 889 | 910 | |
| 890 | − /* Tear down context following last LUN cleanup */ | |
| 891 | − if (list_empty(&ctxi->luns)) { | |
| 892 | − ctxi->unavail = true; | |
| 893 | − mutex_unlock(&ctxi->mutex); | |
| 894 | − mutex_lock(&cfg->ctx_tbl_list_mutex); | |
| 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; | |
| 911 | + /* | |
| 912 | + * Release the context reference and the sdev reference that | |
| 913 | + * bound this LUN to the context. | |
| 914 | + */ | |
| 915 | + if (kref_put(&ctxi->kref, remove_context)) | |
| 907 | 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 | 917 | scsi_device_put(sdev); |
| 923 | − | |
| 924 | 918 | out: |
| 925 | 919 | if (put_ctx) |
| 926 | 920 | put_context(ctxi); |
| @@ -941,34 +935,18 @@ static int cxlflash_disk_detach(struct scsi_device *sdev, · 14 unmodified lines | ||
| 941 | 935 | * |
| 942 | 936 | * This routine is the release handler for the fops registered with |
| 943 | 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 | |
| 945 | − * to the user. Programmatically, the user is not required to perform | |
| 946 | − * the close, as it is handled internally via the detach ioctl when | |
| 947 | − * a context is being removed. Note that nothing prevents the user | |
| 948 | − * from performing a close, but the user should be aware that doing | |
| 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. | |
| 938 | + * when a close (explicity by the user or as part of a process tear | |
| 939 | + * down) is performed on the adapter file descriptor returned to the | |
| 940 | + * user. The user should be aware that explicitly performing a close | |
| 941 | + * considered catastrophic and subsequent usage of the superpipe API | |
| 942 | + * with previously saved off tokens will fail. | |
| 964 | 943 | * |
| 965 | − * Thus, with exception to when the CXL process element (context id) | |
| 966 | − * lookup fails (a case that should theoretically never occur), every | |
| 967 | − * call into this routine results in a complete freeing of a context. | |
| 968 | − * | |
| 969 | − * As part of the detach, all per-context resources associated with the LUN | |
| 970 | − * are cleaned up. When detaching the last LUN for a context, the context | |
| 971 | − * itself is cleaned up and released. | |
| 944 | + * This routine derives the context reference and calls detach for | |
| 945 | + * each LUN associated with the context.The final detach operation | |
| 946 | + * causes the context itself to be freed. With exception to when the | |
| 947 | + * CXL process element (context id) lookup fails (a case that should | |
| 948 | + * theoretically never occur), every call into this routine results | |
| 949 | + * in a complete freeing of a context. | |
| 972 | 950 | * |
| 973 | 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 | 984 | goto out; |
| 1007 | 985 | } |
| 1008 | 986 | |
| 1009 | − dev_dbg(dev, "%s: close(%d) for context %d\n", | |
| 1010 | − __func__, ctxi->lfd, ctxid); | |
| 987 | + dev_dbg(dev, "%s: close for context %d\n", __func__, ctxid); | |
| 1011 | 988 | |
| 1012 | − /* Reset the file descriptor to indicate we're on a close() thread */ | |
| 1013 | − ctxi->lfd = -1; | |
| 1014 | 989 | detach.context_id = ctxi->ctxid; |
| 1015 | 990 | list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) |
| 1016 | 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 | 1085 | goto err; |
| 1111 | 1086 | } |
| 1112 | 1087 | |
| 1113 | − dev_dbg(dev, "%s: fault(%d) for context %d\n", | |
| 1114 | − __func__, ctxi->lfd, ctxid); | |
| 1088 | + dev_dbg(dev, "%s: fault for context %d\n", __func__, ctxid); | |
| 1115 | 1089 | |
| 1116 | 1090 | if (likely(!ctxi->err_recovery_active)) { |
| 1117 | 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 | 1160 | goto out; |
| 1187 | 1161 | } |
| 1188 | 1162 | |
| 1189 | − dev_dbg(dev, "%s: mmap(%d) for context %d\n", | |
| 1190 | − __func__, ctxi->lfd, ctxid); | |
| 1163 | + dev_dbg(dev, "%s: mmap for context %d\n", __func__, ctxid); | |
| 1191 | 1164 | |
| 1192 | 1165 | rc = cxl_fd_mmap(file, vma); |
| 1193 | 1166 | if (likely(!rc)) { |
| @@ -1377,12 +1350,12 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 183 unmodified lines | ||
| 1377 | 1350 | lun_access->lli = lli; |
| 1378 | 1351 | lun_access->sdev = sdev; |
| 1379 | 1352 | |
| 1380 | − /* Non-NULL context indicates reuse */ | |
| 1353 | + /* Non-NULL context indicates reuse (another context reference) */ | |
| 1381 | 1354 | if (ctxi) { |
| 1382 | 1355 | dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n", |
| 1383 | 1356 | __func__, rctxid); |
| 1357 | + kref_get(&ctxi->kref); | |
| 1384 | 1358 | list_add(&lun_access->list, &ctxi->luns); |
| 1385 | − fd = ctxi->lfd; | |
| 1386 | 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 | 1403 | perms = SISL_RHT_PERM(attach->hdr.flags + 1); |
| 1431 | 1404 | |
| 1432 | 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 | 1408 | rc = afu_attach(cfg, ctxi); |
| 1436 | 1409 | if (unlikely(rc)) { |
| @@ -1445,7 +1418,6 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 8 unmodified lines | ||
| 1445 | 1418 | * knows about us yet; we can be the only one holding our mutex. |
| 1446 | 1419 | */ |
| 1447 | 1420 | list_add(&lun_access->list, &ctxi->luns); |
| 1448 | − mutex_unlock(&ctxi->mutex); | |
| 1449 | 1421 | mutex_lock(&cfg->ctx_tbl_list_mutex); |
| 1450 | 1422 | mutex_lock(&ctxi->mutex); |
| 1451 | 1423 | cfg->ctx_tbl[ctxid] = ctxi; |
| @@ -1453,7 +1425,11 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 1 unmodified line | ||
| 1453 | 1425 | fd_install(fd, file); |
| 1454 | 1426 | |
| 1455 | 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 | 1433 | attach->context_id = ctxi->ctxid; |
| 1458 | 1434 | attach->block_size = gli->blk_len; |
| 1459 | 1435 | attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea); |
| @@ -1494,7 +1470,7 @@ err: · 34 unmodified lines | ||
| 1494 | 1470 | file = NULL; |
| 1495 | 1471 | } |
| 1496 | 1472 | |
| 1497 | − /* Cleanup our context; safe to call even with mutex locked */ | |
| 1473 | + /* Cleanup our context */ | |
| 1498 | 1474 | if (ctxi) { |
| 1499 | 1475 | destroy_context(cfg, ctxi); |
| 1500 | 1476 | ctxi = NULL; |
| @@ -1509,16 +1485,19 @@ err: · 8 unmodified lines | ||
| 1509 | 1485 | * recover_context() - recovers a context in error |
| 1510 | 1486 | * @cfg: Internal structure associated with the host. |
| 1511 | 1487 | * @ctxi: Context to release. |
| 1488 | + * @adap_fd: Adapter file descriptor associated with new/recovered context. | |
| 1512 | 1489 | * |
| 1513 | 1490 | * Restablishes the state for a context-in-error. |
| 1514 | 1491 | * |
| 1515 | 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 | 1498 | struct device *dev = &cfg->dev->dev; |
| 1520 | 1499 | int rc = 0; |
| 1521 | − int old_fd, fd = -1; | |
| 1500 | + int fd = -1; | |
| 1522 | 1501 | int ctxid = -1; |
| 1523 | 1502 | struct file *file; |
| 1524 | 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 | 1545 | * No error paths after this point. Once the fd is installed it's |
| 1567 | 1546 | * visible to user space and can't be undone safely on this thread. |
| 1568 | 1547 | */ |
| 1569 | − old_fd = ctxi->lfd; | |
| 1570 | 1548 | ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); |
| 1571 | − ctxi->lfd = fd; | |
| 1572 | 1549 | ctxi->ctx = ctx; |
| 1573 | 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 | 1562 | cfg->ctx_tbl[ctxid] = ctxi; |
| 1586 | 1563 | mutex_unlock(&cfg->ctx_tbl_list_mutex); |
| 1587 | 1564 | fd_install(fd, file); |
| 1588 | − | |
| 1589 | − /* Release the original adapter fd and associated CXL resources */ | |
| 1590 | − sys_close(old_fd); | |
| 1565 | + *adap_fd = fd; | |
| 1591 | 1566 | out: |
| 1592 | 1567 | dev_dbg(dev, "%s: returning ctxid=%d fd=%d rc=%d\n", |
| 1593 | 1568 | __func__, ctxid, fd, rc); |
| @@ -1646,6 +1621,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, · 52 unmodified lines | ||
| 1646 | 1621 | rctxid = recover->context_id; |
| 1647 | 1622 | long reg; |
| 1648 | 1623 | int lretry = 20; /* up to 2 seconds */ |
| 1624 | + int new_adap_fd = -1; | |
| 1649 | 1625 | int rc = 0; |
| 1650 | 1626 | |
| 1651 | 1627 | atomic_inc(&cfg->recovery_threads); |
| @@ -1675,7 +1651,7 @@ retry: · 23 unmodified lines | ||
| 1675 | 1651 | |
| 1676 | 1652 | if (ctxi->err_recovery_active) { |
| 1677 | 1653 | retry_recover: |
| 1678 | − rc = recover_context(cfg, ctxi); | |
| 1654 | + rc = recover_context(cfg, ctxi, &new_adap_fd); | |
| 1679 | 1655 | if (unlikely(rc)) { |
| 1680 | 1656 | dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n", |
| 1681 | 1657 | __func__, ctxid, rc); |
| @@ -1697,9 +1673,9 @@ retry_recover: · 15 unmodified lines | ||
| 1697 | 1673 | |
| 1698 | 1674 | ctxi->err_recovery_active = false; |
| 1699 | 1675 | recover->context_id = ctxi->ctxid; |
| 1700 | − recover->adap_fd = ctxi->lfd; | |
| 1676 | + recover->adap_fd = new_adap_fd; | |
| 1701 | 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 | 1679 | DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET; |
| 1704 | 1680 | goto out; |
| 1705 | 1681 | } |
| @@ -100,13 +100,14 @@ struct ctx_info { · 99 unmodified lines | ||
| 100 | 100 | |
| 101 | 101 | struct cxl_ioctl_start_work work; |
| 102 | 102 | u64 ctxid; |
| 103 | − int lfd; | |
| 104 | 103 | pid_t pid; |
| 105 | 104 | bool initialized; |
| 106 | 105 | bool unavail; |
| 107 | 106 | bool err_recovery_active; |
| 108 | 107 | struct mutex mutex; /* Context protection */ |
| 108 | + struct kref kref; | |
| 109 | 109 | struct cxl_context *ctx; |
| 110 | + struct cxlflash_cfg *cfg; | |
| 110 | 111 | struct list_head luns; /* LUNs attached to this context */ |
| 111 | 112 | const struct vm_operations_struct *cxl_mmap_vmops; |
| 112 | 113 | struct file *file; |
| @@ -1135,14 +1135,13 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 1134 unmodified lines | ||
| 1135 | 1135 | ctxid_dst = DECODE_CTXID(clone->context_id_dst), |
| 1136 | 1136 | rctxid_src = clone->context_id_src, |
| 1137 | 1137 | rctxid_dst = clone->context_id_dst; |
| 1138 | − int adap_fd_src = clone->adap_fd_src; | |
| 1139 | 1138 | int i, j; |
| 1140 | 1139 | int rc = 0; |
| 1141 | 1140 | bool found; |
| 1142 | 1141 | LIST_HEAD(sidecar); |
| 1143 | 1142 | |
| 1144 | − pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu adap_fd_src=%d\n", | |
| 1145 | − __func__, ctxid_src, ctxid_dst, adap_fd_src); | |
| 1143 | + pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu\n", | |
| 1144 | + __func__, ctxid_src, ctxid_dst); | |
| 1146 | 1145 | |
| 1147 | 1146 | /* Do not clone yourself */ |
| 1148 | 1147 | if (unlikely(rctxid_src == rctxid_dst)) { |
| @@ -1166,13 +1165,6 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 17 unmodified lines | ||
| 1166 | 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 | 1168 | /* Verify there is no open resource handle in the destination context */ |
| 1177 | 1169 | for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) |
| 1178 | 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 | 1250 | out_success: |
| 1259 | 1251 | list_splice(&sidecar, &ctxi_dst->luns); |
| 1260 | − sys_close(adap_fd_src); | |
| 1261 | 1252 | |
| 1262 | 1253 | /* fall through */ |
| 1263 | 1254 | out: |
| @@ -583,6 +583,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) · 582 unmodified lines | ||
| 583 | 583 | sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n", |
| 584 | 584 | ALUA_DH_NAME); |
| 585 | 585 | scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); |
| 586 | + kfree(buff); | |
| 586 | 587 | return err; |
| 587 | 588 | } |
| 588 | 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 | 964 | /* initialize the allocated memory */ |
| 965 | 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 | 966 | esas2r_targ_db_initialize(a); |
| 971 | 967 | |
| 972 | 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 | 194 | int length = min(sizeof(struct atto_ioctl), count); |
| 195 | 195 | |
| 196 | 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 | 198 | GFP_KERNEL); |
| 199 | 199 | if (a->local_atto_ioctl == NULL) { |
| 200 | 200 | esas2r_log(ESAS2R_LOG_WARN, |
| @@ -83,6 +83,41 @@ static struct notifier_block libfcoe_notifier = { · 82 unmodified lines | ||
| 83 | 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 | 122 | * fcoe_link_speed_update() - Update the supported and actual link speeds |
| 88 | 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 | 161 | SUPPORTED_40000baseLR4_Full)) |
| 127 | 162 | lport->link_supported_speeds |= FC_PORTSPEED_40GBIT; |
| 128 | 163 | |
| 129 | − switch (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 | − } | |
| 164 | + lport->link_speed = eth2fc_speed(ecmd.base.speed); | |
| 146 | 165 | return 0; |
| 147 | 166 | } |
| 148 | 167 | return -1; |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <scsi/sas_ata.h> |
| 24 | 24 | #include <scsi/libsas.h> |
| 25 | 25 | |
| 26 | −#define DRV_VERSION "v1.5" | |
| 26 | +#define DRV_VERSION "v1.6" | |
| 27 | 27 | |
| 28 | 28 | #define HISI_SAS_MAX_PHYS 9 |
| 29 | 29 | #define HISI_SAS_MAX_QUEUES 32 |
| @@ -56,6 +56,11 @@ enum dev_status { · 26 unmodified lines | ||
| 56 | 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 | 64 | enum hisi_sas_dev_type { |
| 60 | 65 | HISI_SAS_DEV_TYPE_STP = 0, |
| 61 | 66 | HISI_SAS_DEV_TYPE_SSP, |
| @@ -89,6 +94,13 @@ struct hisi_sas_port { · 27 unmodified lines | ||
| 89 | 94 | |
| 90 | 95 | struct hisi_sas_cq { |
| 91 | 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 | 104 | int id; |
| 93 | 105 | }; |
| 94 | 106 | |
| @@ -146,6 +158,9 @@ struct hisi_sas_hw { · 51 unmodified lines | ||
| 146 | 158 | struct hisi_sas_slot *slot); |
| 147 | 159 | int (*prep_stp)(struct hisi_hba *hisi_hba, |
| 148 | 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 | 164 | int (*slot_complete)(struct hisi_hba *hisi_hba, |
| 150 | 165 | struct hisi_sas_slot *slot, int abort); |
| 151 | 166 | void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no); |
| @@ -185,6 +200,7 @@ struct hisi_hba { · 33 unmodified lines | ||
| 185 | 200 | struct Scsi_Host *shost; |
| 186 | 201 | |
| 187 | 202 | struct hisi_sas_cq cq[HISI_SAS_MAX_QUEUES]; |
| 203 | + struct hisi_sas_dq dq[HISI_SAS_MAX_QUEUES]; | |
| 188 | 204 | struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS]; |
| 189 | 205 | struct hisi_sas_port port[HISI_SAS_MAX_PHYS]; |
| 190 | 206 | |
| @@ -17,6 +17,10 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, |
| 19 | 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 | 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 | 97 | slot->task = NULL; |
| 94 | 98 | slot->port = NULL; |
| 95 | 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 | 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 | 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 | 132 | * This function will issue an abort TMF regardless of whether the |
| 121 | 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 | 204 | return rc; |
| 193 | 205 | } |
| 194 | 206 | port = device->port->lldd_port; |
| 195 | − if (port && !port->port_attached && !tmf) { | |
| 196 | − if (sas_protocol_ata(task->task_proto)) { | |
| 197 | − struct task_status_struct *ts = &task->task_status; | |
| 198 | − | |
| 199 | − dev_info(dev, | |
| 200 | − "task prep: SATA/STP port%d not attach device\n", | |
| 201 | − device->port->id); | |
| 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; | |
| 207 | + if (port && !port->port_attached) { | |
| 208 | + dev_info(dev, "task prep: %s port%d not attach device\n", | |
| 209 | + (sas_protocol_ata(task->task_proto)) ? | |
| 210 | + "SATA/STP" : "SAS", | |
| 211 | + device->port->id); | |
| 212 | + | |
| 213 | + return SAS_PHY_DOWN; | |
| 216 | 214 | } |
| 217 | 215 | |
| 218 | 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 | 607 | dev_info(dev, "found dev[%lld:%x] is gone\n", |
| 610 | 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 | 613 | hisi_hba->hw->free_device(hisi_hba, sas_dev); |
| 613 | 614 | device->lldd_dev = NULL; |
| 614 | 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 | 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 | 738 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
| 732 | 739 | task->task_status.stat == SAS_DATA_UNDERRUN) { |
| 733 | 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 | 838 | } else if (task->task_proto & SAS_PROTOCOL_SATA || |
| 830 | 839 | task->task_proto & SAS_PROTOCOL_STP) { |
| 831 | 840 | if (task->dev->dev_type == SAS_SATA_DEV) { |
| 832 | − struct hisi_slot_info *slot = task->lldd_task; | |
| 833 | − | |
| 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; | |
| 841 | + hisi_sas_internal_task_abort(hisi_hba, device, | |
| 842 | + HISI_SAS_INT_ABT_DEV, 0); | |
| 837 | 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 | 854 | out: |
| @@ -954,6 +965,157 @@ static int hisi_sas_query_task(struct sas_task *task) · 110 unmodified lines | ||
| 954 | 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 | 1119 | static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy) |
| 958 | 1120 | { |
| 959 | 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 | 1226 | for (i = 0; i < hisi_hba->queue_count; i++) { |
| 1065 | 1227 | struct hisi_sas_cq *cq = &hisi_hba->cq[i]; |
| 1228 | + struct hisi_sas_dq *dq = &hisi_hba->dq[i]; | |
| 1066 | 1229 | |
| 1067 | 1230 | /* Completion queue structure */ |
| 1068 | 1231 | cq->id = i; |
| 1069 | 1232 | cq->hisi_hba = hisi_hba; |
| 1070 | 1233 | |
| 1234 | + /* Delivery queue structure */ | |
| 1235 | + dq->id = i; | |
| 1236 | + dq->hisi_hba = hisi_hba; | |
| 1237 | + | |
| 1071 | 1238 | /* Delivery queue */ |
| 1072 | 1239 | s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; |
| 1073 | 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 | 1295 | memset(hisi_hba->breakpoint, 0, s); |
| 1129 | 1296 | |
| 1130 | 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 | 1299 | hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL); |
| 1133 | 1300 | if (!hisi_hba->slot_index_tags) |
| 1134 | 1301 | goto err_out; |
| @@ -1272,6 +1439,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, · 137 unmodified lines | ||
| 1272 | 1439 | &hisi_hba->queue_count)) |
| 1273 | 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 | 1448 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1276 | 1449 | hisi_hba->regs = devm_ioremap_resource(dev, res); |
| 1277 | 1450 | if (IS_ERR(hisi_hba->regs)) |
| @@ -1319,13 +1492,6 @@ int hisi_sas_probe(struct platform_device *pdev, · 41 unmodified lines | ||
| 1319 | 1492 | hisi_hba = shost_priv(shost); |
| 1320 | 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 | 1495 | phy_nr = port_nr = hisi_hba->n_phy; |
| 1330 | 1496 | |
| 1331 | 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 | 490 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0, |
| 491 | 491 | __swab32(identify_buffer[0])); |
| 492 | 492 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1, |
| 493 | − identify_buffer[2]); | |
| 493 | + __swab32(identify_buffer[1])); | |
| 494 | 494 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2, |
| 495 | − identify_buffer[1]); | |
| 495 | + __swab32(identify_buffer[2])); | |
| 496 | 496 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3, |
| 497 | − identify_buffer[4]); | |
| 497 | + __swab32(identify_buffer[3])); | |
| 498 | 498 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4, |
| 499 | − identify_buffer[3]); | |
| 499 | + __swab32(identify_buffer[4])); | |
| 500 | 500 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5, |
| 501 | 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 | 504 | static void setup_itct_v1_hw(struct hisi_hba *hisi_hba, |
| 513 | 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 | 766 | msleep(100); |
| 775 | 767 | init_reg_v1_hw(hisi_hba); |
| 776 | 768 | |
| 777 | − init_id_frame_v1_hw(hisi_hba); | |
| 778 | − | |
| 779 | 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 | 865 | static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s) |
| 876 | 866 | { |
| 877 | 867 | struct device *dev = &hisi_hba->pdev->dev; |
| 868 | + struct hisi_sas_dq *dq; | |
| 878 | 869 | u32 r, w; |
| 879 | 870 | int queue = hisi_hba->queue; |
| 880 | 871 | |
| 881 | 872 | while (1) { |
| 882 | − w = hisi_sas_read32_relaxed(hisi_hba, | |
| 883 | − DLVRY_Q_0_WR_PTR + (queue * 0x14)); | |
| 873 | + dq = &hisi_hba->dq[queue]; | |
| 874 | + w = dq->wr_point; | |
| 884 | 875 | r = hisi_sas_read32_relaxed(hisi_hba, |
| 885 | 876 | DLVRY_Q_0_RD_PTR + (queue * 0x14)); |
| 886 | 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 | 895 | int dlvry_queue = hisi_hba->slot_prep->dlvry_queue; |
| 905 | 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, | |
| 908 | − DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), | |
| 909 | − ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS); | |
| 899 | + dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS; | |
| 900 | + hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), | |
| 901 | + dq->wr_point); | |
| 910 | 902 | } |
| 911 | 903 | |
| 912 | 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 | 1557 | struct hisi_sas_complete_v1_hdr *complete_queue = |
| 1566 | 1558 | (struct hisi_sas_complete_v1_hdr *) |
| 1567 | 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 | 1562 | irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); |
| 1571 | 1563 | |
| 1572 | 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 | 1565 | wr_point = hisi_sas_read32(hisi_hba, |
| 1577 | 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 | 1591 | /* update rd_point */ |
| 1592 | + cq->rd_point = rd_point; | |
| 1603 | 1593 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); |
| 1604 | 1594 | |
| 1605 | 1595 | return IRQ_HANDLED; |
| @@ -117,6 +117,8 @@ · 116 unmodified lines | ||
| 117 | 117 | #define SL_CONTROL (PORT_BASE + 0x94) |
| 118 | 118 | #define SL_CONTROL_NOTIFY_EN_OFF 0 |
| 119 | 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 | 122 | #define TX_ID_DWORD0 (PORT_BASE + 0x9c) |
| 121 | 123 | #define TX_ID_DWORD1 (PORT_BASE + 0xa0) |
| 122 | 124 | #define TX_ID_DWORD2 (PORT_BASE + 0xa4) |
| @@ -124,6 +126,9 @@ · 1 unmodified line | ||
| 124 | 126 | #define TX_ID_DWORD4 (PORT_BASE + 0xaC) |
| 125 | 127 | #define TX_ID_DWORD5 (PORT_BASE + 0xb0) |
| 126 | 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 | 132 | #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4) |
| 128 | 133 | #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8) |
| 129 | 134 | #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc) |
| @@ -174,6 +179,10 @@ · 44 unmodified lines | ||
| 174 | 179 | /* HW dma structures */ |
| 175 | 180 | /* Delivery queue header */ |
| 176 | 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 | 186 | #define CMD_HDR_RESP_REPORT_OFF 5 |
| 178 | 187 | #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF) |
| 179 | 188 | #define CMD_HDR_TLR_CTRL_OFF 6 |
| @@ -214,6 +223,8 @@ · 34 unmodified lines | ||
| 214 | 223 | #define CMD_HDR_DIF_SGL_LEN_MSK (0xffff << CMD_HDR_DIF_SGL_LEN_OFF) |
| 215 | 224 | #define CMD_HDR_DATA_SGL_LEN_OFF 16 |
| 216 | 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 | 229 | /* Completion header */ |
| 219 | 230 | /* dw0 */ |
| @@ -221,6 +232,13 @@ · 1 unmodified line | ||
| 221 | 232 | #define CMPLT_HDR_RSPNS_XFRD_MSK (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF) |
| 222 | 233 | #define CMPLT_HDR_ERX_OFF 12 |
| 223 | 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 | 242 | /* dw1 */ |
| 225 | 243 | #define CMPLT_HDR_IPTT_OFF 0 |
| 226 | 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 | 567 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0, |
| 550 | 568 | __swab32(identify_buffer[0])); |
| 551 | 569 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1, |
| 552 | − identify_buffer[2]); | |
| 570 | + __swab32(identify_buffer[1])); | |
| 553 | 571 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2, |
| 554 | − identify_buffer[1]); | |
| 572 | + __swab32(identify_buffer[2])); | |
| 555 | 573 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3, |
| 556 | − identify_buffer[4]); | |
| 574 | + __swab32(identify_buffer[3])); | |
| 557 | 575 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4, |
| 558 | − identify_buffer[3]); | |
| 576 | + __swab32(identify_buffer[4])); | |
| 559 | 577 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5, |
| 560 | 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 | 581 | static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, |
| 572 | 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 | 599 | qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF; |
| 590 | 600 | break; |
| 591 | 601 | case SAS_SATA_DEV: |
| 602 | + case SAS_SATA_PENDING: | |
| 592 | 603 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) |
| 593 | 604 | qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF; |
| 594 | 605 | else |
| @@ -672,9 +683,7 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba) · 77 unmodified lines | ||
| 672 | 683 | else |
| 673 | 684 | reset_val = 0x7ffff; |
| 674 | 685 | |
| 675 | − /* Disable all of the DQ */ | |
| 676 | − for (i = 0; i < HISI_SAS_MAX_QUEUES; i++) | |
| 677 | − hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); | |
| 686 | + hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); | |
| 678 | 687 | |
| 679 | 688 | /* Disable all of the PHYs */ |
| 680 | 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 | 819 | hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855); |
| 811 | 820 | hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908); |
| 812 | 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 | 824 | hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x10); |
| 814 | 825 | hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); |
| 815 | 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 | 912 | msleep(100); |
| 902 | 913 | init_reg_v2_hw(hisi_hba); |
| 903 | 914 | |
| 904 | − init_id_frame_v2_hw(hisi_hba); | |
| 905 | − | |
| 906 | 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 | 962 | static void phys_init_v2_hw(struct hisi_hba *hisi_hba) |
| 954 | 963 | { |
| 955 | − int i; | |
| 956 | 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 | 966 | setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba); |
| 964 | 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 | 1013 | static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s) |
| 1011 | 1014 | { |
| 1012 | 1015 | struct device *dev = &hisi_hba->pdev->dev; |
| 1016 | + struct hisi_sas_dq *dq; | |
| 1013 | 1017 | u32 r, w; |
| 1014 | 1018 | int queue = hisi_hba->queue; |
| 1015 | 1019 | |
| 1016 | 1020 | while (1) { |
| 1017 | − w = hisi_sas_read32_relaxed(hisi_hba, | |
| 1018 | − DLVRY_Q_0_WR_PTR + (queue * 0x14)); | |
| 1021 | + dq = &hisi_hba->dq[queue]; | |
| 1022 | + w = dq->wr_point; | |
| 1019 | 1023 | r = hisi_sas_read32_relaxed(hisi_hba, |
| 1020 | 1024 | DLVRY_Q_0_RD_PTR + (queue * 0x14)); |
| 1021 | 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 | 1043 | int dlvry_queue = hisi_hba->slot_prep->dlvry_queue; |
| 1040 | 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 | 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 | 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 | 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 | 1596 | if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) && |
| 1567 | 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 | 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 | 1834 | static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) |
| 1779 | 1835 | { |
| 1780 | 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 | 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 | 1877 | sas_phy->linkrate = link_rate; |
| 1825 | 1878 | hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, |
| 1826 | 1879 | HARD_PHY_LINKRATE); |
| @@ -1855,16 +1908,21 @@ end: · 28 unmodified lines | ||
| 1855 | 1908 | static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) |
| 1856 | 1909 | { |
| 1857 | 1910 | int res = 0; |
| 1858 | − u32 phy_cfg, phy_state; | |
| 1911 | + u32 phy_state, sl_ctrl, txid_auto; | |
| 1859 | 1912 | |
| 1860 | 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 | 1915 | phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); |
| 1865 | − | |
| 1866 | 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 | 1926 | hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK); |
| 1869 | 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 | 2044 | struct hisi_sas_slot *slot; |
| 1987 | 2045 | struct hisi_sas_itct *itct; |
| 1988 | 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 | 2048 | int queue = cq->id; |
| 1991 | 2049 | |
| 1992 | 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 | 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 | 2055 | wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + |
| 2000 | 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 | 2101 | /* update rd_point */ |
| 2102 | + cq->rd_point = rd_point; | |
| 2046 | 2103 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); |
| 2047 | 2104 | return IRQ_HANDLED; |
| 2048 | 2105 | } |
| @@ -2239,6 +2296,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { · 190 unmodified lines | ||
| 2239 | 2296 | .prep_smp = prep_smp_v2_hw, |
| 2240 | 2297 | .prep_ssp = prep_ssp_v2_hw, |
| 2241 | 2298 | .prep_stp = prep_ata_v2_hw, |
| 2299 | + .prep_abort = prep_abort_v2_hw, | |
| 2242 | 2300 | .get_free_slot = get_free_slot_v2_hw, |
| 2243 | 2301 | .start_delivery = start_delivery_v2_hw, |
| 2244 | 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 | 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 | 250 | * Increase usage count temporarily here so that calling |
| 255 | 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 | 256 | pm_runtime_enable(&shost->shost_gendev); |
| 261 | 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 | 263 | scsi_host_set_state(shost, SHOST_RUNNING); |
| 264 | 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 | 309 | out_del_gendev: |
| 310 | 310 | device_del(&shost->shost_gendev); |
| 311 | 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 | 316 | scsi_destroy_command_freelist(shost); |
| 313 | 317 | out_destroy_tags: |
| 314 | 318 | if (shost_use_blk_mq(shost)) |
| @@ -293,6 +293,8 @@ static int detect_controller_lockup(struct ctlr_info *h); · 292 unmodified lines | ||
| 293 | 293 | static void hpsa_disable_rld_caching(struct ctlr_info *h); |
| 294 | 294 | static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, |
| 295 | 295 | struct ReportExtendedLUNdata *buf, int bufsize); |
| 296 | +static bool hpsa_vpd_page_supported(struct ctlr_info *h, | |
| 297 | + unsigned char scsi3addr[], u8 page); | |
| 296 | 298 | static int hpsa_luns_changed(struct ctlr_info *h); |
| 297 | 299 | static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c, |
| 298 | 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 | 2390 | struct CommandList *c, struct scsi_cmnd *cmd) |
| 2389 | 2391 | { |
| 2390 | 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 | 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 | 2492 | ei = cp->err_info; |
| 2490 | 2493 | cmd = cp->scsi_cmd; |
| 2491 | 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 | 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 | 2506 | c2 = &h->ioaccel2_cmd_pool[cp->cmdindex]; |
| 2494 | 2507 | |
| 2495 | 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 | 2517 | cmd->result = (DID_OK << 16); /* host byte */ |
| 2505 | 2518 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ |
| 2506 | 2519 | |
| 2507 | − if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1) | |
| 2508 | − atomic_dec(&cp->phys_disk->ioaccel_cmds_out); | |
| 2520 | + if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1) { | |
| 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 | 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 | 3094 | buf = kzalloc(64, GFP_KERNEL); |
| 3075 | 3095 | if (!buf) |
| 3076 | 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 | 3105 | if (rc == 0) |
| 3079 | 3106 | *raid_level = buf[8]; |
| 3080 | 3107 | if (*raid_level > RAID_UNKNOWN) |
| 3081 | 3108 | *raid_level = RAID_UNKNOWN; |
| 3109 | +exit: | |
| 3082 | 3110 | kfree(buf); |
| 3083 | 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 | 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 | 3468 | unsigned char scsi3addr[], u8 page) |
| 3441 | 3469 | { |
| 3442 | 3470 | int rc; |
| @@ -3446,7 +3474,7 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h, · 3 unmodified lines | ||
| 3446 | 3474 | |
| 3447 | 3475 | buf = kzalloc(256, GFP_KERNEL); |
| 3448 | 3476 | if (!buf) |
| 3449 | − return 0; | |
| 3477 | + return false; | |
| 3450 | 3478 | |
| 3451 | 3479 | /* Get the size of the page list first */ |
| 3452 | 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 | 3501 | goto exit_supported; |
| 3474 | 3502 | exit_unsupported: |
| 3475 | 3503 | kfree(buf); |
| 3476 | − return 0; | |
| 3504 | + return false; | |
| 3477 | 3505 | exit_supported: |
| 3478 | 3506 | kfree(buf); |
| 3479 | − return 1; | |
| 3507 | + return true; | |
| 3480 | 3508 | } |
| 3481 | 3509 | |
| 3482 | 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 | 3553 | int rc; |
| 3526 | 3554 | unsigned char *buf; |
| 3527 | 3555 | |
| 3528 | − if (buflen > 16) | |
| 3529 | − buflen = 16; | |
| 3556 | + /* Does controller have VPD for device id? */ | |
| 3557 | + if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_DEVICE_ID)) | |
| 3558 | + return 1; /* not supported */ | |
| 3559 | + | |
| 3530 | 3560 | buf = kzalloc(64, GFP_KERNEL); |
| 3531 | 3561 | if (!buf) |
| 3532 | 3562 | return -ENOMEM; |
| 3533 | − rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64); | |
| 3534 | − if (rc == 0) | |
| 3535 | − memcpy(device_id, &buf[index], buflen); | |
| 3563 | + | |
| 3564 | + rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | | |
| 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 | 3572 | kfree(buf); |
| 3538 | 3573 | |
| 3539 | − return rc != 0; | |
| 3574 | + return rc; /*0 - got id, otherwise, didn't */ | |
| 3540 | 3575 | } |
| 3541 | 3576 | |
| 3542 | 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 | 3842 | sizeof(this_device->model)); |
| 3808 | 3843 | memset(this_device->device_id, 0, |
| 3809 | 3844 | sizeof(this_device->device_id)); |
| 3810 | − hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, | |
| 3811 | − sizeof(this_device->device_id)); | |
| 3845 | + if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, | |
| 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 | 3855 | if ((this_device->devtype == TYPE_DISK || |
| 3814 | 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 | 4076 | struct bmic_identify_physical_device *id_phys) |
| 4035 | 4077 | { |
| 4036 | 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 | 4091 | dev->ioaccel_handle = rle->ioaccel_handle; |
| 4040 | 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 | 4322 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, |
| 4271 | 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 | 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 | 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 | 4355 | figure_bus_target_lun(h, lunaddrbytes, tmpdevice); |
| 4304 | 4356 | hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); |
| 4305 | 4357 | this_device = currentsd[ncurrent]; |
| @@ -4513,7 +4565,9 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len) · 207 unmodified lines | ||
| 4513 | 4565 | case READ_6: |
| 4514 | 4566 | case READ_12: |
| 4515 | 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 | 4571 | block_cnt = cdb[4]; |
| 4518 | 4572 | if (block_cnt == 0) |
| 4519 | 4573 | block_cnt = 256; |
| @@ -4638,6 +4692,9 @@ static int hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h, · 118 unmodified lines | ||
| 4638 | 4692 | struct scsi_cmnd *cmd = c->scsi_cmd; |
| 4639 | 4693 | struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; |
| 4640 | 4694 | |
| 4695 | + if (!dev) | |
| 4696 | + return -1; | |
| 4697 | + | |
| 4641 | 4698 | c->phys_disk = dev; |
| 4642 | 4699 | |
| 4643 | 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 | 4728 | switch (cmd->cmnd[0]) { |
| 4672 | 4729 | /* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */ |
| 4673 | − case WRITE_6: | |
| 4674 | 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 | 4735 | break; |
| 4677 | 4736 | case WRITE_10: |
| 4678 | 4737 | case READ_10: |
| @@ -4714,6 +4773,12 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, · 35 unmodified lines | ||
| 4714 | 4773 | u32 len; |
| 4715 | 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 | 4782 | BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); |
| 4718 | 4783 | |
| 4719 | 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 | 4887 | struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len, |
| 4823 | 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 | 4896 | /* Try to honor the device's queue depth */ |
| 4826 | 4897 | if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) > |
| 4827 | 4898 | phys_disk->queue_depth) { |
| @@ -4902,12 +4973,17 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, · 74 unmodified lines | ||
| 4902 | 4973 | #endif |
| 4903 | 4974 | int offload_to_mirror; |
| 4904 | 4975 | |
| 4976 | + if (!dev) | |
| 4977 | + return -1; | |
| 4978 | + | |
| 4905 | 4979 | /* check for valid opcode, get LBA and block count */ |
| 4906 | 4980 | switch (cmd->cmnd[0]) { |
| 4907 | 4981 | case WRITE_6: |
| 4908 | 4982 | is_write = 1; |
| 4909 | 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 | 4987 | block_cnt = cmd->cmnd[4]; |
| 4912 | 4988 | if (block_cnt == 0) |
| 4913 | 4989 | block_cnt = 256; |
| @@ -5314,6 +5390,9 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h, · 400 unmodified lines | ||
| 5314 | 5390 | struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; |
| 5315 | 5391 | int rc = IO_ACCEL_INELIGIBLE; |
| 5316 | 5392 | |
| 5393 | + if (!dev) | |
| 5394 | + return SCSI_MLQUEUE_HOST_BUSY; | |
| 5395 | + | |
| 5317 | 5396 | cmd->host_scribble = (unsigned char *) c; |
| 5318 | 5397 | |
| 5319 | 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 | 5931 | struct scsi_cmnd *scmd = command_to_abort->scsi_cmd; |
| 5853 | 5932 | struct hpsa_scsi_dev_t *dev = scmd->device->hostdata; |
| 5854 | 5933 | |
| 5934 | + if (!dev) | |
| 5935 | + return; | |
| 5936 | + | |
| 5855 | 5937 | /* |
| 5856 | 5938 | * We're overlaying struct hpsa_tmf_struct on top of something which |
| 5857 | 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 | 6017 | "Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", |
| 5936 | 6018 | psa[0], psa[1], psa[2], psa[3], |
| 5937 | 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 | 6021 | if (rc != 0) { |
| 5940 | 6022 | dev_warn(&h->pdev->dev, |
| 5941 | 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 | 6054 | struct io_accel2_cmd *c2; |
| 5973 | 6055 | |
| 5974 | 6056 | dev = abort->scsi_cmd->device->hostdata; |
| 6057 | + if (!dev) | |
| 6058 | + return -1; | |
| 6059 | + | |
| 5975 | 6060 | if (!dev->offload_enabled && !dev->hba_ioaccel_enabled) |
| 5976 | 6061 | return -1; |
| 5977 | 6062 | |
| @@ -312,7 +312,6 @@ struct offline_device_entry { · 311 unmodified lines | ||
| 312 | 312 | #define HPSA_DEVICE_RESET_MSG 1 |
| 313 | 313 | #define HPSA_RESET_TYPE_CONTROLLER 0x00 |
| 314 | 314 | #define HPSA_RESET_TYPE_BUS 0x01 |
| 315 | −#define HPSA_RESET_TYPE_TARGET 0x03 | |
| 316 | 315 | #define HPSA_RESET_TYPE_LUN 0x04 |
| 317 | 316 | #define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */ |
| 318 | 317 | #define HPSA_MSG_SEND_RETRY_LIMIT 10 |
| @@ -157,6 +157,7 @@ · 156 unmodified lines | ||
| 157 | 157 | |
| 158 | 158 | /* VPD Inquiry types */ |
| 159 | 159 | #define HPSA_VPD_SUPPORTED_PAGES 0x00 |
| 160 | +#define HPSA_VPD_LV_DEVICE_ID 0x83 | |
| 160 | 161 | #define HPSA_VPD_LV_DEVICE_GEOMETRY 0xC1 |
| 161 | 162 | #define HPSA_VPD_LV_IOACCEL_STATUS 0xC2 |
| 162 | 163 | #define HPSA_VPD_LV_STATUS 0xC3 |
| @@ -52,6 +52,7 @@ static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT; · 51 unmodified lines | ||
| 52 | 52 | static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS; |
| 53 | 53 | static unsigned int ibmvfc_debug = IBMVFC_DEBUG; |
| 54 | 54 | static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL; |
| 55 | +static unsigned int cls3_error = IBMVFC_CLS3_ERROR; | |
| 55 | 56 | static LIST_HEAD(ibmvfc_head); |
| 56 | 57 | static DEFINE_SPINLOCK(ibmvfc_driver_lock); |
| 57 | 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 | 87 | module_param_named(log_level, log_level, uint, 0); |
| 87 | 88 | MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. " |
| 88 | 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 | 94 | static const struct { |
| 91 | 95 | u16 status; |
| @@ -717,7 +721,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) · 625 unmodified lines | ||
| 717 | 721 | spin_lock_irqsave(vhost->host->host_lock, flags); |
| 718 | 722 | vhost->state = IBMVFC_NO_CRQ; |
| 719 | 723 | vhost->logged_in = 0; |
| 720 | − ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); | |
| 721 | 724 | |
| 722 | 725 | /* Clean out the queue */ |
| 723 | 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 | 1338 | struct srp_direct_buf *data = &vfc_cmd->ioba; |
| 1336 | 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 | 1344 | sg_mapped = scsi_dma_map(scmd); |
| 1339 | 1345 | if (!sg_mapped) { |
| 1340 | 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 | 3387 | prli->parms.type = IBMVFC_SCSI_FCP_TYPE; |
| 3382 | 3388 | prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR); |
| 3383 | 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 | 3395 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); |
| 3386 | 3396 | if (ibmvfc_send_event(evt, vhost, default_timeout)) { |
| @@ -54,6 +54,7 @@ · 53 unmodified lines | ||
| 54 | 54 | #define IBMVFC_DEV_LOSS_TMO (5 * 60) |
| 55 | 55 | #define IBMVFC_DEFAULT_LOG_LEVEL 2 |
| 56 | 56 | #define IBMVFC_MAX_CDB_LEN 16 |
| 57 | +#define IBMVFC_CLS3_ERROR 0 | |
| 57 | 58 | |
| 58 | 59 | /* |
| 59 | 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 | 1607 | if (!(vscsi->flags & RESPONSE_Q_DOWN)) { |
| 1608 | 1608 | list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) { |
| 1609 | − pr_debug("send_messages cmd %p\n", cmd); | |
| 1610 | − | |
| 1611 | 1609 | iue = cmd->iue; |
| 1612 | 1610 | |
| 1613 | 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 | 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 | 1937 | transport_deregister_session(se_sess); |
| 1938 | 1938 | tport->ibmv_nexus = NULL; |
| 1939 | 1939 | kfree(nexus); |
| @@ -1978,7 +1978,7 @@ static long ibmvscsis_srp_login(struct scsi_info *vscsi, · 38 unmodified lines | ||
| 1978 | 1978 | reason = SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED; |
| 1979 | 1979 | else if (fmt->buffers & (~SUPPORTED_FORMATS)) |
| 1980 | 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 | 1982 | reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT; |
| 1983 | 1983 | |
| 1984 | 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 | 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 | 2557 | rc = target_submit_cmd(&cmd->se_cmd, nexus->se_sess, srp->cdb, |
| 2562 | 2558 | cmd->sense_buf, scsilun_to_int(&srp->lun), |
| 2563 | 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 | 3138 | long tx_len; |
| 3143 | 3139 | long rc = 0; |
| 3144 | 3140 | |
| 3145 | − pr_debug("rdma: dir %d, bytes 0x%x\n", dir, bytes); | |
| 3146 | − | |
| 3147 | 3141 | if (bytes == 0) |
| 3148 | 3142 | return 0; |
| 3149 | 3143 | |
| @@ -3192,12 +3186,6 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg, · 42 unmodified lines | ||
| 3192 | 3186 | vscsi->dds.window[LOCAL].liobn, |
| 3193 | 3187 | server_ioba); |
| 3194 | 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 | 3189 | /* The h_copy_rdma will cause phyp, running in another |
| 3202 | 3190 | * partition, to read memory, so we need to make sure |
| 3203 | 3191 | * the data has been written out, hence these syncs. |
| @@ -3322,12 +3310,9 @@ cmd_work: · 118 unmodified lines | ||
| 3322 | 3310 | rc = ibmvscsis_trans_event(vscsi, crq); |
| 3323 | 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 | 3314 | * everything but transport events on the queue |
| 3327 | − */ | |
| 3328 | − pr_debug("handle_crq, ignoring\n"); | |
| 3329 | − | |
| 3330 | − /* | |
| 3315 | + * | |
| 3331 | 3316 | * need to decrement the queue index so we can |
| 3332 | 3317 | * look at the elment again |
| 3333 | 3318 | */ |
| @@ -3461,6 +3446,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev, · 127 unmodified lines | ||
| 3461 | 3446 | vscsi->map_ioba = dma_map_single(&vdev->dev, vscsi->map_buf, PAGE_SIZE, |
| 3462 | 3447 | DMA_BIDIRECTIONAL); |
| 3463 | 3448 | if (dma_mapping_error(&vdev->dev, vscsi->map_ioba)) { |
| 3449 | + rc = -ENOMEM; | |
| 3464 | 3450 | dev_err(&vscsi->dev, "probe: error mapping command buffer\n"); |
| 3465 | 3451 | goto free_buf; |
| 3466 | 3452 | } |
| @@ -3693,12 +3679,9 @@ static void ibmvscsis_release_cmd(struct se_cmd *se_cmd) · 226 unmodified lines | ||
| 3693 | 3679 | se_cmd); |
| 3694 | 3680 | struct scsi_info *vscsi = cmd->adapter; |
| 3695 | 3681 | |
| 3696 | − pr_debug("release_cmd %p, flags %d\n", se_cmd, cmd->flags); | |
| 3697 | − | |
| 3698 | 3682 | spin_lock_bh(&vscsi->intr_lock); |
| 3699 | 3683 | /* Remove from active_q */ |
| 3700 | − list_del(&cmd->list); | |
| 3701 | − list_add_tail(&cmd->list, &vscsi->waiting_rsp); | |
| 3684 | + list_move_tail(&cmd->list, &vscsi->waiting_rsp); | |
| 3702 | 3685 | ibmvscsis_send_messages(vscsi); |
| 3703 | 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 | 3698 | struct iu_entry *iue = cmd->iue; |
| 3716 | 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 | 3701 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, |
| 3722 | 3702 | 1, 1); |
| 3723 | 3703 | if (rc) { |
| @@ -3756,9 +3736,6 @@ static int ibmvscsis_queue_data_in(struct se_cmd *se_cmd) · 32 unmodified lines | ||
| 3756 | 3736 | uint len = 0; |
| 3757 | 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 | 3739 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 1, |
| 3763 | 3740 | 1); |
| 3764 | 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 | 493 | "9072: Link not operational transition"}, |
| 494 | 494 | {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, |
| 495 | 495 | "9032: Array exposed but still protected"}, |
| 496 | − {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1, | |
| 496 | + {0x066B8300, 0, IPR_DEBUG_LOG_LEVEL, | |
| 497 | 497 | "70DD: Device forced failed by disrupt device command"}, |
| 498 | 498 | {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, |
| 499 | 499 | "4061: Multipath redundancy level got better"}, |
| 500 | 500 | {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, |
| 501 | 501 | "4060: Multipath redundancy level got worse"}, |
| 502 | − {0x06808100, 0, IPR_DEFAULT_LOG_LEVEL, | |
| 502 | + {0x06808100, 0, IPR_DEBUG_LOG_LEVEL, | |
| 503 | 503 | "9083: Device raw mode enabled"}, |
| 504 | − {0x06808200, 0, IPR_DEFAULT_LOG_LEVEL, | |
| 504 | + {0x06808200, 0, IPR_DEBUG_LOG_LEVEL, | |
| 505 | 505 | "9084: Device raw mode disabled"}, |
| 506 | 506 | {0x07270000, 0, 0, |
| 507 | 507 | "Failure due to other device"}, |
| @@ -1473,7 +1473,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) · 965 unmodified lines | ||
| 1473 | 1473 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
| 1474 | 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 | 1477 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
| 1478 | 1478 | |
| 1479 | 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 | 2573 | * ipr_process_error - Op done function for an adapter error log. |
| 2557 | 2574 | * @ipr_cmd: ipr command struct |
| @@ -2569,13 +2586,14 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) · 11 unmodified lines | ||
| 2569 | 2586 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
| 2570 | 2587 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
| 2571 | 2588 | u32 fd_ioasc; |
| 2589 | + char *envp[] = { "ASYNC_ERR_LOG=1", NULL }; | |
| 2572 | 2590 | |
| 2573 | 2591 | if (ioa_cfg->sis64) |
| 2574 | 2592 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc); |
| 2575 | 2593 | else |
| 2576 | 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 | 2597 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
| 2580 | 2598 | |
| 2581 | 2599 | if (!ioasc) { |
| @@ -2588,6 +2606,10 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) · 6 unmodified lines | ||
| 2588 | 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 | 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 | 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 | 4178 | static struct device_attribute *ipr_ioa_attrs[] = { |
| 4099 | 4179 | &ipr_fw_version_attr, |
| 4100 | 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 | 7107 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
| 7028 | 7108 | struct ipr_resource_entry *res; |
| 7029 | − struct ipr_hostrcb *hostrcb, *temp; | |
| 7030 | − int i = 0, j; | |
| 7109 | + int j; | |
| 7031 | 7110 | |
| 7032 | 7111 | ENTER; |
| 7033 | 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 | 7128 | schedule_work(&ioa_cfg->work_q); |
| 7050 | 7129 | |
| 7051 | − list_for_each_entry_safe(hostrcb, temp, &ioa_cfg->hostrcb_free_q, queue) { | |
| 7052 | − list_del(&hostrcb->queue); | |
| 7053 | − if (i++ < IPR_NUM_LOG_HCAMS) | |
| 7054 | − ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb); | |
| 7130 | + for (j = 0; j < IPR_NUM_HCAMS; j++) { | |
| 7131 | + list_del_init(&ioa_cfg->hostrcb[j]->queue); | |
| 7132 | + if (j < IPR_NUM_LOG_HCAMS) | |
| 7133 | + ipr_send_hcam(ioa_cfg, | |
| 7134 | + IPR_HCAM_CDB_OP_CODE_LOG_DATA, | |
| 7135 | + ioa_cfg->hostrcb[j]); | |
| 7055 | 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 | 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 | 8050 | ENTER; |
| 7968 | 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 | 8055 | if (ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num) { |
| 7972 | 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 | 8420 | hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next, |
| 8337 | 8421 | struct ipr_hostrcb, queue); |
| 8338 | − list_del(&hostrcb->queue); | |
| 8422 | + list_del_init(&hostrcb->queue); | |
| 8339 | 8423 | memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam)); |
| 8340 | 8424 | |
| 8341 | 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 | 9416 | dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size, |
| 9333 | 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 | 9420 | dma_free_coherent(&ioa_cfg->pdev->dev, |
| 9337 | 9421 | sizeof(struct ipr_hostrcb), |
| 9338 | 9422 | ioa_cfg->hostrcb[i], |
| @@ -9572,7 +9656,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) · 233 unmodified lines | ||
| 9572 | 9656 | if (!ioa_cfg->u.cfg_table) |
| 9573 | 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 | 9660 | ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev, |
| 9577 | 9661 | sizeof(struct ipr_hostrcb), |
| 9578 | 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 | 9799 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_free_q); |
| 9716 | 9800 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); |
| 9801 | + INIT_LIST_HEAD(&ioa_cfg->hostrcb_report_q); | |
| 9717 | 9802 | INIT_LIST_HEAD(&ioa_cfg->free_res_q); |
| 9718 | 9803 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); |
| 9719 | 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 | 10437 | &ipr_trace_attr); |
| 10353 | 10438 | ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj, |
| 10354 | 10439 | &ipr_dump_attr); |
| 10440 | + sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj, | |
| 10441 | + &ipr_ioa_async_err_log); | |
| 10355 | 10442 | scsi_remove_host(ioa_cfg->host); |
| 10356 | 10443 | |
| 10357 | 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 | 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 | 10503 | rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj, |
| 10404 | 10504 | &ipr_dump_attr); |
| 10405 | 10505 | |
| 10406 | 10506 | if (rc) { |
| 10507 | + sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj, | |
| 10508 | + &ipr_ioa_async_err_log); | |
| 10407 | 10509 | ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj, |
| 10408 | 10510 | &ipr_trace_attr); |
| 10409 | 10511 | scsi_remove_host(ioa_cfg->host); |
| @@ -154,7 +154,9 @@ · 153 unmodified lines | ||
| 154 | 154 | #define IPR_DEFAULT_MAX_ERROR_DUMP 984 |
| 155 | 155 | #define IPR_NUM_LOG_HCAMS 2 |
| 156 | 156 | #define IPR_NUM_CFG_CHG_HCAMS 2 |
| 157 | +#define IPR_NUM_HCAM_QUEUE 12 | |
| 157 | 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 | 161 | #define IPR_MAX_SIS64_TARGETS_PER_BUS 1024 |
| 160 | 162 | #define IPR_MAX_SIS64_LUNS_PER_TARGET 0xffffffff |
| @@ -1504,6 +1506,7 @@ struct ipr_ioa_cfg { · 1343 unmodified lines | ||
| 1504 | 1506 | u8 log_level; |
| 1505 | 1507 | #define IPR_MAX_LOG_LEVEL 4 |
| 1506 | 1508 | #define IPR_DEFAULT_LOG_LEVEL 2 |
| 1509 | +#define IPR_DEBUG_LOG_LEVEL 3 | |
| 1507 | 1510 | |
| 1508 | 1511 | #define IPR_NUM_TRACE_INDEX_BITS 8 |
| 1509 | 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 | 1536 | char ipr_hcam_label[8]; |
| 1534 | 1537 | #define IPR_HCAM_LABEL "hcams" |
| 1535 | − struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS]; | |
| 1536 | − dma_addr_t hostrcb_dma[IPR_NUM_HCAMS]; | |
| 1538 | + struct ipr_hostrcb *hostrcb[IPR_MAX_HCAMS]; | |
| 1539 | + dma_addr_t hostrcb_dma[IPR_MAX_HCAMS]; | |
| 1537 | 1540 | struct list_head hostrcb_free_q; |
| 1538 | 1541 | struct list_head hostrcb_pending_q; |
| 1542 | + struct list_head hostrcb_report_q; | |
| 1539 | 1543 | |
| 1540 | 1544 | struct ipr_hrr_queue hrrq[IPR_MAX_HRRQ_NUM]; |
| 1541 | 1545 | u32 hrrq_num; |
| @@ -1837,7 +1837,6 @@ static void fc_exch_reset(struct fc_exch *ep) · 1836 unmodified lines | ||
| 1837 | 1837 | int rc = 1; |
| 1838 | 1838 | |
| 1839 | 1839 | spin_lock_bh(&ep->ex_lock); |
| 1840 | − fc_exch_abort_locked(ep, 0); | |
| 1841 | 1840 | ep->state |= FC_EX_RST_CLEANUP; |
| 1842 | 1841 | fc_exch_timer_cancel(ep); |
| 1843 | 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 | 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 | 463 | mutex_lock(&rdata->rp_mutex); |
| 461 | 464 | |
| 462 | 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 | 469 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); |
| 467 | 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 | 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 | 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 | 564 | FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n", |
| 551 | 565 | IS_ERR(fp) ? -PTR_ERR(fp) : 0, |
| 552 | 566 | fc_rport_state(rdata), rdata->retries); |
| 553 | 567 | |
| 554 | 568 | switch (rdata->rp_state) { |
| 555 | 569 | case RPORT_ST_FLOGI: |
| 556 | − case RPORT_ST_PLOGI: | |
| 557 | 570 | rdata->flags &= ~FC_RP_STARTED; |
| 558 | 571 | fc_rport_enter_delete(rdata, RPORT_EV_FAILED); |
| 559 | 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 | 580 | case RPORT_ST_RTV: |
| 561 | 581 | fc_rport_enter_ready(rdata); |
| 562 | 582 | break; |
| @@ -1877,7 +1897,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, · 1314 unmodified lines | ||
| 1877 | 1897 | spp->spp_type_ext = rspp->spp_type_ext; |
| 1878 | 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 | 1902 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
| 1883 | 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 | 1935 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", |
| 1916 | 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 | 1939 | mutex_unlock(&rdata->rp_mutex); |
| 1920 | 1940 | kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); |
| 1921 | 1941 | } else |
| @@ -1535,7 +1535,7 @@ lpfc_fdmi_num_disc_check(struct lpfc_vport *vport) · 1534 unmodified lines | ||
| 1535 | 1535 | } |
| 1536 | 1536 | |
| 1537 | 1537 | /* Routines for all individual HBA attributes */ |
| 1538 | −int | |
| 1538 | +static int | |
| 1539 | 1539 | lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) |
| 1540 | 1540 | { |
| 1541 | 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 | 1551 | ad->AttrType = cpu_to_be16(RHBA_NODENAME); |
| 1552 | 1552 | return size; |
| 1553 | 1553 | } |
| 1554 | −int | |
| 1554 | +static int | |
| 1555 | 1555 | lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, |
| 1556 | 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 | 1573 | return size; |
| 1574 | 1574 | } |
| 1575 | 1575 | |
| 1576 | −int | |
| 1576 | +static int | |
| 1577 | 1577 | lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) |
| 1578 | 1578 | { |
| 1579 | 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 | 1594 | return size; |
| 1595 | 1595 | } |
| 1596 | 1596 | |
| 1597 | −int | |
| 1597 | +static int | |
| 1598 | 1598 | lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport, |
| 1599 | 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 | 1615 | return size; |
| 1616 | 1616 | } |
| 1617 | 1617 | |
| 1618 | −int | |
| 1618 | +static int | |
| 1619 | 1619 | lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport, |
| 1620 | 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 | 1637 | return size; |
| 1638 | 1638 | } |
| 1639 | 1639 | |
| 1640 | −int | |
| 1640 | +static int | |
| 1641 | 1641 | lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport, |
| 1642 | 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 | 1669 | return size; |
| 1670 | 1670 | } |
| 1671 | 1671 | |
| 1672 | −int | |
| 1672 | +static int | |
| 1673 | 1673 | lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport, |
| 1674 | 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 | 1690 | return size; |
| 1691 | 1691 | } |
| 1692 | 1692 | |
| 1693 | −int | |
| 1693 | +static int | |
| 1694 | 1694 | lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport, |
| 1695 | 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 | 1715 | return size; |
| 1716 | 1716 | } |
| 1717 | 1717 | |
| 1718 | −int | |
| 1718 | +static int | |
| 1719 | 1719 | lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport, |
| 1720 | 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 | 1736 | return size; |
| 1737 | 1737 | } |
| 1738 | 1738 | |
| 1739 | −int | |
| 1739 | +static int | |
| 1740 | 1740 | lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport, |
| 1741 | 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 | 1759 | return size; |
| 1760 | 1760 | } |
| 1761 | 1761 | |
| 1762 | −int | |
| 1762 | +static int | |
| 1763 | 1763 | lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport, |
| 1764 | 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 | 1775 | return size; |
| 1776 | 1776 | } |
| 1777 | 1777 | |
| 1778 | −int | |
| 1778 | +static int | |
| 1779 | 1779 | lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport, |
| 1780 | 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 | 1794 | return size; |
| 1795 | 1795 | } |
| 1796 | 1796 | |
| 1797 | −int | |
| 1797 | +static int | |
| 1798 | 1798 | lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport, |
| 1799 | 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 | 1811 | return size; |
| 1812 | 1812 | } |
| 1813 | 1813 | |
| 1814 | −int | |
| 1814 | +static int | |
| 1815 | 1815 | lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport, |
| 1816 | 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 | 1828 | return size; |
| 1829 | 1829 | } |
| 1830 | 1830 | |
| 1831 | −int | |
| 1831 | +static int | |
| 1832 | 1832 | lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport, |
| 1833 | 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 | 1846 | return size; |
| 1847 | 1847 | } |
| 1848 | 1848 | |
| 1849 | −int | |
| 1849 | +static int | |
| 1850 | 1850 | lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport, |
| 1851 | 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 | 1867 | return size; |
| 1868 | 1868 | } |
| 1869 | 1869 | |
| 1870 | −int | |
| 1870 | +static int | |
| 1871 | 1871 | lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport, |
| 1872 | 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 | 1884 | return size; |
| 1885 | 1885 | } |
| 1886 | 1886 | |
| 1887 | −int | |
| 1887 | +static int | |
| 1888 | 1888 | lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport, |
| 1889 | 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 | 1908 | /* Routines for all individual PORT attributes */ |
| 1909 | −int | |
| 1909 | +static int | |
| 1910 | 1910 | lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, |
| 1911 | 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 | 1925 | return size; |
| 1926 | 1926 | } |
| 1927 | 1927 | |
| 1928 | −int | |
| 1928 | +static int | |
| 1929 | 1929 | lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, |
| 1930 | 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 | 1975 | return size; |
| 1976 | 1976 | } |
| 1977 | 1977 | |
| 1978 | −int | |
| 1978 | +static int | |
| 1979 | 1979 | lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, |
| 1980 | 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 | 2039 | return size; |
| 2040 | 2040 | } |
| 2041 | 2041 | |
| 2042 | −int | |
| 2042 | +static int | |
| 2043 | 2043 | lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, |
| 2044 | 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 | 2059 | return size; |
| 2060 | 2060 | } |
| 2061 | 2061 | |
| 2062 | −int | |
| 2062 | +static int | |
| 2063 | 2063 | lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport, |
| 2064 | 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 | 2081 | return size; |
| 2082 | 2082 | } |
| 2083 | 2083 | |
| 2084 | −int | |
| 2084 | +static int | |
| 2085 | 2085 | lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport, |
| 2086 | 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 | 2102 | return size; |
| 2103 | 2103 | } |
| 2104 | 2104 | |
| 2105 | −int | |
| 2105 | +static int | |
| 2106 | 2106 | lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport, |
| 2107 | 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 | 2120 | return size; |
| 2121 | 2121 | } |
| 2122 | 2122 | |
| 2123 | −int | |
| 2123 | +static int | |
| 2124 | 2124 | lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport, |
| 2125 | 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 | 2138 | return size; |
| 2139 | 2139 | } |
| 2140 | 2140 | |
| 2141 | −int | |
| 2141 | +static int | |
| 2142 | 2142 | lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport, |
| 2143 | 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 | 2156 | return size; |
| 2157 | 2157 | } |
| 2158 | 2158 | |
| 2159 | −int | |
| 2159 | +static int | |
| 2160 | 2160 | lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport, |
| 2161 | 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 | 2175 | return size; |
| 2176 | 2176 | } |
| 2177 | 2177 | |
| 2178 | −int | |
| 2178 | +static int | |
| 2179 | 2179 | lpfc_fdmi_port_attr_class(struct lpfc_vport *vport, |
| 2180 | 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 | 2190 | return size; |
| 2191 | 2191 | } |
| 2192 | 2192 | |
| 2193 | −int | |
| 2193 | +static int | |
| 2194 | 2194 | lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport, |
| 2195 | 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 | 2208 | return size; |
| 2209 | 2209 | } |
| 2210 | 2210 | |
| 2211 | −int | |
| 2211 | +static int | |
| 2212 | 2212 | lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, |
| 2213 | 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 | 2227 | return size; |
| 2228 | 2228 | } |
| 2229 | 2229 | |
| 2230 | −int | |
| 2230 | +static int | |
| 2231 | 2231 | lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport, |
| 2232 | 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 | 2243 | return size; |
| 2244 | 2244 | } |
| 2245 | 2245 | |
| 2246 | −int | |
| 2246 | +static int | |
| 2247 | 2247 | lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport, |
| 2248 | 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 | 2259 | return size; |
| 2260 | 2260 | } |
| 2261 | 2261 | |
| 2262 | −int | |
| 2262 | +static int | |
| 2263 | 2263 | lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport, |
| 2264 | 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 | 2274 | return size; |
| 2275 | 2275 | } |
| 2276 | 2276 | |
| 2277 | −int | |
| 2277 | +static int | |
| 2278 | 2278 | lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport, |
| 2279 | 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 | 2295 | return size; |
| 2296 | 2296 | } |
| 2297 | 2297 | |
| 2298 | −int | |
| 2298 | +static int | |
| 2299 | 2299 | lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport, |
| 2300 | 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 | 2316 | return size; |
| 2317 | 2317 | } |
| 2318 | 2318 | |
| 2319 | −int | |
| 2319 | +static int | |
| 2320 | 2320 | lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, |
| 2321 | 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 | 2337 | return size; |
| 2338 | 2338 | } |
| 2339 | 2339 | |
| 2340 | −int | |
| 2340 | +static int | |
| 2341 | 2341 | lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport, |
| 2342 | 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 | 2358 | return size; |
| 2359 | 2359 | } |
| 2360 | 2360 | |
| 2361 | −int | |
| 2361 | +static int | |
| 2362 | 2362 | lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport, |
| 2363 | 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 | 2378 | return size; |
| 2379 | 2379 | } |
| 2380 | 2380 | |
| 2381 | −int | |
| 2381 | +static int | |
| 2382 | 2382 | lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport, |
| 2383 | 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 | 2393 | return size; |
| 2394 | 2394 | } |
| 2395 | 2395 | |
| 2396 | −int | |
| 2396 | +static int | |
| 2397 | 2397 | lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, |
| 2398 | 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 | 4617 | return sentplogi; |
| 4618 | 4618 | } |
| 4619 | 4619 | |
| 4620 | −uint32_t | |
| 4620 | +static uint32_t | |
| 4621 | 4621 | lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc, |
| 4622 | 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 | 4629 | return sizeof(struct fc_rdp_link_service_desc); |
| 4630 | 4630 | } |
| 4631 | 4631 | |
| 4632 | −uint32_t | |
| 4632 | +static uint32_t | |
| 4633 | 4633 | lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc, |
| 4634 | 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 | 4694 | return sizeof(struct fc_rdp_sfp_desc); |
| 4695 | 4695 | } |
| 4696 | 4696 | |
| 4697 | −uint32_t | |
| 4697 | +static uint32_t | |
| 4698 | 4698 | lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc, |
| 4699 | 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 | 4723 | return sizeof(struct fc_rdp_link_error_status_desc); |
| 4724 | 4724 | } |
| 4725 | 4725 | |
| 4726 | −uint32_t | |
| 4726 | +static uint32_t | |
| 4727 | 4727 | lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat, |
| 4728 | 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 | 4748 | return sizeof(struct fc_rdp_bbc_desc); |
| 4749 | 4749 | } |
| 4750 | 4750 | |
| 4751 | −uint32_t | |
| 4751 | +static uint32_t | |
| 4752 | 4752 | lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba, |
| 4753 | 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 | 4776 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4777 | 4777 | } |
| 4778 | 4778 | |
| 4779 | −uint32_t | |
| 4779 | +static uint32_t | |
| 4780 | 4780 | lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba, |
| 4781 | 4781 | struct fc_rdp_oed_sfp_desc *desc, |
| 4782 | 4782 | uint8_t *page_a2) |
| @@ -4805,7 +4805,7 @@ lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba, · 22 unmodified lines | ||
| 4805 | 4805 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4806 | 4806 | } |
| 4807 | 4807 | |
| 4808 | −uint32_t | |
| 4808 | +static uint32_t | |
| 4809 | 4809 | lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba, |
| 4810 | 4810 | struct fc_rdp_oed_sfp_desc *desc, |
| 4811 | 4811 | uint8_t *page_a2) |
| @@ -4834,7 +4834,7 @@ lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba, · 22 unmodified lines | ||
| 4834 | 4834 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4835 | 4835 | } |
| 4836 | 4836 | |
| 4837 | −uint32_t | |
| 4837 | +static uint32_t | |
| 4838 | 4838 | lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba, |
| 4839 | 4839 | struct fc_rdp_oed_sfp_desc *desc, |
| 4840 | 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 | 4868 | lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba, |
| 4869 | 4869 | struct fc_rdp_oed_sfp_desc *desc, |
| 4870 | 4870 | uint8_t *page_a2) |
| @@ -4893,7 +4893,7 @@ lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba, · 22 unmodified lines | ||
| 4893 | 4893 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4894 | 4894 | } |
| 4895 | 4895 | |
| 4896 | −uint32_t | |
| 4896 | +static uint32_t | |
| 4897 | 4897 | lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, |
| 4898 | 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 | 4907 | return sizeof(struct fc_rdp_opd_sfp_desc); |
| 4908 | 4908 | } |
| 4909 | 4909 | |
| 4910 | −uint32_t | |
| 4910 | +static uint32_t | |
| 4911 | 4911 | lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat) |
| 4912 | 4912 | { |
| 4913 | 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 | 4924 | return sizeof(struct fc_fec_rdp_desc); |
| 4925 | 4925 | } |
| 4926 | 4926 | |
| 4927 | −uint32_t | |
| 4927 | +static uint32_t | |
| 4928 | 4928 | lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) |
| 4929 | 4929 | { |
| 4930 | 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 | 4986 | return sizeof(struct fc_rdp_port_speed_desc); |
| 4987 | 4987 | } |
| 4988 | 4988 | |
| 4989 | −uint32_t | |
| 4989 | +static uint32_t | |
| 4990 | 4990 | lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc, |
| 4991 | 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 | 5003 | return sizeof(struct fc_rdp_port_name_desc); |
| 5004 | 5004 | } |
| 5005 | 5005 | |
| 5006 | −uint32_t | |
| 5006 | +static uint32_t | |
| 5007 | 5007 | lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc, |
| 5008 | 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 | 5027 | return sizeof(struct fc_rdp_port_name_desc); |
| 5028 | 5028 | } |
| 5029 | 5029 | |
| 5030 | −void | |
| 5030 | +static void | |
| 5031 | 5031 | lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, |
| 5032 | 5032 | int status) |
| 5033 | 5033 | { |
| @@ -5165,7 +5165,7 @@ free_rdp_context: · 131 unmodified lines | ||
| 5165 | 5165 | kfree(rdp_context); |
| 5166 | 5166 | } |
| 5167 | 5167 | |
| 5168 | −int | |
| 5168 | +static int | |
| 5169 | 5169 | lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) |
| 5170 | 5170 | { |
| 5171 | 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 | 7999 | lpfc_start_fdmi(struct lpfc_vport *vport) |
| 8000 | 8000 | { |
| 8001 | 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 | 2260 | return 0; |
| 2261 | 2261 | } |
| 2262 | 2262 | |
| 2263 | −void | |
| 2263 | +static void | |
| 2264 | 2264 | lpfc_mbx_cmpl_rdp_link_stat(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) |
| 2265 | 2265 | { |
| 2266 | 2266 | MAILBOX_t *mb; |
| @@ -2281,7 +2281,7 @@ mbx_failed: · 14 unmodified lines | ||
| 2281 | 2281 | rdp_context->cmpl(phba, rdp_context, rc); |
| 2282 | 2282 | } |
| 2283 | 2283 | |
| 2284 | −void | |
| 2284 | +static void | |
| 2285 | 2285 | lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) |
| 2286 | 2286 | { |
| 2287 | 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 | 5689 | return rc; |
| 5690 | 5690 | } |
| 5691 | 5691 | |
| 5692 | −void | |
| 5692 | +static void | |
| 5693 | 5693 | lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox, |
| 5694 | 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 | 8968 | * Since ABORTS must go on the same WQ of the command they are |
| 8969 | 8969 | * aborting, we use command's fcp_wqidx. |
| 8970 | 8970 | */ |
| 8971 | −int | |
| 8971 | +static int | |
| 8972 | 8972 | lpfc_sli_calc_ring(struct lpfc_hba *phba, uint32_t ring_number, |
| 8973 | 8973 | struct lpfc_iocbq *piocb) |
| 8974 | 8974 | { |
| @@ -189,25 +189,12 @@ u32 · 188 unmodified lines | ||
| 189 | 189 | megasas_build_and_issue_cmd(struct megasas_instance *instance, |
| 190 | 190 | struct scsi_cmnd *scmd); |
| 191 | 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 | 192 | int |
| 203 | 193 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, |
| 204 | 194 | int seconds); |
| 205 | −void megasas_reset_reply_desc(struct megasas_instance *instance); | |
| 206 | 195 | void megasas_fusion_ocr_wq(struct work_struct *work); |
| 207 | 196 | static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, |
| 208 | 197 | int initial); |
| 209 | −int megasas_check_mpio_paths(struct megasas_instance *instance, | |
| 210 | − struct scsi_cmnd *scmd); | |
| 211 | 198 | |
| 212 | 199 | int |
| 213 | 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 | 5024 | /* Find first memory bar */ |
| 5038 | 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 | 5027 | if (pci_request_selected_regions(instance->pdev, 1<<instance->bar, |
| 5041 | 5028 | "megasas: LSI")) { |
| 5042 | 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 | 5769 | &instance->consumer_h); |
| 5783 | 5770 | |
| 5784 | 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 | 5773 | "memory for producer, consumer\n"); |
| 5787 | 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 | 6698 | unsigned long flags; |
| 6712 | 6699 | u32 wait_time = MEGASAS_RESET_WAIT_TIME; |
| 6713 | 6700 | |
| 6714 | − ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); | |
| 6715 | − if (!ioc) | |
| 6716 | − return -ENOMEM; | |
| 6717 | − | |
| 6718 | − if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) { | |
| 6719 | − error = -EFAULT; | |
| 6720 | − goto out_kfree_ioc; | |
| 6721 | − } | |
| 6701 | + ioc = memdup_user(user_ioc, sizeof(*ioc)); | |
| 6702 | + if (IS_ERR(ioc)) | |
| 6703 | + return PTR_ERR(ioc); | |
| 6722 | 6704 | |
| 6723 | 6705 | instance = megasas_lookup_instance(ioc->host_no); |
| 6724 | 6706 | if (!instance) { |
| @@ -991,5 +991,14 @@ union desc_value { · 990 unmodified lines | ||
| 991 | 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 | 1004 | #endif /* _MEGARAID_SAS_FUSION_H_ */ |
| @@ -98,7 +98,7 @@ MODULE_PARM_DESC(mpt3sas_fwfault_debug, · 97 unmodified lines | ||
| 98 | 98 | " enable detection of firmware fault and halt firmware - (default=0)"); |
| 99 | 99 | |
| 100 | 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 | 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 | 218 | ioc->non_operational_loop = 0; |
| 219 | 219 | |
| 220 | 220 | if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { |
| 221 | − rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 222 | − FORCE_BIG_HAMMER); | |
| 221 | + rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 223 | 222 | pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name, |
| 224 | 223 | __func__, (rc == 0) ? "success" : "failed"); |
| 225 | 224 | doorbell = mpt3sas_base_get_iocstate(ioc, 0); |
| @@ -2040,7 +2039,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) · 1814 unmodified lines | ||
| 2040 | 2039 | * mpt3sas_base_unmap_resources - free controller resources |
| 2041 | 2040 | * @ioc: per adapter object |
| 2042 | 2041 | */ |
| 2043 | −void | |
| 2042 | +static void | |
| 2044 | 2043 | mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) |
| 2045 | 2044 | { |
| 2046 | 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 | 2145 | _base_mask_interrupts(ioc); |
| 2147 | 2146 | |
| 2148 | − r = _base_get_ioc_facts(ioc, CAN_SLEEP); | |
| 2147 | + r = _base_get_ioc_facts(ioc); | |
| 2149 | 2148 | if (r) |
| 2150 | 2149 | goto out_fail; |
| 2151 | 2150 | |
| @@ -3183,12 +3182,11 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) · 1031 unmodified lines | ||
| 3183 | 3182 | /** |
| 3184 | 3183 | * _base_allocate_memory_pools - allocate start of day memory pools |
| 3185 | 3184 | * @ioc: per adapter object |
| 3186 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3187 | 3185 | * |
| 3188 | 3186 | * Returns 0 success, anything else error |
| 3189 | 3187 | */ |
| 3190 | 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 | 3191 | struct mpt3sas_facts *facts; |
| 3194 | 3192 | u16 max_sge_elements; |
| @@ -3658,29 +3656,25 @@ mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked) · 463 unmodified lines | ||
| 3658 | 3656 | * _base_wait_on_iocstate - waiting on a particular ioc state |
| 3659 | 3657 | * @ioc_state: controller state { READY, OPERATIONAL, or RESET } |
| 3660 | 3658 | * @timeout: timeout in second |
| 3661 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3662 | 3659 | * |
| 3663 | 3660 | * Returns 0 for success, non-zero for failure. |
| 3664 | 3661 | */ |
| 3665 | 3662 | static int |
| 3666 | −_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout, | |
| 3667 | − int sleep_flag) | |
| 3663 | +_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout) | |
| 3668 | 3664 | { |
| 3669 | 3665 | u32 count, cntdn; |
| 3670 | 3666 | u32 current_state; |
| 3671 | 3667 | |
| 3672 | 3668 | count = 0; |
| 3673 | − cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | |
| 3669 | + cntdn = 1000 * timeout; | |
| 3674 | 3670 | do { |
| 3675 | 3671 | current_state = mpt3sas_base_get_iocstate(ioc, 1); |
| 3676 | 3672 | if (current_state == ioc_state) |
| 3677 | 3673 | return 0; |
| 3678 | 3674 | if (count && current_state == MPI2_IOC_STATE_FAULT) |
| 3679 | 3675 | break; |
| 3680 | − if (sleep_flag == CAN_SLEEP) | |
| 3681 | − usleep_range(1000, 1500); | |
| 3682 | − else | |
| 3683 | − udelay(500); | |
| 3676 | + | |
| 3677 | + usleep_range(1000, 1500); | |
| 3684 | 3678 | count++; |
| 3685 | 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 | 3686 | * a write to the doorbell) |
| 3693 | 3687 | * @ioc: per adapter object |
| 3694 | 3688 | * @timeout: timeout in second |
| 3695 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3696 | 3689 | * |
| 3697 | 3690 | * Returns 0 for success, non-zero for failure. |
| 3698 | 3691 | * |
| 3699 | 3692 | * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. |
| 3700 | 3693 | */ |
| 3701 | 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 | 3697 | static int |
| 3705 | −_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, | |
| 3706 | − int sleep_flag) | |
| 3698 | +_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout) | |
| 3707 | 3699 | { |
| 3708 | 3700 | u32 cntdn, count; |
| 3709 | 3701 | u32 int_status; |
| 3710 | 3702 | |
| 3711 | 3703 | count = 0; |
| 3712 | − cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | |
| 3704 | + cntdn = 1000 * timeout; | |
| 3713 | 3705 | do { |
| 3714 | 3706 | int_status = readl(&ioc->chip->HostInterruptStatus); |
| 3715 | 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 | 3710 | ioc->name, __func__, count, timeout)); |
| 3719 | 3711 | return 0; |
| 3720 | 3712 | } |
| 3721 | − if (sleep_flag == CAN_SLEEP) | |
| 3722 | − usleep_range(1000, 1500); | |
| 3723 | − else | |
| 3724 | − udelay(500); | |
| 3713 | + | |
| 3714 | + usleep_range(1000, 1500); | |
| 3715 | + count++; | |
| 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 | 3742 | count++; |
| 3726 | 3743 | } while (--cntdn); |
| 3727 | 3744 | |
| @@ -3729,13 +3746,13 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, · 1 unmodified line | ||
| 3729 | 3746 | "%s: failed due to timeout count(%d), int_status(%x)!\n", |
| 3730 | 3747 | ioc->name, __func__, count, int_status); |
| 3731 | 3748 | return -EFAULT; |
| 3749 | + | |
| 3732 | 3750 | } |
| 3733 | 3751 | |
| 3734 | 3752 | /** |
| 3735 | 3753 | * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. |
| 3736 | 3754 | * @ioc: per adapter object |
| 3737 | 3755 | * @timeout: timeout in second |
| 3738 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3739 | 3756 | * |
| 3740 | 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 | 3760 | * doorbell. |
| 3744 | 3761 | */ |
| 3745 | 3762 | static int |
| 3746 | −_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, | |
| 3747 | − int sleep_flag) | |
| 3763 | +_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout) | |
| 3748 | 3764 | { |
| 3749 | 3765 | u32 cntdn, count; |
| 3750 | 3766 | u32 int_status; |
| 3751 | 3767 | u32 doorbell; |
| 3752 | 3768 | |
| 3753 | 3769 | count = 0; |
| 3754 | − cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | |
| 3770 | + cntdn = 1000 * timeout; | |
| 3755 | 3771 | do { |
| 3756 | 3772 | int_status = readl(&ioc->chip->HostInterruptStatus); |
| 3757 | 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 | 3785 | } else if (int_status == 0xFFFFFFFF) |
| 3770 | 3786 | goto out; |
| 3771 | 3787 | |
| 3772 | − if (sleep_flag == CAN_SLEEP) | |
| 3773 | − usleep_range(1000, 1500); | |
| 3774 | − else | |
| 3775 | − udelay(500); | |
| 3788 | + usleep_range(1000, 1500); | |
| 3776 | 3789 | count++; |
| 3777 | 3790 | } while (--cntdn); |
| 3778 | 3791 | |
| @@ -3787,20 +3800,18 @@ _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, · 8 unmodified lines | ||
| 3787 | 3800 | * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use |
| 3788 | 3801 | * @ioc: per adapter object |
| 3789 | 3802 | * @timeout: timeout in second |
| 3790 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3791 | 3803 | * |
| 3792 | 3804 | * Returns 0 for success, non-zero for failure. |
| 3793 | 3805 | * |
| 3794 | 3806 | */ |
| 3795 | 3807 | static int |
| 3796 | −_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, | |
| 3797 | − int sleep_flag) | |
| 3808 | +_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout) | |
| 3798 | 3809 | { |
| 3799 | 3810 | u32 cntdn, count; |
| 3800 | 3811 | u32 doorbell_reg; |
| 3801 | 3812 | |
| 3802 | 3813 | count = 0; |
| 3803 | − cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | |
| 3814 | + cntdn = 1000 * timeout; | |
| 3804 | 3815 | do { |
| 3805 | 3816 | doorbell_reg = readl(&ioc->chip->Doorbell); |
| 3806 | 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 | 3820 | ioc->name, __func__, count, timeout)); |
| 3810 | 3821 | return 0; |
| 3811 | 3822 | } |
| 3812 | − if (sleep_flag == CAN_SLEEP) | |
| 3813 | − usleep_range(1000, 1500); | |
| 3814 | − else | |
| 3815 | − udelay(500); | |
| 3823 | + | |
| 3824 | + usleep_range(1000, 1500); | |
| 3816 | 3825 | count++; |
| 3817 | 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 | 3836 | * @ioc: per adapter object |
| 3828 | 3837 | * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET |
| 3829 | 3838 | * @timeout: timeout in second |
| 3830 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3831 | 3839 | * |
| 3832 | 3840 | * Returns 0 for success, non-zero for failure. |
| 3833 | 3841 | */ |
| 3834 | 3842 | static int |
| 3835 | −_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout, | |
| 3836 | − int sleep_flag) | |
| 3843 | +_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout) | |
| 3837 | 3844 | { |
| 3838 | 3845 | u32 ioc_state; |
| 3839 | 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 | 3860 | writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, |
| 3854 | 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 | 3863 | r = -EFAULT; |
| 3857 | 3864 | goto out; |
| 3858 | 3865 | } |
| 3859 | − ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | |
| 3860 | − timeout, sleep_flag); | |
| 3866 | + ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout); | |
| 3861 | 3867 | if (ioc_state) { |
| 3862 | 3868 | pr_err(MPT3SAS_FMT |
| 3863 | 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 | 3885 | * @reply_bytes: reply length |
| 3880 | 3886 | * @reply: pointer to reply payload |
| 3881 | 3887 | * @timeout: timeout in second |
| 3882 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 3883 | 3888 | * |
| 3884 | 3889 | * Returns 0 for success, non-zero for failure. |
| 3885 | 3890 | */ |
| 3886 | 3891 | static int |
| 3887 | 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 | 3895 | MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; |
| 3891 | 3896 | int i; |
| 3892 | 3897 | u8 failed; |
| 3893 | − u16 dummy; | |
| 3894 | 3898 | __le32 *mfp; |
| 3895 | 3899 | |
| 3896 | 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 | 3915 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), |
| 3912 | 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 | 3919 | pr_err(MPT3SAS_FMT |
| 3916 | 3920 | "doorbell handshake int failed (line=%d)\n", |
| 3917 | 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 | 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 | 3927 | pr_err(MPT3SAS_FMT |
| 3924 | 3928 | "doorbell handshake ack failed (line=%d)\n", |
| 3925 | 3929 | ioc->name, __LINE__); |
| @@ -3929,7 +3933,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 3 unmodified lines | ||
| 3929 | 3933 | /* send message 32-bits at a time */ |
| 3930 | 3934 | for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { |
| 3931 | 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 | 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 | 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 | 3949 | pr_err(MPT3SAS_FMT |
| 3946 | 3950 | "doorbell handshake int failed (line=%d)\n", |
| 3947 | 3951 | ioc->name, __LINE__); |
| @@ -3952,7 +3956,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 4 unmodified lines | ||
| 3952 | 3956 | reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) |
| 3953 | 3957 | & MPI2_DOORBELL_DATA_MASK); |
| 3954 | 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 | 3960 | pr_err(MPT3SAS_FMT |
| 3957 | 3961 | "doorbell handshake int failed (line=%d)\n", |
| 3958 | 3962 | ioc->name, __LINE__); |
| @@ -3963,22 +3967,22 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 4 unmodified lines | ||
| 3963 | 3967 | writel(0, &ioc->chip->HostInterruptStatus); |
| 3964 | 3968 | |
| 3965 | 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 | 3971 | pr_err(MPT3SAS_FMT |
| 3968 | 3972 | "doorbell handshake int failed (line=%d)\n", |
| 3969 | 3973 | ioc->name, __LINE__); |
| 3970 | 3974 | return -EFAULT; |
| 3971 | 3975 | } |
| 3972 | 3976 | if (i >= reply_bytes/2) /* overflow case */ |
| 3973 | − dummy = readl(&ioc->chip->Doorbell); | |
| 3977 | + readl(&ioc->chip->Doorbell); | |
| 3974 | 3978 | else |
| 3975 | 3979 | reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) |
| 3976 | 3980 | & MPI2_DOORBELL_DATA_MASK); |
| 3977 | 3981 | writel(0, &ioc->chip->HostInterruptStatus); |
| 3978 | 3982 | } |
| 3979 | 3983 | |
| 3980 | − _base_wait_for_doorbell_int(ioc, 5, sleep_flag); | |
| 3981 | − if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) { | |
| 3984 | + _base_wait_for_doorbell_int(ioc, 5); | |
| 3985 | + if (_base_wait_for_doorbell_not_used(ioc, 5) != 0) { | |
| 3982 | 3986 | dhsprintk(ioc, pr_info(MPT3SAS_FMT |
| 3983 | 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 | 4020 | u16 smid; |
| 4017 | 4021 | u32 ioc_state; |
| 4018 | − unsigned long timeleft; | |
| 4019 | 4022 | bool issue_reset = false; |
| 4020 | 4023 | int rc; |
| 4021 | 4024 | void *request; |
| @@ -4068,7 +4071,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, · 46 unmodified lines | ||
| 4068 | 4071 | ioc->ioc_link_reset_in_progress = 1; |
| 4069 | 4072 | init_completion(&ioc->base_cmds.done); |
| 4070 | 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 | 4075 | msecs_to_jiffies(10000)); |
| 4073 | 4076 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || |
| 4074 | 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 | 4097 | issue_host_reset: |
| 4095 | 4098 | if (issue_reset) |
| 4096 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 4097 | − FORCE_BIG_HAMMER); | |
| 4099 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 4098 | 4100 | ioc->base_cmds.status = MPT3_CMD_NOT_USED; |
| 4099 | 4101 | rc = -EFAULT; |
| 4100 | 4102 | out: |
| @@ -4119,7 +4121,6 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 18 unmodified lines | ||
| 4119 | 4121 | { |
| 4120 | 4122 | u16 smid; |
| 4121 | 4123 | u32 ioc_state; |
| 4122 | − unsigned long timeleft; | |
| 4123 | 4124 | bool issue_reset = false; |
| 4124 | 4125 | int rc; |
| 4125 | 4126 | void *request; |
| @@ -4170,7 +4171,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 44 unmodified lines | ||
| 4170 | 4171 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); |
| 4171 | 4172 | init_completion(&ioc->base_cmds.done); |
| 4172 | 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 | 4175 | msecs_to_jiffies(10000)); |
| 4175 | 4176 | if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { |
| 4176 | 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 | 4193 | issue_host_reset: |
| 4193 | 4194 | if (issue_reset) |
| 4194 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 4195 | − FORCE_BIG_HAMMER); | |
| 4195 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 4196 | 4196 | ioc->base_cmds.status = MPT3_CMD_NOT_USED; |
| 4197 | 4197 | rc = -EFAULT; |
| 4198 | 4198 | out: |
| @@ -4203,12 +4203,11 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 4 unmodified lines | ||
| 4203 | 4203 | /** |
| 4204 | 4204 | * _base_get_port_facts - obtain port facts reply and save in ioc |
| 4205 | 4205 | * @ioc: per adapter object |
| 4206 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4207 | 4206 | * |
| 4208 | 4207 | * Returns 0 for success, non-zero for failure. |
| 4209 | 4208 | */ |
| 4210 | 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 | 4212 | Mpi2PortFactsRequest_t mpi_request; |
| 4214 | 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 | 4223 | mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; |
| 4225 | 4224 | mpi_request.PortNumber = port; |
| 4226 | 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 | 4228 | if (r != 0) { |
| 4230 | 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 | 4246 | * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL |
| 4248 | 4247 | * @ioc: per adapter object |
| 4249 | 4248 | * @timeout: |
| 4250 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4251 | 4249 | * |
| 4252 | 4250 | * Returns 0 for success, non-zero for failure. |
| 4253 | 4251 | */ |
| 4254 | 4252 | static int |
| 4255 | −_base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, | |
| 4256 | − int sleep_flag) | |
| 4253 | +_base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout) | |
| 4257 | 4254 | { |
| 4258 | 4255 | u32 ioc_state; |
| 4259 | 4256 | int rc; |
| @@ -4287,8 +4284,7 @@ _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, · 27 unmodified lines | ||
| 4287 | 4284 | goto issue_diag_reset; |
| 4288 | 4285 | } |
| 4289 | 4286 | |
| 4290 | − ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | |
| 4291 | − timeout, sleep_flag); | |
| 4287 | + ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout); | |
| 4292 | 4288 | if (ioc_state) { |
| 4293 | 4289 | dfailprintk(ioc, printk(MPT3SAS_FMT |
| 4294 | 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 | 4295 | issue_diag_reset: |
| 4300 | − rc = _base_diag_reset(ioc, sleep_flag); | |
| 4296 | + rc = _base_diag_reset(ioc); | |
| 4301 | 4297 | return rc; |
| 4302 | 4298 | } |
| 4303 | 4299 | |
| 4304 | 4300 | /** |
| 4305 | 4301 | * _base_get_ioc_facts - obtain ioc facts reply and save in ioc |
| 4306 | 4302 | * @ioc: per adapter object |
| 4307 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4308 | 4303 | * |
| 4309 | 4304 | * Returns 0 for success, non-zero for failure. |
| 4310 | 4305 | */ |
| 4311 | 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 | 4309 | Mpi2IOCFactsRequest_t mpi_request; |
| 4315 | 4310 | Mpi2IOCFactsReply_t mpi_reply; |
| @@ -4319,7 +4314,7 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 3 unmodified lines | ||
| 4319 | 4314 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 4320 | 4315 | __func__)); |
| 4321 | 4316 | |
| 4322 | − r = _base_wait_for_iocstate(ioc, 10, sleep_flag); | |
| 4317 | + r = _base_wait_for_iocstate(ioc, 10); | |
| 4323 | 4318 | if (r) { |
| 4324 | 4319 | dfailprintk(ioc, printk(MPT3SAS_FMT |
| 4325 | 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 | 4326 | memset(&mpi_request, 0, mpi_request_sz); |
| 4332 | 4327 | mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; |
| 4333 | 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 | 4331 | if (r != 0) { |
| 4337 | 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 | 4387 | * _base_send_ioc_init - send ioc_init to firmware |
| 4393 | 4388 | * @ioc: per adapter object |
| 4394 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4395 | 4389 | * |
| 4396 | 4390 | * Returns 0 for success, non-zero for failure. |
| 4397 | 4391 | */ |
| 4398 | 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 | 4395 | Mpi2IOCInitRequest_t mpi_request; |
| 4402 | 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 | 4474 | r = _base_handshake_req_reply_wait(ioc, |
| 4481 | 4475 | sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, |
| 4482 | − sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10, | |
| 4483 | − sleep_flag); | |
| 4476 | + sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10); | |
| 4484 | 4477 | |
| 4485 | 4478 | if (r != 0) { |
| 4486 | 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 | 4549 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware |
| 4557 | 4550 | * @ioc: per adapter object |
| 4558 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4559 | 4551 | * |
| 4560 | 4552 | * Returns 0 for success, non-zero for failure. |
| 4561 | 4553 | */ |
| 4562 | 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 | 4557 | Mpi2PortEnableRequest_t *mpi_request; |
| 4566 | 4558 | Mpi2PortEnableReply_t *mpi_reply; |
| 4567 | − unsigned long timeleft; | |
| 4568 | 4559 | int r = 0; |
| 4569 | 4560 | u16 smid; |
| 4570 | 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 | 4584 | init_completion(&ioc->port_enable_cmds.done); |
| 4594 | 4585 | mpt3sas_base_put_smid_default(ioc, smid); |
| 4595 | − timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done, | |
| 4596 | − 300*HZ); | |
| 4586 | + wait_for_completion_timeout(&ioc->port_enable_cmds.done, 300*HZ); | |
| 4597 | 4587 | if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { |
| 4598 | 4588 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 4599 | 4589 | ioc->name, __func__); |
| @@ -4737,15 +4727,13 @@ _base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event) · 137 unmodified lines | ||
| 4737 | 4727 | /** |
| 4738 | 4728 | * _base_event_notification - send event notification |
| 4739 | 4729 | * @ioc: per adapter object |
| 4740 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4741 | 4730 | * |
| 4742 | 4731 | * Returns 0 for success, non-zero for failure. |
| 4743 | 4732 | */ |
| 4744 | 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 | 4736 | Mpi2EventNotificationRequest_t *mpi_request; |
| 4748 | − unsigned long timeleft; | |
| 4749 | 4737 | u16 smid; |
| 4750 | 4738 | int r = 0; |
| 4751 | 4739 | int i; |
| @@ -4777,7 +4765,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 25 unmodified lines | ||
| 4777 | 4765 | cpu_to_le32(ioc->event_masks[i]); |
| 4778 | 4766 | init_completion(&ioc->base_cmds.done); |
| 4779 | 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 | 4769 | if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { |
| 4782 | 4770 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 4783 | 4771 | ioc->name, __func__); |
| @@ -4827,19 +4815,18 @@ mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type) · 43 unmodified lines | ||
| 4827 | 4815 | return; |
| 4828 | 4816 | |
| 4829 | 4817 | mutex_lock(&ioc->base_cmds.mutex); |
| 4830 | − _base_event_notification(ioc, CAN_SLEEP); | |
| 4818 | + _base_event_notification(ioc); | |
| 4831 | 4819 | mutex_unlock(&ioc->base_cmds.mutex); |
| 4832 | 4820 | } |
| 4833 | 4821 | |
| 4834 | 4822 | /** |
| 4835 | 4823 | * _base_diag_reset - the "big hammer" start of day reset |
| 4836 | 4824 | * @ioc: per adapter object |
| 4837 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4838 | 4825 | * |
| 4839 | 4826 | * Returns 0 for success, non-zero for failure. |
| 4840 | 4827 | */ |
| 4841 | 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 | 4831 | u32 host_diagnostic; |
| 4845 | 4832 | u32 ioc_state; |
| @@ -4867,10 +4854,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 21 unmodified lines | ||
| 4867 | 4854 | writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); |
| 4868 | 4855 | |
| 4869 | 4856 | /* wait 100 msec */ |
| 4870 | − if (sleep_flag == CAN_SLEEP) | |
| 4871 | − msleep(100); | |
| 4872 | − else | |
| 4873 | − mdelay(100); | |
| 4857 | + msleep(100); | |
| 4874 | 4858 | |
| 4875 | 4859 | if (count++ > 20) |
| 4876 | 4860 | goto out; |
| @@ -4890,10 +4874,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 13 unmodified lines | ||
| 4890 | 4874 | &ioc->chip->HostDiagnostic); |
| 4891 | 4875 | |
| 4892 | 4876 | /*This delay allows the chip PCIe hardware time to finish reset tasks*/ |
| 4893 | − if (sleep_flag == CAN_SLEEP) | |
| 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); | |
| 4877 | + msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); | |
| 4897 | 4878 | |
| 4898 | 4879 | /* Approximately 300 second max wait */ |
| 4899 | 4880 | for (count = 0; count < (300000000 / |
| @@ -4906,13 +4887,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 6 unmodified lines | ||
| 4906 | 4887 | if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) |
| 4907 | 4888 | break; |
| 4908 | 4889 | |
| 4909 | − /* Wait to pass the second read delay window */ | |
| 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); | |
| 4890 | + msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC / 1000); | |
| 4916 | 4891 | } |
| 4917 | 4892 | |
| 4918 | 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 | 4917 | drsprintk(ioc, pr_info(MPT3SAS_FMT |
| 4943 | 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, | |
| 4945 | − sleep_flag); | |
| 4919 | + ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20); | |
| 4946 | 4920 | if (ioc_state) { |
| 4947 | 4921 | pr_err(MPT3SAS_FMT |
| 4948 | 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 | 4936 | * _base_make_ioc_ready - put controller in READY state |
| 4963 | 4937 | * @ioc: per adapter object |
| 4964 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 4965 | 4938 | * @type: FORCE_BIG_HAMMER or SOFT_RESET |
| 4966 | 4939 | * |
| 4967 | 4940 | * Returns 0 for success, non-zero for failure. |
| 4968 | 4941 | */ |
| 4969 | 4942 | static int |
| 4970 | −_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, | |
| 4971 | − enum reset_type type) | |
| 4943 | +_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type) | |
| 4972 | 4944 | { |
| 4973 | 4945 | u32 ioc_state; |
| 4974 | 4946 | int rc; |
| @@ -4995,10 +4967,7 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 20 unmodified lines | ||
| 4995 | 4967 | ioc->name, __func__, ioc_state); |
| 4996 | 4968 | return -EFAULT; |
| 4997 | 4969 | } |
| 4998 | − if (sleep_flag == CAN_SLEEP) | |
| 4999 | − ssleep(1); | |
| 5000 | − else | |
| 5001 | − mdelay(1000); | |
| 4970 | + ssleep(1); | |
| 5002 | 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 | 4994 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) |
| 5026 | 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 | 4997 | return 0; |
| 5029 | 4998 | } |
| 5030 | 4999 | |
| 5031 | 5000 | issue_diag_reset: |
| 5032 | − rc = _base_diag_reset(ioc, CAN_SLEEP); | |
| 5001 | + rc = _base_diag_reset(ioc); | |
| 5033 | 5002 | return rc; |
| 5034 | 5003 | } |
| 5035 | 5004 | |
| 5036 | 5005 | /** |
| 5037 | 5006 | * _base_make_ioc_operational - put controller in OPERATIONAL state |
| 5038 | 5007 | * @ioc: per adapter object |
| 5039 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 5040 | 5008 | * |
| 5041 | 5009 | * Returns 0 for success, non-zero for failure. |
| 5042 | 5010 | */ |
| 5043 | 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 | 5014 | int r, i, index; |
| 5047 | 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 | 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 | 5132 | if (r) |
| 5165 | 5133 | return r; |
| 5166 | 5134 | |
| @@ -5186,13 +5154,11 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 19 unmodified lines | ||
| 5186 | 5154 | skip_init_reply_post_host_index: |
| 5187 | 5155 | |
| 5188 | 5156 | _base_unmask_interrupts(ioc); |
| 5189 | − r = _base_event_notification(ioc, sleep_flag); | |
| 5157 | + r = _base_event_notification(ioc); | |
| 5190 | 5158 | if (r) |
| 5191 | 5159 | return r; |
| 5192 | 5160 | |
| 5193 | − if (sleep_flag == CAN_SLEEP) | |
| 5194 | − _base_static_config_pages(ioc); | |
| 5195 | − | |
| 5161 | + _base_static_config_pages(ioc); | |
| 5196 | 5162 | |
| 5197 | 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 | 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 | 5181 | if (r) |
| 5216 | 5182 | return r; |
| 5217 | 5183 | |
| @@ -5235,7 +5201,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) · 17 unmodified lines | ||
| 5235 | 5201 | if (ioc->chip_phys && ioc->chip) { |
| 5236 | 5202 | _base_mask_interrupts(ioc); |
| 5237 | 5203 | ioc->shost_recovery = 1; |
| 5238 | − _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | |
| 5204 | + _base_make_ioc_ready(ioc, SOFT_RESET); | |
| 5239 | 5205 | ioc->shost_recovery = 0; |
| 5240 | 5206 | } |
| 5241 | 5207 | |
| @@ -5292,7 +5258,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 50 unmodified lines | ||
| 5292 | 5258 | goto out_free_resources; |
| 5293 | 5259 | |
| 5294 | 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 | 5262 | if (r) |
| 5297 | 5263 | goto out_free_resources; |
| 5298 | 5264 | |
| @@ -5326,7 +5292,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 27 unmodified lines | ||
| 5326 | 5292 | ioc->build_sg_mpi = &_base_build_sg; |
| 5327 | 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 | 5296 | if (r) |
| 5331 | 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 | 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 | 5308 | if (r) |
| 5343 | 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 | 5313 | if (r) |
| 5348 | 5314 | goto out_free_resources; |
| 5349 | 5315 | |
| @@ -5429,7 +5395,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 79 unmodified lines | ||
| 5429 | 5395 | if (ioc->hba_mpi_version_belonged == MPI26_VERSION) |
| 5430 | 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 | 5399 | if (r) |
| 5434 | 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 | 5532 | * _wait_for_commands_to_complete - reset controller |
| 5567 | 5533 | * @ioc: Pointer to MPT_ADAPTER structure |
| 5568 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 5569 | 5534 | * |
| 5570 | 5535 | * This function waiting(3s) for all pending commands to complete |
| 5571 | 5536 | * prior to putting controller in reset. |
| 5572 | 5537 | */ |
| 5573 | 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 | 5541 | u32 ioc_state; |
| 5577 | 5542 | unsigned long flags; |
| 5578 | 5543 | u16 i; |
| 5579 | 5544 | |
| 5580 | 5545 | ioc->pending_io_count = 0; |
| 5581 | − if (sleep_flag != CAN_SLEEP) | |
| 5582 | − return; | |
| 5583 | 5546 | |
| 5584 | 5547 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); |
| 5585 | 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 | 5566 | * mpt3sas_base_hard_reset_handler - reset controller |
| 5604 | 5567 | * @ioc: Pointer to MPT_ADAPTER structure |
| 5605 | − * @sleep_flag: CAN_SLEEP or NO_SLEEP | |
| 5606 | 5568 | * @type: FORCE_BIG_HAMMER or SOFT_RESET |
| 5607 | 5569 | * |
| 5608 | 5570 | * Returns 0 for success, non-zero for failure. |
| 5609 | 5571 | */ |
| 5610 | 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 | 5574 | enum reset_type type) |
| 5613 | 5575 | { |
| 5614 | 5576 | int r; |
| @@ -5629,13 +5591,6 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 14 unmodified lines | ||
| 5629 | 5591 | if (mpt3sas_fwfault_debug) |
| 5630 | 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 | 5594 | /* wait for an active reset in progress to complete */ |
| 5640 | 5595 | if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { |
| 5641 | 5596 | do { |
| @@ -5660,9 +5615,9 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 18 unmodified lines | ||
| 5660 | 5615 | is_fault = 1; |
| 5661 | 5616 | } |
| 5662 | 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 | 5619 | _base_mask_interrupts(ioc); |
| 5665 | − r = _base_make_ioc_ready(ioc, sleep_flag, type); | |
| 5620 | + r = _base_make_ioc_ready(ioc, type); | |
| 5666 | 5621 | if (r) |
| 5667 | 5622 | goto out; |
| 5668 | 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 | 5630 | r = -EFAULT; |
| 5676 | 5631 | goto out; |
| 5677 | 5632 | } |
| 5678 | − r = _base_get_ioc_facts(ioc, CAN_SLEEP); | |
| 5633 | + r = _base_get_ioc_facts(ioc); | |
| 5679 | 5634 | if (r) |
| 5680 | 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 | 5639 | "Please reboot the system and ensure that the correct" |
| 5685 | 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 | 5643 | if (!r) |
| 5689 | 5644 | _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); |
| 5690 | 5645 | |
| @@ -119,10 +119,6 @@ · 118 unmodified lines | ||
| 119 | 119 | |
| 120 | 120 | #define MPT_MAX_CALLBACKS 32 |
| 121 | 121 | |
| 122 | − | |
| 123 | −#define CAN_SLEEP 1 | |
| 124 | −#define NO_SLEEP 0 | |
| 125 | − | |
| 126 | 122 | #define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ |
| 127 | 123 | /* reserved for issuing internally framed scsi io cmds */ |
| 128 | 124 | #define INTERNAL_SCSIIO_CMDS_COUNT 3 |
| @@ -478,7 +474,7 @@ struct _sas_device { · 349 unmodified lines | ||
| 478 | 474 | u8 pfa_led_on; |
| 479 | 475 | u8 pend_sas_rphy_add; |
| 480 | 476 | u8 enclosure_level; |
| 481 | − u8 connector_name[4]; | |
| 477 | + u8 connector_name[5]; | |
| 482 | 478 | struct kref refcount; |
| 483 | 479 | }; |
| 484 | 480 | |
| @@ -794,16 +790,6 @@ struct reply_post_struct { · 309 unmodified lines | ||
| 794 | 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 | 793 | typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); |
| 808 | 794 | /** |
| 809 | 795 | * struct MPT3SAS_ADAPTER - per adapter struct |
| @@ -1229,7 +1215,7 @@ int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc); · 419 unmodified lines | ||
| 1229 | 1215 | void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc); |
| 1230 | 1216 | int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc); |
| 1231 | 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 | 1219 | enum reset_type type); |
| 1234 | 1220 | |
| 1235 | 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 | 1278 | int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, |
| 1293 | 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 | 1285 | void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); |
| 1296 | 1286 | void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); |
| 1297 | 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 | 286 | u16 smid; |
| 287 | 287 | u32 ioc_state; |
| 288 | − unsigned long timeleft; | |
| 289 | 288 | Mpi2ConfigRequest_t *config_request; |
| 290 | 289 | int r; |
| 291 | 290 | u8 retry_count, issue_host_reset = 0; |
| @@ -386,8 +385,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t · 94 unmodified lines | ||
| 386 | 385 | _config_display_some_debug(ioc, smid, "config_request", NULL); |
| 387 | 386 | init_completion(&ioc->config_cmds.done); |
| 388 | 387 | mpt3sas_base_put_smid_default(ioc, smid); |
| 389 | − timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | |
| 390 | − timeout*HZ); | |
| 388 | + wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ); | |
| 391 | 389 | if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { |
| 392 | 390 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 393 | 391 | ioc->name, __func__); |
| @@ -491,8 +489,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t · 97 unmodified lines | ||
| 491 | 489 | mutex_unlock(&ioc->config_cmds.mutex); |
| 492 | 490 | |
| 493 | 491 | if (issue_host_reset) |
| 494 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 495 | − FORCE_BIG_HAMMER); | |
| 492 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 496 | 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 | 519 | * Called when application request fasyn callback handler. |
| 520 | 520 | */ |
| 521 | −int | |
| 521 | +static int | |
| 522 | 522 | _ctl_fasync(int fd, struct file *filep, int mode) |
| 523 | 523 | { |
| 524 | 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 | 530 | * @wait - |
| 531 | 531 | * |
| 532 | 532 | */ |
| 533 | −unsigned int | |
| 533 | +static unsigned int | |
| 534 | 534 | _ctl_poll(struct file *filep, poll_table *wait) |
| 535 | 535 | { |
| 536 | 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 | 641 | MPI2RequestHeader_t *mpi_request = NULL, *request; |
| 642 | 642 | MPI2DefaultReply_t *mpi_reply; |
| 643 | 643 | u32 ioc_state; |
| 644 | − u16 ioc_status; | |
| 645 | 644 | u16 smid; |
| 646 | − unsigned long timeout, timeleft; | |
| 645 | + unsigned long timeout; | |
| 647 | 646 | u8 issue_reset; |
| 648 | 647 | u32 sz; |
| 649 | 648 | void *psge; |
| @@ -914,8 +913,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, · 264 unmodified lines | ||
| 914 | 913 | timeout = MPT3_IOCTL_DEFAULT_TIMEOUT; |
| 915 | 914 | else |
| 916 | 915 | timeout = karg.timeout; |
| 917 | − timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | |
| 918 | − timeout*HZ); | |
| 916 | + wait_for_completion_timeout(&ioc->ctl_cmds.done, timeout*HZ); | |
| 919 | 917 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { |
| 920 | 918 | Mpi2SCSITaskManagementRequest_t *tm_request = |
| 921 | 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 | 938 | mpi_reply = ioc->ctl_cmds.reply; |
| 941 | − ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | |
| 942 | 939 | |
| 943 | 940 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && |
| 944 | 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 | 998 | ioc->name, |
| 1002 | 999 | le16_to_cpu(mpi_request->FunctionDependent1)); |
| 1003 | 1000 | mpt3sas_halt_firmware(ioc); |
| 1004 | − mpt3sas_scsih_issue_tm(ioc, | |
| 1001 | + mpt3sas_scsih_issue_locked_tm(ioc, | |
| 1005 | 1002 | le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, |
| 1006 | − 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, | |
| 1007 | − TM_MUTEX_ON); | |
| 1003 | + 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30); | |
| 1008 | 1004 | } else |
| 1009 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 1010 | − FORCE_BIG_HAMMER); | |
| 1005 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 1011 | 1006 | } |
| 1012 | 1007 | |
| 1013 | 1008 | out: |
| @@ -1220,8 +1215,7 @@ _ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 206 unmodified lines | ||
| 1220 | 1215 | dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, |
| 1221 | 1216 | __func__)); |
| 1222 | 1217 | |
| 1223 | − retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 1224 | − FORCE_BIG_HAMMER); | |
| 1218 | + retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 1225 | 1219 | pr_info(MPT3SAS_FMT "host reset: %s\n", |
| 1226 | 1220 | ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); |
| 1227 | 1221 | return 0; |
| @@ -1381,7 +1375,6 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, · 153 unmodified lines | ||
| 1381 | 1375 | Mpi2DiagBufferPostRequest_t *mpi_request; |
| 1382 | 1376 | Mpi2DiagBufferPostReply_t *mpi_reply; |
| 1383 | 1377 | u8 buffer_type; |
| 1384 | − unsigned long timeleft; | |
| 1385 | 1378 | u16 smid; |
| 1386 | 1379 | u16 ioc_status; |
| 1387 | 1380 | u32 ioc_state; |
| @@ -1499,7 +1492,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, · 111 unmodified lines | ||
| 1499 | 1492 | |
| 1500 | 1493 | init_completion(&ioc->ctl_cmds.done); |
| 1501 | 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 | 1496 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); |
| 1504 | 1497 | |
| 1505 | 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 | 1532 | issue_host_reset: |
| 1540 | 1533 | if (issue_reset) |
| 1541 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 1542 | − FORCE_BIG_HAMMER); | |
| 1534 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 1543 | 1535 | |
| 1544 | 1536 | out: |
| 1545 | 1537 | |
| @@ -1800,7 +1792,6 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, · 254 unmodified lines | ||
| 1800 | 1792 | u16 ioc_status; |
| 1801 | 1793 | u32 ioc_state; |
| 1802 | 1794 | int rc; |
| 1803 | − unsigned long timeleft; | |
| 1804 | 1795 | |
| 1805 | 1796 | dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 1806 | 1797 | __func__)); |
| @@ -1848,7 +1839,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, · 41 unmodified lines | ||
| 1848 | 1839 | |
| 1849 | 1840 | init_completion(&ioc->ctl_cmds.done); |
| 1850 | 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 | 1843 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); |
| 1853 | 1844 | |
| 1854 | 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 | 1965 | rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset); |
| 1975 | 1966 | |
| 1976 | 1967 | if (issue_reset) |
| 1977 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 1978 | − FORCE_BIG_HAMMER); | |
| 1968 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 1979 | 1969 | |
| 1980 | 1970 | return rc; |
| 1981 | 1971 | } |
| @@ -1995,7 +1985,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 13 unmodified lines | ||
| 1995 | 1985 | Mpi2DiagBufferPostReply_t *mpi_reply; |
| 1996 | 1986 | int rc, i; |
| 1997 | 1987 | u8 buffer_type; |
| 1998 | − unsigned long timeleft, request_size, copy_size; | |
| 1988 | + unsigned long request_size, copy_size; | |
| 1999 | 1989 | u16 smid; |
| 2000 | 1990 | u16 ioc_status; |
| 2001 | 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 | 2107 | init_completion(&ioc->ctl_cmds.done); |
| 2118 | 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 | 2110 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); |
| 2121 | 2111 | |
| 2122 | 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 | 2146 | issue_host_reset: |
| 2157 | 2147 | if (issue_reset) |
| 2158 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 2159 | − FORCE_BIG_HAMMER); | |
| 2148 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 2160 | 2149 | |
| 2161 | 2150 | out: |
| 2162 | 2151 | |
| @@ -2352,7 +2341,7 @@ out_unlock_pciaccess: · 189 unmodified lines | ||
| 2352 | 2341 | * @cmd - ioctl opcode |
| 2353 | 2342 | * @arg - |
| 2354 | 2343 | */ |
| 2355 | −long | |
| 2344 | +static long | |
| 2356 | 2345 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 2357 | 2346 | { |
| 2358 | 2347 | long ret; |
| @@ -2372,7 +2361,7 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 13 unmodified lines | ||
| 2372 | 2361 | * @cmd - ioctl opcode |
| 2373 | 2362 | * @arg - |
| 2374 | 2363 | */ |
| 2375 | −long | |
| 2364 | +static long | |
| 2376 | 2365 | _ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 2377 | 2366 | { |
| 2378 | 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 | 2382 | * This routine handles 32 bit applications in 64bit os. |
| 2394 | 2383 | */ |
| 2395 | −long | |
| 2384 | +static long | |
| 2396 | 2385 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
| 2397 | 2386 | { |
| 2398 | 2387 | long ret; |
| @@ -2410,7 +2399,7 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) · 11 unmodified lines | ||
| 2410 | 2399 | * |
| 2411 | 2400 | * This routine handles 32 bit applications in 64bit os. |
| 2412 | 2401 | */ |
| 2413 | −long | |
| 2402 | +static long | |
| 2414 | 2403 | _ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
| 2415 | 2404 | { |
| 2416 | 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 | 1196 | * Returns queue depth. |
| 1197 | 1197 | */ |
| 1198 | −int | |
| 1198 | +static int | |
| 1199 | 1199 | scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) |
| 1200 | 1200 | { |
| 1201 | 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 | 1244 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1245 | 1245 | * the device is ignored. |
| 1246 | 1246 | */ |
| 1247 | −int | |
| 1247 | +static int | |
| 1248 | 1248 | scsih_target_alloc(struct scsi_target *starget) |
| 1249 | 1249 | { |
| 1250 | 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 | 1312 | * Returns nothing. |
| 1313 | 1313 | */ |
| 1314 | −void | |
| 1314 | +static void | |
| 1315 | 1315 | scsih_target_destroy(struct scsi_target *starget) |
| 1316 | 1316 | { |
| 1317 | 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 | 1320 | struct _sas_device *sas_device; |
| 1321 | 1321 | struct _raid_device *raid_device; |
| 1322 | 1322 | unsigned long flags; |
| 1323 | − struct sas_rphy *rphy; | |
| 1324 | 1323 | |
| 1325 | 1324 | sas_target_priv_data = starget->hostdata; |
| 1326 | 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 | 1340 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1342 | − rphy = dev_to_rphy(starget->dev.parent); | |
| 1343 | 1341 | sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1344 | 1342 | if (sas_device && (sas_device->starget == starget) && |
| 1345 | 1343 | (sas_device->id == starget->id) && |
| @@ -1369,7 +1367,7 @@ scsih_target_destroy(struct scsi_target *starget) · 23 unmodified lines | ||
| 1369 | 1367 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1370 | 1368 | * the device is ignored. |
| 1371 | 1369 | */ |
| 1372 | −int | |
| 1370 | +static int | |
| 1373 | 1371 | scsih_slave_alloc(struct scsi_device *sdev) |
| 1374 | 1372 | { |
| 1375 | 1373 | struct Scsi_Host *shost; |
| @@ -1434,7 +1432,7 @@ scsih_slave_alloc(struct scsi_device *sdev) · 58 unmodified lines | ||
| 1434 | 1432 | * |
| 1435 | 1433 | * Returns nothing. |
| 1436 | 1434 | */ |
| 1437 | −void | |
| 1435 | +static void | |
| 1438 | 1436 | scsih_slave_destroy(struct scsi_device *sdev) |
| 1439 | 1437 | { |
| 1440 | 1438 | struct MPT3SAS_TARGET *sas_target_priv_data; |
| @@ -1527,7 +1525,7 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, · 86 unmodified lines | ||
| 1527 | 1525 | * scsih_is_raid - return boolean indicating device is raid volume |
| 1528 | 1526 | * @dev the device struct object |
| 1529 | 1527 | */ |
| 1530 | −int | |
| 1528 | +static int | |
| 1531 | 1529 | scsih_is_raid(struct device *dev) |
| 1532 | 1530 | { |
| 1533 | 1531 | struct scsi_device *sdev = to_scsi_device(dev); |
| @@ -1542,7 +1540,7 @@ scsih_is_raid(struct device *dev) · 8 unmodified lines | ||
| 1542 | 1540 | * scsih_get_resync - get raid volume resync percent complete |
| 1543 | 1541 | * @dev the device struct object |
| 1544 | 1542 | */ |
| 1545 | −void | |
| 1543 | +static void | |
| 1546 | 1544 | scsih_get_resync(struct device *dev) |
| 1547 | 1545 | { |
| 1548 | 1546 | struct scsi_device *sdev = to_scsi_device(dev); |
| @@ -1603,7 +1601,7 @@ scsih_get_resync(struct device *dev) · 54 unmodified lines | ||
| 1603 | 1601 | * scsih_get_state - get raid volume level |
| 1604 | 1602 | * @dev the device struct object |
| 1605 | 1603 | */ |
| 1606 | −void | |
| 1604 | +static void | |
| 1607 | 1605 | scsih_get_state(struct device *dev) |
| 1608 | 1606 | { |
| 1609 | 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 | 1803 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1806 | 1804 | * the device is ignored. |
| 1807 | 1805 | */ |
| 1808 | −int | |
| 1806 | +static int | |
| 1809 | 1807 | scsih_slave_configure(struct scsi_device *sdev) |
| 1810 | 1808 | { |
| 1811 | 1809 | struct Scsi_Host *shost = sdev->host; |
| @@ -2021,7 +2019,7 @@ scsih_slave_configure(struct scsi_device *sdev) · 209 unmodified lines | ||
| 2021 | 2019 | * |
| 2022 | 2020 | * Return nothing. |
| 2023 | 2021 | */ |
| 2024 | −int | |
| 2022 | +static int | |
| 2025 | 2023 | scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, |
| 2026 | 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 | 2199 | * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) |
| 2202 | 2200 | * @smid_task: smid assigned to the task |
| 2203 | 2201 | * @timeout: timeout in seconds |
| 2204 | − * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF | |
| 2205 | 2202 | * Context: user |
| 2206 | 2203 | * |
| 2207 | 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 | 2210 | int |
| 2214 | 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, | |
| 2216 | − enum mutex_type m_type) | |
| 2212 | + uint id, uint lun, u8 type, u16 smid_task, ulong timeout) | |
| 2217 | 2213 | { |
| 2218 | 2214 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
| 2219 | 2215 | Mpi2SCSITaskManagementReply_t *mpi_reply; |
| 2220 | 2216 | u16 smid = 0; |
| 2221 | 2217 | u32 ioc_state; |
| 2222 | − unsigned long timeleft; | |
| 2223 | 2218 | struct scsiio_tracker *scsi_lookup = NULL; |
| 2224 | 2219 | int rc; |
| 2225 | 2220 | u16 msix_task = 0; |
| 2226 | 2221 | |
| 2227 | − if (m_type == TM_MUTEX_ON) | |
| 2228 | − mutex_lock(&ioc->tm_cmds.mutex); | |
| 2222 | + lockdep_assert_held(&ioc->tm_cmds.mutex); | |
| 2223 | + | |
| 2229 | 2224 | if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) { |
| 2230 | 2225 | pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n", |
| 2231 | 2226 | __func__, ioc->name); |
| 2232 | − rc = FAILED; | |
| 2233 | − goto err_out; | |
| 2227 | + return FAILED; | |
| 2234 | 2228 | } |
| 2235 | 2229 | |
| 2236 | 2230 | if (ioc->shost_recovery || ioc->remove_host || |
| 2237 | 2231 | ioc->pci_error_recovery) { |
| 2238 | 2232 | pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", |
| 2239 | 2233 | __func__, ioc->name); |
| 2240 | − rc = FAILED; | |
| 2241 | − goto err_out; | |
| 2234 | + return FAILED; | |
| 2242 | 2235 | } |
| 2243 | 2236 | |
| 2244 | 2237 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); |
| 2245 | 2238 | if (ioc_state & MPI2_DOORBELL_USED) { |
| 2246 | 2239 | dhsprintk(ioc, pr_info(MPT3SAS_FMT |
| 2247 | 2240 | "unexpected doorbell active!\n", ioc->name)); |
| 2248 | − rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 2249 | − FORCE_BIG_HAMMER); | |
| 2250 | − rc = (!rc) ? SUCCESS : FAILED; | |
| 2251 | − goto err_out; | |
| 2241 | + rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 2242 | + return (!rc) ? SUCCESS : FAILED; | |
| 2252 | 2243 | } |
| 2253 | 2244 | |
| 2254 | 2245 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { |
| 2255 | 2246 | mpt3sas_base_fault_info(ioc, ioc_state & |
| 2256 | 2247 | MPI2_DOORBELL_DATA_MASK); |
| 2257 | − rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 2258 | − FORCE_BIG_HAMMER); | |
| 2259 | − rc = (!rc) ? SUCCESS : FAILED; | |
| 2260 | − goto err_out; | |
| 2248 | + rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 2249 | + return (!rc) ? SUCCESS : FAILED; | |
| 2261 | 2250 | } |
| 2262 | 2251 | |
| 2263 | 2252 | smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); |
| 2264 | 2253 | if (!smid) { |
| 2265 | 2254 | pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", |
| 2266 | 2255 | ioc->name, __func__); |
| 2267 | − rc = FAILED; | |
| 2268 | − goto err_out; | |
| 2256 | + return FAILED; | |
| 2269 | 2257 | } |
| 2270 | 2258 | |
| 2271 | 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 | 2280 | else |
| 2293 | 2281 | msix_task = 0; |
| 2294 | 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 | 2284 | if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { |
| 2297 | 2285 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 2298 | 2286 | ioc->name, __func__); |
| 2299 | 2287 | _debug_dump_mf(mpi_request, |
| 2300 | 2288 | sizeof(Mpi2SCSITaskManagementRequest_t)/4); |
| 2301 | 2289 | if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) { |
| 2302 | − rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 2303 | − FORCE_BIG_HAMMER); | |
| 2290 | + rc = mpt3sas_base_hard_reset_handler(ioc, | |
| 2291 | + FORCE_BIG_HAMMER); | |
| 2304 | 2292 | rc = (!rc) ? SUCCESS : FAILED; |
| 2305 | − ioc->tm_cmds.status = MPT3_CMD_NOT_USED; | |
| 2306 | − mpt3sas_scsih_clear_tm_flag(ioc, handle); | |
| 2307 | − goto err_out; | |
| 2293 | + goto 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 | 2342 | break; |
| 2357 | 2343 | } |
| 2358 | 2344 | |
| 2345 | +out: | |
| 2359 | 2346 | mpt3sas_scsih_clear_tm_flag(ioc, handle); |
| 2360 | 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 | 2348 | return rc; |
| 2349 | +} | |
| 2365 | 2350 | |
| 2366 | − err_out: | |
| 2367 | − if (m_type == TM_MUTEX_ON) | |
| 2368 | − mutex_unlock(&ioc->tm_cmds.mutex); | |
| 2369 | − return rc; | |
| 2351 | +int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |
| 2352 | + uint channel, uint id, uint lun, u8 type, u16 smid_task, ulong timeout) | |
| 2353 | +{ | |
| 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 | 2432 | * Returns SUCCESS if command aborted else FAILED |
| 2441 | 2433 | */ |
| 2442 | −int | |
| 2434 | +static int | |
| 2443 | 2435 | scsih_abort(struct scsi_cmnd *scmd) |
| 2444 | 2436 | { |
| 2445 | 2437 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| @@ -2482,9 +2474,9 @@ scsih_abort(struct scsi_cmnd *scmd) · 36 unmodified lines | ||
| 2482 | 2474 | mpt3sas_halt_firmware(ioc); |
| 2483 | 2475 | |
| 2484 | 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 | 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 | 2481 | out: |
| 2490 | 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 | 2491 | * Returns SUCCESS if command aborted else FAILED |
| 2500 | 2492 | */ |
| 2501 | −int | |
| 2493 | +static int | |
| 2502 | 2494 | scsih_dev_reset(struct scsi_cmnd *scmd) |
| 2503 | 2495 | { |
| 2504 | 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 | 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 | 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 | 2540 | out: |
| 2549 | 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 | 2554 | * Returns SUCCESS if command aborted else FAILED |
| 2563 | 2555 | */ |
| 2564 | −int | |
| 2556 | +static int | |
| 2565 | 2557 | scsih_target_reset(struct scsi_cmnd *scmd) |
| 2566 | 2558 | { |
| 2567 | 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 | 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 | 2599 | scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, |
| 2608 | − 30, TM_MUTEX_ON); | |
| 2600 | + 30); | |
| 2609 | 2601 | |
| 2610 | 2602 | out: |
| 2611 | 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 | 2617 | * Returns SUCCESS if command aborted else FAILED |
| 2626 | 2618 | */ |
| 2627 | −int | |
| 2619 | +static int | |
| 2628 | 2620 | scsih_host_reset(struct scsi_cmnd *scmd) |
| 2629 | 2621 | { |
| 2630 | 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 | 2633 | goto out; |
| 2642 | 2634 | } |
| 2643 | 2635 | |
| 2644 | − retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 2645 | − FORCE_BIG_HAMMER); | |
| 2636 | + retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 2646 | 2637 | r = (retval < 0) ? FAILED : SUCCESS; |
| 2647 | 2638 | out: |
| 2648 | 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 | 3447 | * Context - processed in interrupt context. |
| 3457 | 3448 | */ |
| 3458 | −void | |
| 3449 | +static void | |
| 3459 | 3450 | _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, |
| 3460 | 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 | 3486 | * Context - processed in interrupt context. |
| 3496 | 3487 | */ |
| 3497 | −void | |
| 3488 | +static void | |
| 3498 | 3489 | _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, |
| 3499 | 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 | 4023 | * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or |
| 4033 | 4024 | * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full |
| 4034 | 4025 | */ |
| 4035 | −int | |
| 4026 | +static int | |
| 4036 | 4027 | scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) |
| 4037 | 4028 | { |
| 4038 | 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 | 4692 | le16_to_cpu(mpi_reply->DevHandle)); |
| 4702 | 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 | 4696 | ((scmd->sense_buffer[2] == UNIT_ATTENTION) || |
| 4706 | 4697 | (scmd->sense_buffer[2] == MEDIUM_ERROR) || |
| 4707 | 4698 | (scmd->sense_buffer[2] == HARDWARE_ERROR))) |
| @@ -5380,8 +5371,9 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, · 672 unmodified lines | ||
| 5380 | 5371 | MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { |
| 5381 | 5372 | sas_device->enclosure_level = |
| 5382 | 5373 | le16_to_cpu(sas_device_pg0.EnclosureLevel); |
| 5383 | − memcpy(&sas_device->connector_name[0], | |
| 5384 | − &sas_device_pg0.ConnectorName[0], 4); | |
| 5374 | + memcpy(sas_device->connector_name, | |
| 5375 | + sas_device_pg0.ConnectorName, 4); | |
| 5376 | + sas_device->connector_name[4] = '\0'; | |
| 5385 | 5377 | } else { |
| 5386 | 5378 | sas_device->enclosure_level = 0; |
| 5387 | 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 | 5500 | if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { |
| 5509 | 5501 | sas_device->enclosure_level = |
| 5510 | 5502 | le16_to_cpu(sas_device_pg0.EnclosureLevel); |
| 5511 | − memcpy(&sas_device->connector_name[0], | |
| 5512 | − &sas_device_pg0.ConnectorName[0], 4); | |
| 5503 | + memcpy(sas_device->connector_name, | |
| 5504 | + sas_device_pg0.ConnectorName, 4); | |
| 5505 | + sas_device->connector_name[4] = '\0'; | |
| 5513 | 5506 | } else { |
| 5514 | 5507 | sas_device->enclosure_level = 0; |
| 5515 | 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 | 6081 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
| 6089 | 6082 | r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun, |
| 6090 | − MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, | |
| 6091 | − TM_MUTEX_OFF); | |
| 6083 | + MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); | |
| 6092 | 6084 | if (r == FAILED) { |
| 6093 | 6085 | sdev_printk(KERN_WARNING, sdev, |
| 6094 | 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 | 6120 | goto out_no_lock; |
| 6129 | 6121 | |
| 6130 | 6122 | r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, |
| 6131 | − sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, | |
| 6132 | − TM_MUTEX_OFF); | |
| 6123 | + sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, | |
| 6124 | + 30); | |
| 6133 | 6125 | if (r == FAILED) { |
| 6134 | 6126 | sdev_printk(KERN_WARNING, sdev, |
| 6135 | 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 | 6289 | mutex_unlock(&ioc->scsih_cmds.mutex); |
| 6298 | 6290 | |
| 6299 | 6291 | if (issue_reset) |
| 6300 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 6301 | − FORCE_BIG_HAMMER); | |
| 6292 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 6302 | 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 | 6302 | static void |
| 6312 | 6303 | _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) |
| 6313 | 6304 | { |
| 6314 | − int rc; | |
| 6315 | 6305 | sdev->no_uld_attach = no_uld_attach ? 1 : 0; |
| 6316 | 6306 | sdev_printk(KERN_INFO, sdev, "%s raid component\n", |
| 6317 | 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 | 8127 | * Routine called when unloading the driver. |
| 8138 | 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 | 8132 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8143 | 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 | 8201 | * Return nothing. |
| 8212 | 8202 | */ |
| 8213 | −void | |
| 8203 | +static void | |
| 8214 | 8204 | scsih_shutdown(struct pci_dev *pdev) |
| 8215 | 8205 | { |
| 8216 | 8206 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8451,7 +8441,7 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc) · 234 unmodified lines | ||
| 8451 | 8441 | * of scanning the entire bus. In our implemention, we will kick off |
| 8452 | 8442 | * firmware discovery. |
| 8453 | 8443 | */ |
| 8454 | −void | |
| 8444 | +static void | |
| 8455 | 8445 | scsih_scan_start(struct Scsi_Host *shost) |
| 8456 | 8446 | { |
| 8457 | 8447 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8478,7 +8468,7 @@ scsih_scan_start(struct Scsi_Host *shost) · 20 unmodified lines | ||
| 8478 | 8468 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, |
| 8479 | 8469 | * we wait for firmware discovery to complete, then return 1. |
| 8480 | 8470 | */ |
| 8481 | −int | |
| 8471 | +static int | |
| 8482 | 8472 | scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) |
| 8483 | 8473 | { |
| 8484 | 8474 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8608,7 +8598,7 @@ static struct raid_function_template mpt3sas_raid_functions = { · 123 unmodified lines | ||
| 8608 | 8598 | * MPI25_VERSION for SAS 3.0 HBA devices, and |
| 8609 | 8599 | * MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices |
| 8610 | 8600 | */ |
| 8611 | −u16 | |
| 8601 | +static u16 | |
| 8612 | 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 | 8651 | * Returns 0 success, anything else error. |
| 8662 | 8652 | */ |
| 8663 | −int | |
| 8653 | +static int | |
| 8664 | 8654 | _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 8665 | 8655 | { |
| 8666 | 8656 | struct MPT3SAS_ADAPTER *ioc; |
| @@ -8869,7 +8859,7 @@ out_add_shost_fail: · 202 unmodified lines | ||
| 8869 | 8859 | * |
| 8870 | 8860 | * Returns 0 success, anything else error. |
| 8871 | 8861 | */ |
| 8872 | −int | |
| 8862 | +static int | |
| 8873 | 8863 | scsih_suspend(struct pci_dev *pdev, pm_message_t state) |
| 8874 | 8864 | { |
| 8875 | 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 | 8887 | * Returns 0 success, anything else error. |
| 8898 | 8888 | */ |
| 8899 | −int | |
| 8889 | +static int | |
| 8900 | 8890 | scsih_resume(struct pci_dev *pdev) |
| 8901 | 8891 | { |
| 8902 | 8892 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8916,7 +8906,7 @@ scsih_resume(struct pci_dev *pdev) · 13 unmodified lines | ||
| 8916 | 8906 | if (r) |
| 8917 | 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 | 8910 | scsi_unblock_requests(shost); |
| 8921 | 8911 | mpt3sas_base_start_watchdog(ioc); |
| 8922 | 8912 | return 0; |
| @@ -8933,7 +8923,7 @@ scsih_resume(struct pci_dev *pdev) · 10 unmodified lines | ||
| 8933 | 8923 | * Return value: |
| 8934 | 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 | 8927 | scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) |
| 8938 | 8928 | { |
| 8939 | 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 | 8960 | * code after the PCI slot has been reset, just before we |
| 8971 | 8961 | * should resume normal operations. |
| 8972 | 8962 | */ |
| 8973 | −pci_ers_result_t | |
| 8963 | +static pci_ers_result_t | |
| 8974 | 8964 | scsih_pci_slot_reset(struct pci_dev *pdev) |
| 8975 | 8965 | { |
| 8976 | 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 | 8977 | if (rc) |
| 8988 | 8978 | return PCI_ERS_RESULT_DISCONNECT; |
| 8989 | 8979 | |
| 8990 | − rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 8991 | − FORCE_BIG_HAMMER); | |
| 8980 | + rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 8992 | 8981 | |
| 8993 | 8982 | pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name, |
| 8994 | 8983 | (rc == 0) ? "success" : "failed"); |
| @@ -9007,7 +8996,7 @@ scsih_pci_slot_reset(struct pci_dev *pdev) · 12 unmodified lines | ||
| 9007 | 8996 | * OK to resume normal operation. Use completion to allow |
| 9008 | 8997 | * halted scsi ops to resume. |
| 9009 | 8998 | */ |
| 9010 | −void | |
| 8999 | +static void | |
| 9011 | 9000 | scsih_pci_resume(struct pci_dev *pdev) |
| 9012 | 9001 | { |
| 9013 | 9002 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -9024,7 +9013,7 @@ scsih_pci_resume(struct pci_dev *pdev) · 10 unmodified lines | ||
| 9024 | 9013 | * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers |
| 9025 | 9014 | * @pdev: pointer to PCI device |
| 9026 | 9015 | */ |
| 9027 | −pci_ers_result_t | |
| 9016 | +static pci_ers_result_t | |
| 9028 | 9017 | scsih_pci_mmio_enabled(struct pci_dev *pdev) |
| 9029 | 9018 | { |
| 9030 | 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 | 9142 | * Returns 0 success, anything else error. |
| 9154 | 9143 | */ |
| 9155 | −int | |
| 9144 | +static int | |
| 9156 | 9145 | scsih_init(void) |
| 9157 | 9146 | { |
| 9158 | 9147 | mpt2_ids = 0; |
| @@ -9202,7 +9191,7 @@ scsih_init(void) · 43 unmodified lines | ||
| 9202 | 9191 | * |
| 9203 | 9192 | * Returns 0 success, anything else error. |
| 9204 | 9193 | */ |
| 9205 | −void | |
| 9194 | +static void | |
| 9206 | 9195 | scsih_exit(void) |
| 9207 | 9196 | { |
| 9208 | 9197 | |
| @@ -300,7 +300,6 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, · 299 unmodified lines | ||
| 300 | 300 | int rc; |
| 301 | 301 | u16 smid; |
| 302 | 302 | u32 ioc_state; |
| 303 | − unsigned long timeleft; | |
| 304 | 303 | void *psge; |
| 305 | 304 | u8 issue_reset = 0; |
| 306 | 305 | void *data_out = NULL; |
| @@ -394,8 +393,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, · 87 unmodified lines | ||
| 394 | 393 | ioc->name, (unsigned long long)sas_address)); |
| 395 | 394 | init_completion(&ioc->transport_cmds.done); |
| 396 | 395 | mpt3sas_base_put_smid_default(ioc, smid); |
| 397 | − timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | |
| 398 | − 10*HZ); | |
| 396 | + wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); | |
| 399 | 397 | |
| 400 | 398 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 401 | 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 | 445 | issue_host_reset: |
| 448 | 446 | if (issue_reset) |
| 449 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 450 | − FORCE_BIG_HAMMER); | |
| 447 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 451 | 448 | out: |
| 452 | 449 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; |
| 453 | 450 | if (data_out) |
| @@ -1107,7 +1104,6 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, · 653 unmodified lines | ||
| 1107 | 1104 | int rc; |
| 1108 | 1105 | u16 smid; |
| 1109 | 1106 | u32 ioc_state; |
| 1110 | − unsigned long timeleft; | |
| 1111 | 1107 | void *psge; |
| 1112 | 1108 | u8 issue_reset = 0; |
| 1113 | 1109 | void *data_out = NULL; |
| @@ -1203,8 +1199,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, · 89 unmodified lines | ||
| 1203 | 1199 | phy->number)); |
| 1204 | 1200 | init_completion(&ioc->transport_cmds.done); |
| 1205 | 1201 | mpt3sas_base_put_smid_default(ioc, smid); |
| 1206 | − timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | |
| 1207 | − 10*HZ); | |
| 1202 | + wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); | |
| 1208 | 1203 | |
| 1209 | 1204 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 1210 | 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 | 1249 | issue_host_reset: |
| 1255 | 1250 | if (issue_reset) |
| 1256 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 1257 | − FORCE_BIG_HAMMER); | |
| 1251 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 1258 | 1252 | out: |
| 1259 | 1253 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; |
| 1260 | 1254 | if (data_out) |
| @@ -1421,7 +1415,6 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, · 160 unmodified lines | ||
| 1421 | 1415 | int rc; |
| 1422 | 1416 | u16 smid; |
| 1423 | 1417 | u32 ioc_state; |
| 1424 | − unsigned long timeleft; | |
| 1425 | 1418 | void *psge; |
| 1426 | 1419 | u8 issue_reset = 0; |
| 1427 | 1420 | void *data_out = NULL; |
| @@ -1522,8 +1515,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, · 94 unmodified lines | ||
| 1522 | 1515 | phy->number, phy_operation)); |
| 1523 | 1516 | init_completion(&ioc->transport_cmds.done); |
| 1524 | 1517 | mpt3sas_base_put_smid_default(ioc, smid); |
| 1525 | − timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | |
| 1526 | − 10*HZ); | |
| 1518 | + wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); | |
| 1527 | 1519 | |
| 1528 | 1520 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 1529 | 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 | 1557 | issue_host_reset: |
| 1566 | 1558 | if (issue_reset) |
| 1567 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 1568 | − FORCE_BIG_HAMMER); | |
| 1559 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 1569 | 1560 | out: |
| 1570 | 1561 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; |
| 1571 | 1562 | if (data_out) |
| @@ -1899,7 +1890,6 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, · 327 unmodified lines | ||
| 1899 | 1890 | int rc; |
| 1900 | 1891 | u16 smid; |
| 1901 | 1892 | u32 ioc_state; |
| 1902 | − unsigned long timeleft; | |
| 1903 | 1893 | void *psge; |
| 1904 | 1894 | u8 issue_reset = 0; |
| 1905 | 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 | 2034 | init_completion(&ioc->transport_cmds.done); |
| 2045 | 2035 | mpt3sas_base_put_smid_default(ioc, smid); |
| 2046 | − timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | |
| 2047 | − 10*HZ); | |
| 2036 | + wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); | |
| 2048 | 2037 | |
| 2049 | 2038 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 2050 | 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 | 2093 | issue_host_reset: |
| 2105 | 2094 | if (issue_reset) { |
| 2106 | − mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | |
| 2107 | − FORCE_BIG_HAMMER); | |
| 2095 | + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); | |
| 2108 | 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 | 142 | void __iomem *regs = mvi->regs; |
| 142 | 143 | u32 tmp; |
| @@ -563,7 +564,7 @@ static u8 mvs_64xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs) · 420 unmodified lines | ||
| 563 | 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 | 569 | int i; |
| 569 | 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 | 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 | 638 | struct sas_phy_linkrates *rates) |
| 638 | 639 | { |
| 639 | 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 | 674 | void __iomem *regs = mvi->regs_ex; |
| 674 | 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 | 680 | void __iomem *regs = mvi->regs_ex; |
| 680 | 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 | 686 | u32 *dwCmd, |
| 686 | 687 | u8 cmd, |
| 687 | 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 | 711 | void __iomem *regs = mvi->regs_ex; |
| 711 | 712 | int retry; |
| @@ -720,7 +721,7 @@ int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) · 8 unmodified lines | ||
| 720 | 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 | 726 | void __iomem *regs = mvi->regs_ex; |
| 726 | 727 | u32 i, dwTmp; |
| @@ -735,7 +736,7 @@ int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) · 8 unmodified lines | ||
| 735 | 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 | 740 | int buf_len, int from, void *prd) |
| 740 | 741 | { |
| 741 | 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, | |
| 52 | − struct phy_tuning phy_tuning) | |
| 51 | +static void set_phy_tuning(struct mvs_info *mvi, int phy_id, | |
| 52 | + struct phy_tuning phy_tuning) | |
| 53 | 53 | { |
| 54 | 54 | u32 tmp, setting_0 = 0, setting_1 = 0; |
| 55 | 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, | |
| 114 | − struct ffe_control ffe) | |
| 113 | +static void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id, | |
| 114 | + struct ffe_control ffe) | |
| 115 | 115 | { |
| 116 | 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 | 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 | 182 | union reg_phy_cfg phy_cfg, phy_cfg_tmp; |
| 183 | 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 | 685 | void __iomem *regs = mvi->regs; |
| 685 | 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 | − struct sas_phy_linkrates *rates) | |
| 910 | +static void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, | |
| 911 | + struct sas_phy_linkrates *rates) | |
| 911 | 912 | { |
| 912 | 913 | u32 lrmax = 0; |
| 913 | 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 | 942 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 942 | 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 | 948 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 948 | 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 | − u32 *dwCmd, | |
| 954 | − u8 cmd, | |
| 955 | − u8 read, | |
| 956 | − u8 length, | |
| 957 | − u32 addr | |
| 953 | +static int mvs_94xx_spi_buildcmd(struct mvs_info *mvi, | |
| 954 | + u32 *dwCmd, | |
| 955 | + u8 cmd, | |
| 956 | + u8 read, | |
| 957 | + u8 length, | |
| 958 | + u32 addr | |
| 958 | 959 | ) |
| 959 | 960 | { |
| 960 | 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 | 980 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 980 | 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 | 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 | 988 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 988 | 989 | u32 i, dwTmp; |
| @@ -997,8 +998,8 @@ int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) · 8 unmodified lines | ||
| 997 | 998 | return -1; |
| 998 | 999 | } |
| 999 | 1000 | |
| 1000 | −void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, | |
| 1001 | − int buf_len, int from, void *prd) | |
| 1001 | +static void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, | |
| 1002 | + int buf_len, int from, void *prd) | |
| 1002 | 1003 | { |
| 1003 | 1004 | int i; |
| 1004 | 1005 | struct mvs_prd *buf_prd = prd; |
| @@ -74,7 +74,7 @@ void mvs_tag_init(struct mvs_info *mvi) · 73 unmodified lines | ||
| 74 | 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 | 79 | unsigned long i = 0, j = 0, hi = 0; |
| 80 | 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 | 107 | unsigned long i = 0, j = 0, n = 0, num = 0; |
| 108 | 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 | 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 | 1163 | u32 dev; |
| 1164 | 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 | 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 | 1180 | u32 id = mvi_dev->device_id; |
| 1181 | 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 | 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 | 1190 | unsigned long flags = 0; |
| 1191 | 1191 | int res = 0; |
| @@ -1241,7 +1241,7 @@ int mvs_dev_found(struct domain_device *dev) · 49 unmodified lines | ||
| 1241 | 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 | 1246 | unsigned long flags = 0; |
| 1247 | 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 | 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 | 1615 | int key, int asc, int ascq) |
| 1616 | 1616 | { |
| 1617 | 1617 | memset(buffer, 0, len); |
| @@ -1650,7 +1650,7 @@ void mvs_set_sense(u8 *buffer, int len, int d_sense, · 32 unmodified lines | ||
| 1650 | 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 | 1654 | u8 key, u8 asc, u8 asc_q) |
| 1655 | 1655 | { |
| 1656 | 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 | 4492 | * @num: the inbound queue number |
| 4493 | 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, | |
| 4496 | − u8 phy_id) | |
| 4495 | +static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, | |
| 4496 | + u8 phy_id) | |
| 4497 | 4497 | { |
| 4498 | 4498 | struct phy_stop_req payload; |
| 4499 | 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 | 527 | * pm8001_alloc_dev - find a empty pm8001_device |
| 528 | 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 | 532 | u32 dev; |
| 533 | 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 | 306 | * Return Value |
| 307 | 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 | 311 | struct pmcraid_ioarcb *ioarcb = &(cmd->ioa_cb->ioarcb); |
| 312 | 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 | 401 | * Return Value: |
| 402 | 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 | 406 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
| 407 | 407 | unsigned long lock_flags; |
| @@ -1710,7 +1710,7 @@ static struct pmcraid_ioasc_error *pmcraid_get_error_info(u32 ioasc) · 1302 unmodified lines | ||
| 1710 | 1710 | * @ioasc: ioasc code |
| 1711 | 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 | 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 | 3137 | * returns pointer pmcraid_ioadl_desc, initialized to point to internal |
| 3138 | 3138 | * or external IOADLs |
| 3139 | 3139 | */ |
| 3140 | −struct pmcraid_ioadl_desc * | |
| 3140 | +static struct pmcraid_ioadl_desc * | |
| 3141 | 3141 | pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount) |
| 3142 | 3142 | { |
| 3143 | 3143 | struct pmcraid_ioadl_desc *ioadl; |
| @@ -278,16 +278,6 @@ · 277 unmodified lines | ||
| 278 | 278 | struct req_que; |
| 279 | 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 | 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 | 1828 | if (scsi_prot_sg_count(cmd)) { |
| 1829 | 1829 | uint32_t i, j = 0, k = 0, num_ent; |
| 1830 | 1830 | struct scatterlist *sg; |
| 1831 | − struct sd_dif_tuple *spt; | |
| 1831 | + struct t10_pi_tuple *spt; | |
| 1832 | 1832 | |
| 1833 | 1833 | /* Patch the corresponding protection tags */ |
| 1834 | 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 | 899 | struct qla_hw_data *ha = vha->hw; |
| 900 | 900 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
| 901 | 901 | |
| 902 | − while (((qla2x00_reset_active(vha)) || ha->dpc_active || | |
| 903 | − ha->flags.mbox_busy) || | |
| 904 | − test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || | |
| 905 | − test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) { | |
| 906 | − if (test_bit(UNLOADING, &base_vha->dpc_flags)) | |
| 907 | − break; | |
| 902 | + while ((qla2x00_reset_active(vha) || ha->dpc_active || | |
| 903 | + ha->flags.mbox_busy) || | |
| 904 | + test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || | |
| 905 | + test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) { | |
| 906 | + if (test_bit(UNLOADING, &base_vha->dpc_flags)) | |
| 907 | + break; | |
| 908 | 908 | msleep(1000); |
| 909 | 909 | } |
| 910 | 910 | } |
| @@ -4694,7 +4694,7 @@ retry_unlock: · 3783 unmodified lines | ||
| 4694 | 4694 | qla83xx_wait_logic(); |
| 4695 | 4695 | retry++; |
| 4696 | 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 | 4698 | goto retry_unlock; |
| 4699 | 4699 | } |
| 4700 | 4700 | } else if (retry < 10) { |
| @@ -4702,7 +4702,7 @@ retry_unlock: · 1 unmodified line | ||
| 4702 | 4702 | qla83xx_wait_logic(); |
| 4703 | 4703 | retry++; |
| 4704 | 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 | 4706 | goto retry_unlock; |
| 4707 | 4707 | } |
| 4708 | 4708 | |
| @@ -4718,7 +4718,7 @@ retry_unlock2: · 9 unmodified lines | ||
| 4718 | 4718 | qla83xx_wait_logic(); |
| 4719 | 4719 | retry++; |
| 4720 | 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 | 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 | 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 | 1847 | uint32_t addr3, uint32_t mask, uint32_t addr, |
| 1848 | 1848 | uint32_t *data_ptr) |
| 1849 | 1849 | { |
| @@ -42,6 +42,7 @@ · 41 unmodified lines | ||
| 42 | 42 | #include <linux/atomic.h> |
| 43 | 43 | #include <linux/hrtimer.h> |
| 44 | 44 | #include <linux/uuid.h> |
| 45 | +#include <linux/t10-pi.h> | |
| 45 | 46 | |
| 46 | 47 | #include <net/checksum.h> |
| 47 | 48 | |
| @@ -627,7 +628,7 @@ static LIST_HEAD(sdebug_host_list); · 579 unmodified lines | ||
| 627 | 628 | static DEFINE_SPINLOCK(sdebug_host_list_lock); |
| 628 | 629 | |
| 629 | 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 | 632 | static void *map_storep; /* provisioning map */ |
| 632 | 633 | |
| 633 | 634 | static unsigned long map_size; |
| @@ -682,7 +683,7 @@ static void *fake_store(unsigned long long lba) · 48 unmodified lines | ||
| 682 | 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 | 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 | 1350 | } else if (0x86 == cmd[2]) { /* extended inquiry */ |
| 1350 | 1351 | arr[1] = cmd[2]; /*sanity */ |
| 1351 | 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 | 1354 | arr[4] = 0x4; /* SPT: GRD_CHK:1 */ |
| 1354 | 1355 | else if (have_dif_prot) |
| 1355 | 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 | 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 | 2435 | sector_t sector, u32 ei_lba) |
| 2435 | 2436 | { |
| 2436 | 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 | 2443 | be16_to_cpu(csum)); |
| 2443 | 2444 | return 0x01; |
| 2444 | 2445 | } |
| 2445 | − if (sdebug_dif == SD_DIF_TYPE1_PROTECTION && | |
| 2446 | + if (sdebug_dif == T10_PI_TYPE1_PROTECTION && | |
| 2446 | 2447 | be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { |
| 2447 | 2448 | pr_err("REF check failed on sector %lu\n", |
| 2448 | 2449 | (unsigned long)sector); |
| 2449 | 2450 | return 0x03; |
| 2450 | 2451 | } |
| 2451 | − if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && | |
| 2452 | + if (sdebug_dif == T10_PI_TYPE2_PROTECTION && | |
| 2452 | 2453 | be32_to_cpu(sdt->ref_tag) != ei_lba) { |
| 2453 | 2454 | pr_err("REF check failed on sector %lu\n", |
| 2454 | 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 | 2505 | unsigned int sectors, u32 ei_lba) |
| 2505 | 2506 | { |
| 2506 | 2507 | unsigned int i; |
| 2507 | − struct sd_dif_tuple *sdt; | |
| 2508 | + struct t10_pi_tuple *sdt; | |
| 2508 | 2509 | sector_t sector; |
| 2509 | 2510 | |
| 2510 | 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 | 2581 | break; |
| 2581 | 2582 | } |
| 2582 | 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 | 2585 | (cmd[1] & 0xe0)) { |
| 2585 | 2586 | mk_sense_invalid_opcode(scp); |
| 2586 | 2587 | return check_condition_result; |
| 2587 | 2588 | } |
| 2588 | − if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || | |
| 2589 | − sdebug_dif == SD_DIF_TYPE3_PROTECTION) && | |
| 2589 | + if ((sdebug_dif == T10_PI_TYPE1_PROTECTION || | |
| 2590 | + sdebug_dif == T10_PI_TYPE3_PROTECTION) && | |
| 2590 | 2591 | (cmd[1] & 0xe0) == 0) |
| 2591 | 2592 | sdev_printk(KERN_ERR, scp->device, "Unprotected RD " |
| 2592 | 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 | 2697 | unsigned int sectors, u32 ei_lba) |
| 2697 | 2698 | { |
| 2698 | 2699 | int ret; |
| 2699 | − struct sd_dif_tuple *sdt; | |
| 2700 | + struct t10_pi_tuple *sdt; | |
| 2700 | 2701 | void *daddr; |
| 2701 | 2702 | sector_t sector = start_sec; |
| 2702 | 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 | 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 | 2727 | /* If we're at the end of the current |
| 2727 | 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 | 2894 | break; |
| 2894 | 2895 | } |
| 2895 | 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 | 2898 | (cmd[1] & 0xe0)) { |
| 2898 | 2899 | mk_sense_invalid_opcode(scp); |
| 2899 | 2900 | return check_condition_result; |
| 2900 | 2901 | } |
| 2901 | − if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || | |
| 2902 | − sdebug_dif == SD_DIF_TYPE3_PROTECTION) && | |
| 2902 | + if ((sdebug_dif == T10_PI_TYPE1_PROTECTION || | |
| 2903 | + sdebug_dif == T10_PI_TYPE3_PROTECTION) && | |
| 2903 | 2904 | (cmd[1] & 0xe0) == 0) |
| 2904 | 2905 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " |
| 2905 | 2906 | "to DIF device\n"); |
| @@ -3135,13 +3136,13 @@ static int resp_comp_write(struct scsi_cmnd *scp, · 229 unmodified lines | ||
| 3135 | 3136 | num = cmd[13]; /* 1 to a maximum of 255 logical blocks */ |
| 3136 | 3137 | if (0 == num) |
| 3137 | 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 | 3140 | (cmd[1] & 0xe0)) { |
| 3140 | 3141 | mk_sense_invalid_opcode(scp); |
| 3141 | 3142 | return check_condition_result; |
| 3142 | 3143 | } |
| 3143 | − if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || | |
| 3144 | − sdebug_dif == SD_DIF_TYPE3_PROTECTION) && | |
| 3144 | + if ((sdebug_dif == T10_PI_TYPE1_PROTECTION || | |
| 3145 | + sdebug_dif == T10_PI_TYPE3_PROTECTION) && | |
| 3145 | 3146 | (cmd[1] & 0xe0) == 0) |
| 3146 | 3147 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " |
| 3147 | 3148 | "to DIF device\n"); |
| @@ -4939,12 +4940,11 @@ static int __init scsi_debug_init(void) · 1791 unmodified lines | ||
| 4939 | 4940 | } |
| 4940 | 4941 | |
| 4941 | 4942 | switch (sdebug_dif) { |
| 4942 | − | |
| 4943 | − case SD_DIF_TYPE0_PROTECTION: | |
| 4943 | + case T10_PI_TYPE0_PROTECTION: | |
| 4944 | 4944 | break; |
| 4945 | − case SD_DIF_TYPE1_PROTECTION: | |
| 4946 | − case SD_DIF_TYPE2_PROTECTION: | |
| 4947 | − case SD_DIF_TYPE3_PROTECTION: | |
| 4945 | + case T10_PI_TYPE1_PROTECTION: | |
| 4946 | + case T10_PI_TYPE2_PROTECTION: | |
| 4947 | + case T10_PI_TYPE3_PROTECTION: | |
| 4948 | 4948 | have_dif_prot = true; |
| 4949 | 4949 | break; |
| 4950 | 4950 | |
| @@ -5026,7 +5026,7 @@ static int __init scsi_debug_init(void) · 75 unmodified lines | ||
| 5026 | 5026 | if (sdebug_dix) { |
| 5027 | 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 | 5030 | dif_storep = vmalloc(dif_size); |
| 5031 | 5031 | |
| 5032 | 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 | 5481 | switch (sdebug_dif) { |
| 5482 | 5482 | |
| 5483 | − case SD_DIF_TYPE1_PROTECTION: | |
| 5483 | + case T10_PI_TYPE1_PROTECTION: | |
| 5484 | 5484 | hprot = SHOST_DIF_TYPE1_PROTECTION; |
| 5485 | 5485 | if (sdebug_dix) |
| 5486 | 5486 | hprot |= SHOST_DIX_TYPE1_PROTECTION; |
| 5487 | 5487 | break; |
| 5488 | 5488 | |
| 5489 | − case SD_DIF_TYPE2_PROTECTION: | |
| 5489 | + case T10_PI_TYPE2_PROTECTION: | |
| 5490 | 5490 | hprot = SHOST_DIF_TYPE2_PROTECTION; |
| 5491 | 5491 | if (sdebug_dix) |
| 5492 | 5492 | hprot |= SHOST_DIX_TYPE2_PROTECTION; |
| 5493 | 5493 | break; |
| 5494 | 5494 | |
| 5495 | − case SD_DIF_TYPE3_PROTECTION: | |
| 5495 | + case T10_PI_TYPE3_PROTECTION: | |
| 5496 | 5496 | hprot = SHOST_DIF_TYPE3_PROTECTION; |
| 5497 | 5497 | if (sdebug_dix) |
| 5498 | 5498 | hprot |= SHOST_DIX_TYPE3_PROTECTION; |
| @@ -86,12 +86,14 @@ extern void scsi_device_unbusy(struct scsi_device *sdev); · 85 unmodified lines | ||
| 86 | 86 | extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason); |
| 87 | 87 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); |
| 88 | 88 | extern void scsi_run_host_queues(struct Scsi_Host *shost); |
| 89 | +extern void scsi_requeue_run_queue(struct work_struct *work); | |
| 89 | 90 | extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); |
| 90 | 91 | extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); |
| 91 | 92 | extern int scsi_mq_setup_tags(struct Scsi_Host *shost); |
| 92 | 93 | extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); |
| 93 | 94 | extern int scsi_init_queue(void); |
| 94 | 95 | extern void scsi_exit_queue(void); |
| 96 | +extern void scsi_evt_thread(struct work_struct *work); | |
| 95 | 97 | struct request_queue; |
| 96 | 98 | struct request; |
| 97 | 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 | 217 | struct scsi_device *sdev; |
| 218 | 218 | int display_failure_msg = 1, ret; |
| 219 | 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 | 221 | sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, |
| 224 | 222 | GFP_ATOMIC); |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | #include <linux/slab.h> |
| 53 | 53 | #include <linux/pm_runtime.h> |
| 54 | 54 | #include <linux/pr.h> |
| 55 | +#include <linux/t10-pi.h> | |
| 55 | 56 | #include <asm/uaccess.h> |
| 56 | 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 | 315 | if (err) |
| 315 | 316 | return err; |
| 316 | 317 | |
| 317 | − if (val >= 0 && val <= SD_DIF_TYPE3_PROTECTION) | |
| 318 | + if (val >= 0 && val <= T10_PI_TYPE3_PROTECTION) | |
| 318 | 319 | sdkp->protection_type = val; |
| 319 | 320 | |
| 320 | 321 | return count; |
| @@ -332,7 +333,7 @@ protection_mode_show(struct device *dev, struct device_attribute *attr, · 11 unmodified lines | ||
| 332 | 333 | dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); |
| 333 | 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 | 337 | dif = 0; |
| 337 | 338 | dix = 1; |
| 338 | 339 | } |
| @@ -608,7 +609,7 @@ static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, · 269 unmodified lines | ||
| 608 | 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 | 613 | scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; |
| 613 | 614 | |
| 614 | 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 | 1032 | else |
| 1032 | 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 | 1036 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); |
| 1036 | 1037 | |
| 1037 | 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 | 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 | 2002 | ret = -ENODEV; |
| 2002 | 2003 | else if (scsi_host_dif_capable(sdp->host, type)) |
| 2003 | 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 | 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 | 160 | * Look up the DIX operation based on whether the command is read or |
| 182 | 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 | 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 | 221 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
| 252 | 222 | |
| 253 | 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 | 61 | /* Enable DMA of protection information */ |
| 62 | 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 | 64 | bi.profile = &t10_pi_type3_ip; |
| 65 | 65 | else |
| 66 | 66 | bi.profile = &t10_pi_type1_ip; |
| 67 | 67 | |
| 68 | 68 | bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; |
| 69 | 69 | } else |
| 70 | − if (type == SD_DIF_TYPE3_PROTECTION) | |
| 70 | + if (type == T10_PI_TYPE3_PROTECTION) | |
| 71 | 71 | bi.profile = &t10_pi_type3_crc; |
| 72 | 72 | else |
| 73 | 73 | bi.profile = &t10_pi_type1_crc; |
| @@ -82,7 +82,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp) · 8 unmodified lines | ||
| 82 | 82 | if (!sdkp->ATO) |
| 83 | 83 | goto out; |
| 84 | 84 | |
| 85 | − if (type == SD_DIF_TYPE3_PROTECTION) | |
| 85 | + if (type == T10_PI_TYPE3_PROTECTION) | |
| 86 | 86 | bi.tag_size = sizeof(u16) + sizeof(u32); |
| 87 | 87 | else |
| 88 | 88 | bi.tag_size = sizeof(u16); |
| @@ -121,7 +121,7 @@ void sd_dif_prepare(struct scsi_cmnd *scmd) · 32 unmodified lines | ||
| 121 | 121 | |
| 122 | 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 | 125 | return; |
| 126 | 126 | |
| 127 | 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 | 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 | 176 | return; |
| 177 | 177 | |
| 178 | 178 | intervals = good_bytes / scsi_prot_interval(scmd); |
| @@ -79,18 +79,7 @@ static void sg_proc_cleanup(void); · 78 unmodified lines | ||
| 79 | 79 | */ |
| 80 | 80 | #define SG_MAX_CDB_SIZE 252 |
| 81 | 81 | |
| 82 | −/* | |
| 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) | |
| 82 | +#define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ) | |
| 94 | 83 | |
| 95 | 84 | int sg_big_buff = SG_DEF_RESERVED_SIZE; |
| 96 | 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 | 873 | return result; |
| 885 | 874 | if (val < 0) |
| 886 | 875 | return -EIO; |
| 887 | − if (val >= MULDIV (INT_MAX, USER_HZ, HZ)) | |
| 888 | − val = MULDIV (INT_MAX, USER_HZ, HZ); | |
| 876 | + if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ)) | |
| 877 | + val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ), | |
| 878 | + INT_MAX); | |
| 889 | 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 | 882 | return 0; |
| 893 | 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.