SCSI misc on 20161006
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. Signed-off-by: James Bottomley <jejb@linux.vnet.ibm.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJX9fZGAAoJEAVr7HOZEZN4TfkP/2bOHBGqyQ16P9jRjWXtC6pJ Fp/ZfU6ZrSpcGN49Wr9vyPbpvYKdtIZg3oUs6XhKmnfP+lbeIIJ5jxlEnwBVwWya JOOD91o8lLN7zRMuyfYIfgnm4dIU3GSLpnWIyfAhoMH1utiLLcq7s2XEM5girDft dVUL20XprtJkVsg2C+hhRAI8PMjWFInadj2eRIHdxJIDC8fXR+w8ojBShou+lf6Q /zYPgckTCBlZWIc/ohI3j52r4qmkChgX+3/jR+v9i5bGXjFfpmh0GzxM7tscESSa 4Y/ZLTg72j/colYkA1jt04YLxA2dQCa6b8DmJIcUTL0WStsJUQH5hFFFHt3mSafI HirqRfHpmadHbfi5Kiyx688S5b0oVN4bMxvMoEOAUy7WVaLEr84GJ5VYhoAwkPhL USaDx6Hsa1OT0lGYAtyRKOUT/d55grztEOnSxBFiQgRoB8wrGX616Xg8VONy7JZS wEZtf1v5K0+ZXJiu4NtY+/RzQdOwu7OQHKfN5mLri8tJ+eo8d88ZwSARJxEZetSM P4EVR2ZjhL+Ct78v3i4Yj8FVMXHSzzulj530KQ/U7z/l4c2S54mtEKijDmXmto8k baiIah/wgaS/fznoOsJw+Iy/2HqsAtNZsReNcgNPLzfabTBXKSBXJDLmO4d3g/3s zwj1m3JtzAx2j3kQrkSv =cyTO -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi 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 ...
This commit is contained in:
commit
4dfddf5036
@ -121,7 +121,7 @@ Block library API
|
||||
below.
|
||||
|
||||
The block library can be found on GitHub:
|
||||
http://www.github.com/mikehollinger/ibmcapikv
|
||||
http://github.com/open-power/capiflash
|
||||
|
||||
|
||||
CXL Flash Driver IOCTLs
|
||||
@ -171,11 +171,30 @@ DK_CXLFLASH_ATTACH
|
||||
destroyed, the tokens are to be considered stale and subsequent
|
||||
usage will result in errors.
|
||||
|
||||
- When a context is no longer needed, the user shall detach from
|
||||
the context via the DK_CXLFLASH_DETACH ioctl.
|
||||
- A valid adapter file descriptor (fd2 >= 0) is only returned on
|
||||
the initial attach for a context. Subsequent attaches to an
|
||||
existing context (DK_CXLFLASH_ATTACH_REUSE_CONTEXT flag present)
|
||||
do not provide the adapter file descriptor as it was previously
|
||||
made known to the application.
|
||||
|
||||
- A close on fd2 will invalidate the tokens. This operation is not
|
||||
required by the user.
|
||||
- When a context is no longer needed, the user shall detach from
|
||||
the context via the DK_CXLFLASH_DETACH ioctl. When this ioctl
|
||||
returns with a valid adapter file descriptor and the return flag
|
||||
DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
|
||||
close the adapter file descriptor following a successful detach.
|
||||
|
||||
- When this ioctl returns with a valid fd2 and the return flag
|
||||
DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
|
||||
close fd2 in the following circumstances:
|
||||
|
||||
+ Following a successful detach of the last user of the context
|
||||
+ Following a successful recovery on the context's original fd2
|
||||
+ In the child process of a fork(), following a clone ioctl,
|
||||
on the fd2 associated with the source context
|
||||
|
||||
- At any time, a close on fd2 will invalidate the tokens. Applications
|
||||
should exercise caution to only close fd2 when appropriate (outlined
|
||||
in the previous bullet) to avoid premature loss of I/O.
|
||||
|
||||
DK_CXLFLASH_USER_DIRECT
|
||||
-----------------------
|
||||
@ -254,6 +273,10 @@ DK_CXLFLASH_DETACH
|
||||
success, all "tokens" which had been provided to the user from the
|
||||
DK_CXLFLASH_ATTACH onward are no longer valid.
|
||||
|
||||
When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
|
||||
attach, the application _must_ close the fd2 associated with the context
|
||||
following the detach of the final user of the context.
|
||||
|
||||
DK_CXLFLASH_VLUN_CLONE
|
||||
----------------------
|
||||
This ioctl is responsible for cloning a previously created
|
||||
@ -261,7 +284,7 @@ DK_CXLFLASH_VLUN_CLONE
|
||||
support maintaining user space access to storage after a process
|
||||
forks. Upon success, the child process (which invoked the ioctl)
|
||||
will have access to the same LUNs via the same resource handle(s)
|
||||
and fd2 as the parent, but under a different context.
|
||||
as the parent, but under a different context.
|
||||
|
||||
Context sharing across processes is not supported with CXL and
|
||||
therefore each fork must be met with establishing a new context
|
||||
@ -275,6 +298,12 @@ DK_CXLFLASH_VLUN_CLONE
|
||||
translation tables are copied from the parent context to the child's
|
||||
and then synced with the AFU.
|
||||
|
||||
When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
|
||||
attach, the application _must_ close the fd2 associated with the source
|
||||
context (still resident/accessible in the parent process) following the
|
||||
clone. This is to avoid a stale entry in the file descriptor table of the
|
||||
child process.
|
||||
|
||||
DK_CXLFLASH_VERIFY
|
||||
------------------
|
||||
This ioctl is used to detect various changes such as the capacity of
|
||||
@ -309,6 +338,11 @@ DK_CXLFLASH_RECOVER_AFU
|
||||
at which time the context/resources they held will be freed as part of
|
||||
the release fop.
|
||||
|
||||
When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
|
||||
attach, the application _must_ unmap and close the fd2 associated with the
|
||||
original context following this ioctl returning success and indicating that
|
||||
the context was recovered (DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET).
|
||||
|
||||
DK_CXLFLASH_MANAGE_LUN
|
||||
----------------------
|
||||
This ioctl is used to switch a LUN from a mode where it is available
|
||||
|
@ -64,8 +64,6 @@ hpsa.txt
|
||||
- HP Smart Array Controller SCSI driver.
|
||||
hptiop.txt
|
||||
- HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
|
||||
in2000.txt
|
||||
- info on in2000 driver
|
||||
libsas.txt
|
||||
- Serial Attached SCSI management layer.
|
||||
link_power_management_policy.txt
|
||||
|
@ -1,43 +0,0 @@
|
||||
README file for the Linux DTC3180/3280 scsi driver.
|
||||
by Ray Van Tassle (rayvt@comm.mot.com) March 1996
|
||||
Based on the generic & core NCR5380 code by Drew Eckhard
|
||||
|
||||
SCSI device driver for the DTC 3180/3280.
|
||||
Data Technology Corp---a division of Qume.
|
||||
|
||||
The 3280 has a standard floppy interface.
|
||||
|
||||
The 3180 does not. Otherwise, they are identical.
|
||||
|
||||
The DTC3x80 does not support DMA but it does have Pseudo-DMA which is
|
||||
supported by the driver.
|
||||
|
||||
Its DTC406 scsi chip is supposedly compatible with the NCR 53C400.
|
||||
It is memory mapped, uses an IRQ, but no dma or io-port. There is
|
||||
internal DMA, between SCSI bus and an on-chip 128-byte buffer. Double
|
||||
buffering is done automagically by the chip. Data is transferred
|
||||
between the on-chip buffer and CPU/RAM via memory moves.
|
||||
|
||||
The driver detects the possible memory addresses (jumper selectable):
|
||||
CC00, DC00, C800, and D800
|
||||
The possible IRQ's (jumper selectable) are:
|
||||
IRQ 10, 11, 12, 15
|
||||
Parity is supported by the chip, but not by this driver.
|
||||
Information can be obtained from /proc/scsi/dtc3c80/N.
|
||||
|
||||
Note on interrupts:
|
||||
|
||||
The documentation says that it can be set to interrupt whenever the
|
||||
on-chip buffer needs CPU attention. I couldn't get this to work. So
|
||||
the driver polls for data-ready in the pseudo-DMA transfer routine.
|
||||
The interrupt support routines in the NCR3280.c core modules handle
|
||||
scsi disconnect/reconnect, and this (mostly) works. However..... I
|
||||
have tested it with 4 totally different hard drives (both SCSI-1 and
|
||||
SCSI-2), and one CDROM drive. Interrupts works great for all but one
|
||||
specific hard drive. For this one, the driver will eventually hang in
|
||||
the transfer state. I have tested with: "dd bs=4k count=2k
|
||||
of=/dev/null if=/dev/sdb". It reads ok for a while, then hangs.
|
||||
After beating my head against this for a couple of weeks, getting
|
||||
nowhere, I give up. So.....This driver does NOT use interrupts, even
|
||||
if you have the card jumpered to an IRQ. Probably nobody will ever
|
||||
care.
|
@ -1,202 +0,0 @@
|
||||
|
||||
UPDATE NEWS: version 1.33 - 26 Aug 98
|
||||
|
||||
Interrupt management in this driver has become, over
|
||||
time, increasingly odd and difficult to explain - this
|
||||
has been mostly due to my own mental inadequacies. In
|
||||
recent kernels, it has failed to function at all when
|
||||
compiled for SMP. I've fixed that problem, and after
|
||||
taking a fresh look at interrupts in general, greatly
|
||||
reduced the number of places where they're fiddled
|
||||
with. Done some heavy testing and it looks very good.
|
||||
The driver now makes use of the __initfunc() and
|
||||
__initdata macros to save about 4k of kernel memory.
|
||||
Once again, the same code works for both 2.0.xx and
|
||||
2.1.xx kernels.
|
||||
|
||||
UPDATE NEWS: version 1.32 - 28 Mar 98
|
||||
|
||||
Removed the check for legal IN2000 hardware versions:
|
||||
It appears that the driver works fine with serial
|
||||
EPROMs (the 8-pin chip that defines hardware rev) as
|
||||
old as 2.1, so we'll assume that all cards are OK.
|
||||
|
||||
UPDATE NEWS: version 1.31 - 6 Jul 97
|
||||
|
||||
Fixed a bug that caused incorrect SCSI status bytes to be
|
||||
returned from commands sent to LUNs greater than 0. This
|
||||
means that CDROM changers work now! Fixed a bug in the
|
||||
handling of command-line arguments when loaded as a module.
|
||||
Also put all the header data in in2000.h where it belongs.
|
||||
There are no longer any differences between this driver in
|
||||
the 2.1.xx source tree and the 2.0.xx tree, as of 2.0.31
|
||||
and 2.1.45 (or is it .46?) - this makes things much easier
|
||||
for me...
|
||||
|
||||
UPDATE NEWS: version 1.30 - 14 Oct 96
|
||||
|
||||
Fixed a bug in the code that sets the transfer direction
|
||||
bit (DESTID_DPD in the WD_DESTINATION_ID register). There
|
||||
are quite a few SCSI commands that do a write-to-device;
|
||||
now we deal with all of them correctly. Thanks to Joerg
|
||||
Dorchain for catching this one.
|
||||
|
||||
UPDATE NEWS: version 1.29 - 24 Sep 96
|
||||
|
||||
The memory-mapped hardware on the card is now accessed via
|
||||
the 'readb()' and 'readl()' macros - required by the new
|
||||
memory management scheme in the 2.1.x kernel series.
|
||||
As suggested by Andries Brouwer, 'bios_param()' no longer
|
||||
forces an artificial 1023 track limit on drives. Also
|
||||
removed some kludge-code left over from struggles with
|
||||
older (buggy) compilers.
|
||||
|
||||
UPDATE NEWS: version 1.28 - 07 May 96
|
||||
|
||||
Tightened up the "interrupts enabled/disabled" discipline
|
||||
in 'in2000_queuecommand()' and maybe 1 or 2 other places.
|
||||
I _think_ it may have been a little too lax, causing an
|
||||
occasional crash during full moon. A fully functional
|
||||
/proc interface is now in place - if you want to play
|
||||
with it, start by doing 'cat /proc/scsi/in2000/0'. You
|
||||
can also use it to change a few run-time parameters on
|
||||
the fly, but it's mostly for debugging. The curious
|
||||
should take a good look at 'in2000_proc_info()' in the
|
||||
in2000.c file to get an understanding of what it's all
|
||||
about; I figure that people who are really into it will
|
||||
want to add features suited to their own needs...
|
||||
Also, sync is now DISABLED by default.
|
||||
|
||||
UPDATE NEWS: version 1.27 - 10 Apr 96
|
||||
|
||||
Fixed a well-hidden bug in the adaptive-disconnect code
|
||||
that would show up every now and then during extreme
|
||||
heavy loads involving 2 or more simultaneously active
|
||||
devices. Thanks to Joe Mack for keeping my nose to the
|
||||
grindstone on this one.
|
||||
|
||||
UPDATE NEWS: version 1.26 - 07 Mar 96
|
||||
|
||||
1.25 had a nasty bug that bit people with swap partitions
|
||||
and tape drives. Also, in my attempt to guess my way
|
||||
through Intel assembly language, I made an error in the
|
||||
inline code for IO writes. Made a few other changes and
|
||||
repairs - this version (fingers crossed) should work well.
|
||||
|
||||
UPDATE NEWS: version 1.25 - 05 Mar 96
|
||||
|
||||
Kernel 1.3.70 interrupt mods added; old kernels still OK.
|
||||
Big help from Bill Earnest and David Willmore on speed
|
||||
testing and optimizing: I think there's a real improvement
|
||||
in this area.
|
||||
New! User-friendly command-line interface for LILO and
|
||||
module loading - the old method is gone, so you'll need
|
||||
to read the comments for 'setup_strings' near the top
|
||||
of in2000.c. For people with CDROM's or other devices
|
||||
that have a tough time with sync negotiation, you can
|
||||
now selectively disable sync on individual devices -
|
||||
search for the 'nosync' keyword in the command-line
|
||||
comments. Some of you disable the BIOS on the card, which
|
||||
caused the auto-detect function to fail; there is now a
|
||||
command-line option to force detection of a ROM-less card.
|
||||
|
||||
UPDATE NEWS: version 1.24a - 24 Feb 96
|
||||
|
||||
There was a bug in the synchronous transfer code. Only
|
||||
a few people downloaded before I caught it - could have
|
||||
been worse.
|
||||
|
||||
UPDATE NEWS: version 1.24 - 23 Feb 96
|
||||
|
||||
Lots of good changes. Advice from Bill Earnest resulted
|
||||
in much better detection of cards, more efficient usage
|
||||
of the fifo, and (hopefully) faster data transfers. The
|
||||
jury is still out on speed - I hope it's improved some.
|
||||
One nifty new feature is a cool way of doing disconnect/
|
||||
reselect. The driver defaults to what I'm calling
|
||||
'adaptive disconnect' - meaning that each command is
|
||||
evaluated individually as to whether or not it should be
|
||||
run with the option to disconnect/reselect (if the device
|
||||
chooses), or as a "SCSI-bus-hog". When several devices
|
||||
are operating simultaneously, disconnects are usually an
|
||||
advantage. In a single device system, or if only 1 device
|
||||
is being accessed, transfers usually go faster if disconnects
|
||||
are not allowed.
|
||||
|
||||
|
||||
|
||||
The default arguments (you get these when you don't give an 'in2000'
|
||||
command-line argument, or you give a blank argument) will cause
|
||||
the driver to do adaptive disconnect, synchronous transfers, and a
|
||||
minimum of debug messages. If you want to fool with the options,
|
||||
search for 'setup_strings' near the top of the in2000.c file and
|
||||
check the 'hostdata->args' section in in2000.h - but be warned! Not
|
||||
everything is working yet (some things will never work, probably).
|
||||
I believe that disabling disconnects (DIS_NEVER) will allow you
|
||||
to choose a LEVEL2 value higher than 'L2_BASIC', but I haven't
|
||||
spent a lot of time testing this. You might try 'ENABLE_CLUSTERING'
|
||||
to see what happens: my tests showed little difference either way.
|
||||
There's also a define called 'DEFAULT_SX_PER'; this sets the data
|
||||
transfer speed for the asynchronous mode. I've put it at 500 ns
|
||||
despite the fact that the card could handle settings of 376 or
|
||||
252, because higher speeds may be a problem with poor quality
|
||||
cables or improper termination; 500 ns is a compromise. You can
|
||||
choose your own default through the command-line with the
|
||||
'period' keyword.
|
||||
|
||||
|
||||
------------------------------------------------
|
||||
*********** DIP switch settings **************
|
||||
------------------------------------------------
|
||||
|
||||
sw1-1 sw1-2 BIOS address (hex)
|
||||
-----------------------------------------
|
||||
off off C8000 - CBFF0
|
||||
on off D8000 - DBFF0
|
||||
off on D0000 - D3FF0
|
||||
on on BIOS disabled
|
||||
|
||||
sw1-3 sw1-4 IO port address (hex)
|
||||
------------------------------------
|
||||
off off 220 - 22F
|
||||
on off 200 - 20F
|
||||
off on 110 - 11F
|
||||
on on 100 - 10F
|
||||
|
||||
sw1-5 sw1-6 sw1-7 Interrupt
|
||||
------------------------------
|
||||
off off off 15
|
||||
off on off 14
|
||||
off off on 11
|
||||
off on on 10
|
||||
on - - disabled
|
||||
|
||||
sw1-8 function depends on BIOS version. In earlier versions this
|
||||
controlled synchronous data transfer support for MSDOS:
|
||||
off = disabled
|
||||
on = enabled
|
||||
In later ROMs (starting with 01.3 in April 1994) sw1-8 controls
|
||||
the "greater than 2 disk drive" feature that first appeared in
|
||||
MSDOS 5.0 (ignored by Linux):
|
||||
off = 2 drives maximum
|
||||
on = 7 drives maximum
|
||||
|
||||
sw1-9 Floppy controller
|
||||
--------------------------
|
||||
off disabled
|
||||
on enabled
|
||||
|
||||
------------------------------------------------
|
||||
|
||||
I should mention that Drew Eckhardt's 'Generic NCR5380' sources
|
||||
were my main inspiration, with lots of reference to the IN2000
|
||||
driver currently distributed in the kernel source. I also owe
|
||||
much to a driver written by Hamish Macdonald for Linux-m68k(!).
|
||||
And to Eric Wright for being an ALPHA guinea pig. And to Bill
|
||||
Earnest for 2 tons of great input and information. And to David
|
||||
Willmore for extensive 'bonnie' testing. And to Joe Mack for
|
||||
continual testing and feedback.
|
||||
|
||||
|
||||
John Shifflett jshiffle@netcom.com
|
||||
|
@ -34,9 +34,6 @@ parameters may be changed at runtime by the command
|
||||
See drivers/scsi/BusLogic.c, comment before function
|
||||
BusLogic_ParseDriverOptions().
|
||||
|
||||
dtc3181e= [HW,SCSI]
|
||||
See Documentation/scsi/g_NCR5380.txt.
|
||||
|
||||
eata= [HW,SCSI]
|
||||
|
||||
fdomain= [HW,SCSI]
|
||||
@ -47,9 +44,6 @@ parameters may be changed at runtime by the command
|
||||
|
||||
gvp11= [HW,SCSI]
|
||||
|
||||
in2000= [HW,SCSI]
|
||||
See header of drivers/scsi/in2000.c.
|
||||
|
||||
ips= [HW,SCSI] Adaptec / IBM ServeRAID controller
|
||||
See header of drivers/scsi/ips.c.
|
||||
|
||||
@ -83,9 +77,6 @@ parameters may be changed at runtime by the command
|
||||
Format: <buffer_size>,<write_threshold>
|
||||
See also Documentation/scsi/st.txt.
|
||||
|
||||
pas16= [HW,SCSI]
|
||||
See header of drivers/scsi/pas16.c.
|
||||
|
||||
scsi_debug_*= [SCSI]
|
||||
See drivers/scsi/scsi_debug.c.
|
||||
|
||||
@ -119,18 +110,9 @@ parameters may be changed at runtime by the command
|
||||
sym53c416= [HW,SCSI]
|
||||
See header of drivers/scsi/sym53c416.c.
|
||||
|
||||
t128= [HW,SCSI]
|
||||
See header of drivers/scsi/t128.c.
|
||||
|
||||
tmscsim= [HW,SCSI]
|
||||
See comment before function dc390_setup() in
|
||||
drivers/scsi/tmscsim.c.
|
||||
|
||||
u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter
|
||||
See header of drivers/scsi/u14-34f.c.
|
||||
|
||||
wd33c93= [HW,SCSI]
|
||||
See header of drivers/scsi/wd33c93.c.
|
||||
|
||||
wd7000= [HW,SCSI]
|
||||
See header of drivers/scsi/wd7000.c.
|
||||
|
80
Documentation/scsi/smartpqi.txt
Normal file
80
Documentation/scsi/smartpqi.txt
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
SMARTPQI - Microsemi Smart PQI Driver
|
||||
-----------------------------------------
|
||||
|
||||
This file describes the smartpqi SCSI driver for Microsemi
|
||||
(http://www.microsemi.com) PQI controllers. The smartpqi driver
|
||||
is the next generation SCSI driver for Microsemi Corp. The smartpqi
|
||||
driver is the first SCSI driver to implement the PQI queuing model.
|
||||
|
||||
The smartpqi driver will replace the aacraid driver for Adaptec Series 9
|
||||
controllers. Customers running an older kernel (Pre-4.9) using an Adaptec
|
||||
Series 9 controller will have to configure the smartpqi driver or their
|
||||
volumes will not be added to the OS.
|
||||
|
||||
For Microsemi smartpqi controller support, enable the smartpqi driver
|
||||
when configuring the kernel.
|
||||
|
||||
For more information on the PQI Queuing Interface, please see:
|
||||
http://www.t10.org/drafts.htm
|
||||
http://www.t10.org/members/w_pqi2.htm
|
||||
|
||||
Supported devices:
|
||||
------------------
|
||||
<Controller names to be added as they become publically available.>
|
||||
|
||||
smartpqi specific entries in /sys
|
||||
-----------------------------
|
||||
|
||||
smartpqi host attributes:
|
||||
-------------------------
|
||||
/sys/class/scsi_host/host*/rescan
|
||||
/sys/class/scsi_host/host*/version
|
||||
|
||||
The host rescan attribute is a write only attribute. Writing to this
|
||||
attribute will trigger the driver to scan for new, changed, or removed
|
||||
devices and notify the SCSI mid-layer of any changes detected.
|
||||
|
||||
The version attribute is read-only and will return the driver version
|
||||
and the controller firmware version.
|
||||
For example:
|
||||
driver: 0.9.13-370
|
||||
firmware: 0.01-522
|
||||
|
||||
smartpqi sas device attributes
|
||||
------------------------------
|
||||
HBA devices are added to the SAS transport layer. These attributes are
|
||||
automatically added by the SAS transport layer.
|
||||
|
||||
/sys/class/sas_device/end_device-X:X/sas_address
|
||||
/sys/class/sas_device/end_device-X:X/enclosure_identifier
|
||||
/sys/class/sas_device/end_device-X:X/scsi_target_id
|
||||
|
||||
smartpqi specific ioctls:
|
||||
-------------------------
|
||||
|
||||
For compatibility with applications written for the cciss protocol.
|
||||
|
||||
CCISS_DEREGDISK
|
||||
CCISS_REGNEWDISK
|
||||
CCISS_REGNEWD
|
||||
|
||||
The above three ioctls all do exactly the same thing, which is to cause the driver
|
||||
to rescan for new devices. This does exactly the same thing as writing to the
|
||||
smartpqi specific host "rescan" attribute.
|
||||
|
||||
CCISS_GETPCIINFO
|
||||
|
||||
Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID).
|
||||
|
||||
CCISS_GETDRIVVER
|
||||
|
||||
Returns driver version in three bytes encoded as:
|
||||
(DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | DRIVER_REVISION;
|
||||
|
||||
CCISS_PASSTHRU
|
||||
|
||||
Allows "BMIC" and "CISS" commands to be passed through to the Smart Storage Array.
|
||||
These are used extensively by the SSA Array Configuration Utility, SNMP storage
|
||||
agents, etc.
|
||||
|
38
MAINTAINERS
38
MAINTAINERS
@ -7973,6 +7973,18 @@ W: http://www.melexis.com
|
||||
S: Supported
|
||||
F: drivers/iio/temperature/mlx90614.c
|
||||
|
||||
MICROSEMI SMART ARRAY SMARTPQI DRIVER (smartpqi)
|
||||
M: Don Brace <don.brace@microsemi.com>
|
||||
L: esc.storagedev@microsemi.com
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/scsi/smartpqi/smartpqi*.[ch]
|
||||
F: drivers/scsi/smartpqi/Kconfig
|
||||
F: drivers/scsi/smartpqi/Makefile
|
||||
F: include/linux/cciss*.h
|
||||
F: include/uapi/linux/cciss*.h
|
||||
F: Documentation/scsi/smartpqi.txt
|
||||
|
||||
MN88472 MEDIA DRIVER
|
||||
M: Antti Palosaari <crope@iki.fi>
|
||||
L: linux-media@vger.kernel.org
|
||||
@ -8185,20 +8197,16 @@ M: Michael Schmitz <schmitzmic@gmail.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/scsi/g_NCR5380.txt
|
||||
F: Documentation/scsi/dtc3x80.txt
|
||||
F: drivers/scsi/NCR5380.*
|
||||
F: drivers/scsi/arm/cumana_1.c
|
||||
F: drivers/scsi/arm/oak.c
|
||||
F: drivers/scsi/atari_scsi.*
|
||||
F: drivers/scsi/dmx3191d.c
|
||||
F: drivers/scsi/dtc.*
|
||||
F: drivers/scsi/g_NCR5380.*
|
||||
F: drivers/scsi/g_NCR5380_mmio.c
|
||||
F: drivers/scsi/mac_scsi.*
|
||||
F: drivers/scsi/pas16.*
|
||||
F: drivers/scsi/sun3_scsi.*
|
||||
F: drivers/scsi/sun3_scsi_vme.c
|
||||
F: drivers/scsi/t128.*
|
||||
|
||||
NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
|
||||
M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
|
||||
@ -10740,12 +10748,12 @@ S: Maintained
|
||||
F: drivers/misc/phantom.c
|
||||
F: include/uapi/linux/phantom.h
|
||||
|
||||
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
|
||||
M: Jayamohan Kallickal <jayamohan.kallickal@avagotech.com>
|
||||
M: Ketan Mukadam <ketan.mukadam@avagotech.com>
|
||||
M: John Soni Jose <sony.john@avagotech.com>
|
||||
Emulex 10Gbps iSCSI - OneConnect DRIVER
|
||||
M: Subbu Seetharaman <subbu.seetharaman@broadcom.com>
|
||||
M: Ketan Mukadam <ketan.mukadam@broadcom.com>
|
||||
M: Jitendra Bhivare <jitendra.bhivare@broadcom.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
W: http://www.avagotech.com
|
||||
W: http://www.broadcom.com
|
||||
S: Supported
|
||||
F: drivers/scsi/be2iscsi/
|
||||
|
||||
@ -12143,12 +12151,6 @@ S: Maintained
|
||||
F: drivers/tc/
|
||||
F: include/linux/tc.h
|
||||
|
||||
U14-34F SCSI DRIVER
|
||||
M: Dario Ballabio <ballabio_dario@emc.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/scsi/u14-34f.c
|
||||
|
||||
UBI FILE SYSTEM (UBIFS)
|
||||
M: Richard Weinberger <richard@nod.at>
|
||||
M: Artem Bityutskiy <dedekind1@gmail.com>
|
||||
@ -12876,12 +12878,6 @@ F: drivers/watchdog/
|
||||
F: include/linux/watchdog.h
|
||||
F: include/uapi/linux/watchdog.h
|
||||
|
||||
WD7000 SCSI DRIVER
|
||||
M: Miroslav Zagorac <zaga@fly.cc.fer.hr>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/scsi/wd7000.c
|
||||
|
||||
WIIMOTE HID DRIVER
|
||||
M: David Herrmann <dh.herrmann@googlemail.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
|
@ -1865,8 +1865,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
||||
snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN,
|
||||
"mpt_poll_%d", ioc->id);
|
||||
ioc->reset_work_q =
|
||||
create_singlethread_workqueue(ioc->reset_work_q_name);
|
||||
ioc->reset_work_q = alloc_workqueue(ioc->reset_work_q_name,
|
||||
WQ_MEM_RECLAIM, 0);
|
||||
if (!ioc->reset_work_q) {
|
||||
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
|
||||
ioc->name);
|
||||
@ -1992,7 +1992,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
INIT_LIST_HEAD(&ioc->fw_event_list);
|
||||
spin_lock_init(&ioc->fw_event_lock);
|
||||
snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
|
||||
ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
|
||||
ioc->fw_event_q = alloc_workqueue(ioc->fw_event_q_name,
|
||||
WQ_MEM_RECLAIM, 0);
|
||||
if (!ioc->fw_event_q) {
|
||||
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
|
||||
ioc->name);
|
||||
|
@ -1324,9 +1324,12 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
|
||||
"mptfc_wq_%d", sh->host_no);
|
||||
ioc->fc_rescan_work_q =
|
||||
create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
|
||||
if (!ioc->fc_rescan_work_q)
|
||||
alloc_ordered_workqueue(ioc->fc_rescan_work_q_name,
|
||||
WQ_MEM_RECLAIM);
|
||||
if (!ioc->fc_rescan_work_q) {
|
||||
error = -ENOMEM;
|
||||
goto out_mptfc_probe;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-fetch FC port WWN and stuff...
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Debug traces for zfcp.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2013
|
||||
* Copyright IBM Corp. 2002, 2016
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@ -65,7 +65,7 @@ void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area,
|
||||
* @tag: tag indicating which kind of unsolicited status has been received
|
||||
* @req: request for which a response was received
|
||||
*/
|
||||
void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req)
|
||||
void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req)
|
||||
{
|
||||
struct zfcp_dbf *dbf = req->adapter->dbf;
|
||||
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)
|
||||
rec->u.res.req_issued = req->issued;
|
||||
rec->u.res.prot_status = q_pref->prot_status;
|
||||
rec->u.res.fsf_status = q_head->fsf_status;
|
||||
rec->u.res.port_handle = q_head->port_handle;
|
||||
rec->u.res.lun_handle = q_head->lun_handle;
|
||||
|
||||
memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual,
|
||||
FSF_PROT_STATUS_QUAL_SIZE);
|
||||
@ -97,7 +99,7 @@ void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req)
|
||||
rec->pl_len, "fsf_res", req->req_id);
|
||||
}
|
||||
|
||||
debug_event(dbf->hba, 1, rec, sizeof(*rec));
|
||||
debug_event(dbf->hba, level, rec, sizeof(*rec));
|
||||
spin_unlock_irqrestore(&dbf->hba_lock, flags);
|
||||
}
|
||||
|
||||
@ -241,7 +243,8 @@ static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
|
||||
if (sdev) {
|
||||
rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status);
|
||||
rec->lun = zfcp_scsi_dev_lun(sdev);
|
||||
}
|
||||
} else
|
||||
rec->lun = ZFCP_DBF_INVALID_LUN;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -320,13 +323,48 @@ void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
|
||||
spin_unlock_irqrestore(&dbf->rec_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery
|
||||
* @tag: identifier for event
|
||||
* @wka_port: well known address port
|
||||
* @req_id: request ID to correlate with potential HBA trace record
|
||||
*/
|
||||
void zfcp_dbf_rec_run_wka(char *tag, struct zfcp_fc_wka_port *wka_port,
|
||||
u64 req_id)
|
||||
{
|
||||
struct zfcp_dbf *dbf = wka_port->adapter->dbf;
|
||||
struct zfcp_dbf_rec *rec = &dbf->rec_buf;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dbf->rec_lock, flags);
|
||||
memset(rec, 0, sizeof(*rec));
|
||||
|
||||
rec->id = ZFCP_DBF_REC_RUN;
|
||||
memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
|
||||
rec->port_status = wka_port->status;
|
||||
rec->d_id = wka_port->d_id;
|
||||
rec->lun = ZFCP_DBF_INVALID_LUN;
|
||||
|
||||
rec->u.run.fsf_req_id = req_id;
|
||||
rec->u.run.rec_status = ~0;
|
||||
rec->u.run.rec_step = ~0;
|
||||
rec->u.run.rec_action = ~0;
|
||||
rec->u.run.rec_count = ~0;
|
||||
|
||||
debug_event(dbf->rec, 1, rec, sizeof(*rec));
|
||||
spin_unlock_irqrestore(&dbf->rec_lock, flags);
|
||||
}
|
||||
|
||||
static inline
|
||||
void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len,
|
||||
u64 req_id, u32 d_id)
|
||||
void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf,
|
||||
char *paytag, struct scatterlist *sg, u8 id, u16 len,
|
||||
u64 req_id, u32 d_id, u16 cap_len)
|
||||
{
|
||||
struct zfcp_dbf_san *rec = &dbf->san_buf;
|
||||
u16 rec_len;
|
||||
unsigned long flags;
|
||||
struct zfcp_dbf_pay *payload = &dbf->pay_buf;
|
||||
u16 pay_sum = 0;
|
||||
|
||||
spin_lock_irqsave(&dbf->san_lock, flags);
|
||||
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,
|
||||
rec->id = id;
|
||||
rec->fsf_req_id = req_id;
|
||||
rec->d_id = d_id;
|
||||
rec_len = min(len, (u16)ZFCP_DBF_SAN_MAX_PAYLOAD);
|
||||
memcpy(rec->payload, data, rec_len);
|
||||
memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
|
||||
rec->pl_len = len; /* full length even if we cap pay below */
|
||||
if (!sg)
|
||||
goto out;
|
||||
rec_len = min_t(unsigned int, sg->length, ZFCP_DBF_SAN_MAX_PAYLOAD);
|
||||
memcpy(rec->payload, sg_virt(sg), rec_len); /* part of 1st sg entry */
|
||||
if (len <= rec_len)
|
||||
goto out; /* skip pay record if full content in rec->payload */
|
||||
|
||||
/* if (len > rec_len):
|
||||
* dump data up to cap_len ignoring small duplicate in rec->payload
|
||||
*/
|
||||
spin_lock_irqsave(&dbf->pay_lock, flags);
|
||||
memset(payload, 0, sizeof(*payload));
|
||||
memcpy(payload->area, paytag, ZFCP_DBF_TAG_LEN);
|
||||
payload->fsf_req_id = req_id;
|
||||
payload->counter = 0;
|
||||
for (; sg && pay_sum < cap_len; sg = sg_next(sg)) {
|
||||
u16 pay_len, offset = 0;
|
||||
|
||||
while (offset < sg->length && pay_sum < cap_len) {
|
||||
pay_len = min((u16)ZFCP_DBF_PAY_MAX_REC,
|
||||
(u16)(sg->length - offset));
|
||||
/* cap_len <= pay_sum < cap_len+ZFCP_DBF_PAY_MAX_REC */
|
||||
memcpy(payload->data, sg_virt(sg) + offset, pay_len);
|
||||
debug_event(dbf->pay, 1, payload,
|
||||
zfcp_dbf_plen(pay_len));
|
||||
payload->counter++;
|
||||
offset += pay_len;
|
||||
pay_sum += pay_len;
|
||||
}
|
||||
}
|
||||
spin_unlock(&dbf->pay_lock);
|
||||
|
||||
out:
|
||||
debug_event(dbf->san, 1, rec, sizeof(*rec));
|
||||
spin_unlock_irqrestore(&dbf->san_lock, flags);
|
||||
}
|
||||
@ -354,9 +423,62 @@ void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id)
|
||||
struct zfcp_fsf_ct_els *ct_els = fsf->data;
|
||||
u16 length;
|
||||
|
||||
length = (u16)(ct_els->req->length + FC_CT_HDR_LEN);
|
||||
zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length,
|
||||
fsf->req_id, d_id);
|
||||
length = (u16)zfcp_qdio_real_bytes(ct_els->req);
|
||||
zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ,
|
||||
length, fsf->req_id, d_id, length);
|
||||
}
|
||||
|
||||
static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
|
||||
struct zfcp_fsf_req *fsf,
|
||||
u16 len)
|
||||
{
|
||||
struct zfcp_fsf_ct_els *ct_els = fsf->data;
|
||||
struct fc_ct_hdr *reqh = sg_virt(ct_els->req);
|
||||
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
|
||||
struct scatterlist *resp_entry = ct_els->resp;
|
||||
struct fc_gpn_ft_resp *acc;
|
||||
int max_entries, x, last = 0;
|
||||
|
||||
if (!(memcmp(tag, "fsscth2", 7) == 0
|
||||
&& ct_els->d_id == FC_FID_DIR_SERV
|
||||
&& reqh->ct_rev == FC_CT_REV
|
||||
&& reqh->ct_in_id[0] == 0
|
||||
&& reqh->ct_in_id[1] == 0
|
||||
&& reqh->ct_in_id[2] == 0
|
||||
&& reqh->ct_fs_type == FC_FST_DIR
|
||||
&& reqh->ct_fs_subtype == FC_NS_SUBTYPE
|
||||
&& reqh->ct_options == 0
|
||||
&& reqh->_ct_resvd1 == 0
|
||||
&& reqh->ct_cmd == FC_NS_GPN_FT
|
||||
/* reqh->ct_mr_size can vary so do not match but read below */
|
||||
&& reqh->_ct_resvd2 == 0
|
||||
&& reqh->ct_reason == 0
|
||||
&& reqh->ct_explan == 0
|
||||
&& reqh->ct_vendor == 0
|
||||
&& reqn->fn_resvd == 0
|
||||
&& reqn->fn_domain_id_scope == 0
|
||||
&& reqn->fn_area_id_scope == 0
|
||||
&& reqn->fn_fc4_type == FC_TYPE_FCP))
|
||||
return len; /* not GPN_FT response so do not cap */
|
||||
|
||||
acc = sg_virt(resp_entry);
|
||||
max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp))
|
||||
+ 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one
|
||||
* to account for header as 1st pseudo "entry" */;
|
||||
|
||||
/* the basic CT_IU preamble is the same size as one entry in the GPN_FT
|
||||
* response, allowing us to skip special handling for it - just skip it
|
||||
*/
|
||||
for (x = 1; x < max_entries && !last; x++) {
|
||||
if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1))
|
||||
acc++;
|
||||
else
|
||||
acc = sg_virt(++resp_entry);
|
||||
|
||||
last = acc->fp_flags & FC_NS_FID_LAST;
|
||||
}
|
||||
len = min(len, (u16)(x * sizeof(struct fc_gpn_ft_resp)));
|
||||
return len; /* cap after last entry */
|
||||
}
|
||||
|
||||
/**
|
||||
@ -370,9 +492,10 @@ void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf)
|
||||
struct zfcp_fsf_ct_els *ct_els = fsf->data;
|
||||
u16 length;
|
||||
|
||||
length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN);
|
||||
zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length,
|
||||
fsf->req_id, 0);
|
||||
length = (u16)zfcp_qdio_real_bytes(ct_els->resp);
|
||||
zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES,
|
||||
length, fsf->req_id, ct_els->d_id,
|
||||
zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -386,11 +509,13 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf)
|
||||
struct fsf_status_read_buffer *srb =
|
||||
(struct fsf_status_read_buffer *) fsf->data;
|
||||
u16 length;
|
||||
struct scatterlist sg;
|
||||
|
||||
length = (u16)(srb->length -
|
||||
offsetof(struct fsf_status_read_buffer, payload));
|
||||
zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length,
|
||||
fsf->req_id, ntoh24(srb->d_id));
|
||||
sg_init_one(&sg, srb->payload.data, length);
|
||||
zfcp_dbf_san(tag, dbf, "san_els", &sg, ZFCP_DBF_SAN_ELS, length,
|
||||
fsf->req_id, ntoh24(srb->d_id), length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,7 +524,8 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf)
|
||||
* @sc: pointer to struct scsi_cmnd
|
||||
* @fsf: pointer to struct zfcp_fsf_req
|
||||
*/
|
||||
void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf)
|
||||
void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
|
||||
struct zfcp_fsf_req *fsf)
|
||||
{
|
||||
struct zfcp_adapter *adapter =
|
||||
(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)
|
||||
}
|
||||
}
|
||||
|
||||
debug_event(dbf->scsi, 1, rec, sizeof(*rec));
|
||||
debug_event(dbf->scsi, level, rec, sizeof(*rec));
|
||||
spin_unlock_irqrestore(&dbf->scsi_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* zfcp device driver
|
||||
* debug feature declarations
|
||||
*
|
||||
* Copyright IBM Corp. 2008, 2010
|
||||
* Copyright IBM Corp. 2008, 2015
|
||||
*/
|
||||
|
||||
#ifndef ZFCP_DBF_H
|
||||
@ -17,6 +17,11 @@
|
||||
|
||||
#define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull
|
||||
|
||||
enum zfcp_dbf_pseudo_erp_act_type {
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD = 0xff,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL = 0xfe,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zfcp_dbf_rec_trigger - trace record for triggered recovery action
|
||||
* @ready: number of ready recovery actions
|
||||
@ -110,6 +115,7 @@ struct zfcp_dbf_san {
|
||||
u32 d_id;
|
||||
#define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32)
|
||||
char payload[ZFCP_DBF_SAN_MAX_PAYLOAD];
|
||||
u16 pl_len;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
@ -126,6 +132,8 @@ struct zfcp_dbf_hba_res {
|
||||
u8 prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
|
||||
u32 fsf_status;
|
||||
u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
|
||||
u32 port_handle;
|
||||
u32 lun_handle;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
@ -279,7 +287,7 @@ static inline
|
||||
void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
|
||||
{
|
||||
if (debug_level_enabled(req->adapter->dbf->hba, level))
|
||||
zfcp_dbf_hba_fsf_res(tag, req);
|
||||
zfcp_dbf_hba_fsf_res(tag, level, req);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -318,7 +326,7 @@ void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd,
|
||||
scmd->device->host->hostdata[0];
|
||||
|
||||
if (debug_level_enabled(adapter->dbf->scsi, level))
|
||||
zfcp_dbf_scsi(tag, scmd, req);
|
||||
zfcp_dbf_scsi(tag, level, scmd, req);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Error Recovery Procedures (ERP).
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2010
|
||||
* Copyright IBM Corp. 2002, 2015
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@ -1217,8 +1217,14 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
|
||||
break;
|
||||
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT:
|
||||
if (result == ZFCP_ERP_SUCCEEDED)
|
||||
zfcp_scsi_schedule_rport_register(port);
|
||||
/* This switch case might also happen after a forced reopen
|
||||
* was successfully done and thus overwritten with a new
|
||||
* non-forced reopen at `ersfs_2'. In this case, we must not
|
||||
* do the clean-up of the non-forced version.
|
||||
*/
|
||||
if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
|
||||
if (result == ZFCP_ERP_SUCCEEDED)
|
||||
zfcp_scsi_schedule_rport_register(port);
|
||||
/* fall through */
|
||||
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
|
||||
put_device(&port->dev);
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* External function declarations.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2010
|
||||
* Copyright IBM Corp. 2002, 2015
|
||||
*/
|
||||
|
||||
#ifndef ZFCP_EXT_H
|
||||
@ -35,8 +35,9 @@ extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *);
|
||||
extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
|
||||
struct zfcp_port *, struct scsi_device *, u8, u8);
|
||||
extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
|
||||
extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64);
|
||||
extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
|
||||
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 *);
|
||||
extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
|
||||
extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *,
|
||||
struct zfcp_fsf_req *);
|
||||
|
||||
/* zfcp_erp.c */
|
||||
extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Implementation of FSF commands.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2013
|
||||
* Copyright IBM Corp. 2002, 2015
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@ -508,7 +508,10 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
|
||||
break;
|
||||
case FSF_TOPO_FABRIC:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
|
||||
if (bottom->connection_features & FSF_FEATURE_NPIV_MODE)
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
|
||||
else
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
|
||||
break;
|
||||
case FSF_TOPO_AL:
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
|
||||
@ -613,7 +616,6 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
|
||||
|
||||
if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
|
||||
fc_host_permanent_port_name(shost) = bottom->wwpn;
|
||||
fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
|
||||
} else
|
||||
fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
|
||||
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,
|
||||
if (zfcp_adapter_multi_buffer_active(adapter)) {
|
||||
if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
|
||||
return -EIO;
|
||||
qtcb->bottom.support.req_buf_length =
|
||||
zfcp_qdio_real_bytes(sg_req);
|
||||
if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
|
||||
return -EIO;
|
||||
qtcb->bottom.support.resp_buf_length =
|
||||
zfcp_qdio_real_bytes(sg_resp);
|
||||
|
||||
zfcp_qdio_set_data_div(qdio, &req->qdio_req,
|
||||
zfcp_qdio_sbale_count(sg_req));
|
||||
@ -1073,6 +1079,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
|
||||
|
||||
req->handler = zfcp_fsf_send_ct_handler;
|
||||
req->qtcb->header.port_handle = wka_port->handle;
|
||||
ct->d_id = wka_port->d_id;
|
||||
req->data = ct;
|
||||
|
||||
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,
|
||||
|
||||
hton24(req->qtcb->bottom.support.d_id, d_id);
|
||||
req->handler = zfcp_fsf_send_els_handler;
|
||||
els->d_id = d_id;
|
||||
req->data = els;
|
||||
|
||||
zfcp_dbf_san_req("fssels1", req, d_id);
|
||||
@ -1575,7 +1583,7 @@ out:
|
||||
int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
|
||||
{
|
||||
struct zfcp_qdio *qdio = wka_port->adapter->qdio;
|
||||
struct zfcp_fsf_req *req;
|
||||
struct zfcp_fsf_req *req = NULL;
|
||||
int retval = -EIO;
|
||||
|
||||
spin_lock_irq(&qdio->req_q_lock);
|
||||
@ -1604,6 +1612,8 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
|
||||
zfcp_fsf_req_free(req);
|
||||
out:
|
||||
spin_unlock_irq(&qdio->req_q_lock);
|
||||
if (req && !IS_ERR(req))
|
||||
zfcp_dbf_rec_run_wka("fsowp_1", wka_port, req->req_id);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1628,7 +1638,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
|
||||
int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
|
||||
{
|
||||
struct zfcp_qdio *qdio = wka_port->adapter->qdio;
|
||||
struct zfcp_fsf_req *req;
|
||||
struct zfcp_fsf_req *req = NULL;
|
||||
int retval = -EIO;
|
||||
|
||||
spin_lock_irq(&qdio->req_q_lock);
|
||||
@ -1657,6 +1667,8 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
|
||||
zfcp_fsf_req_free(req);
|
||||
out:
|
||||
spin_unlock_irq(&qdio->req_q_lock);
|
||||
if (req && !IS_ERR(req))
|
||||
zfcp_dbf_rec_run_wka("fscwp_1", wka_port, req->req_id);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Interface to the FSF support functions.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2010
|
||||
* Copyright IBM Corp. 2002, 2015
|
||||
*/
|
||||
|
||||
#ifndef FSF_H
|
||||
@ -436,6 +436,7 @@ struct zfcp_blk_drv_data {
|
||||
* @handler_data: data passed to handler function
|
||||
* @port: Optional pointer to port for zfcp internal ELS (only test link ADISC)
|
||||
* @status: used to pass error status to calling function
|
||||
* @d_id: Destination ID of either open WKA port for CT or of D_ID for ELS
|
||||
*/
|
||||
struct zfcp_fsf_ct_els {
|
||||
struct scatterlist *req;
|
||||
@ -444,6 +445,7 @@ struct zfcp_fsf_ct_els {
|
||||
void *handler_data;
|
||||
struct zfcp_port *port;
|
||||
int status;
|
||||
u32 d_id;
|
||||
};
|
||||
|
||||
#endif /* FSF_H */
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Interface to Linux SCSI midlayer.
|
||||
*
|
||||
* Copyright IBM Corp. 2002, 2013
|
||||
* Copyright IBM Corp. 2002, 2015
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zfcp"
|
||||
@ -556,6 +556,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
|
||||
ids.port_id = port->d_id;
|
||||
ids.roles = FC_RPORT_ROLE_FCP_TARGET;
|
||||
|
||||
zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
|
||||
rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
|
||||
if (!rport) {
|
||||
dev_err(&port->adapter->ccw_device->dev,
|
||||
@ -577,6 +580,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port)
|
||||
struct fc_rport *rport = port->rport;
|
||||
|
||||
if (rport) {
|
||||
zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
|
||||
ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
|
||||
fc_remote_port_delete(rport);
|
||||
port->rport = NULL;
|
||||
}
|
||||
|
@ -396,18 +396,6 @@ config SCSI_3W_SAS
|
||||
Please read the comments at the top of
|
||||
<file:drivers/scsi/3w-sas.c>.
|
||||
|
||||
config SCSI_7000FASST
|
||||
tristate "7000FASST SCSI support"
|
||||
depends on ISA && SCSI && ISA_DMA_API
|
||||
select CHECK_SIGNATURE
|
||||
help
|
||||
This driver supports the Western Digital 7000 SCSI host adapter
|
||||
family. Some information is in the source:
|
||||
<file:drivers/scsi/wd7000.c>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wd7000.
|
||||
|
||||
config SCSI_ACARD
|
||||
tristate "ACARD SCSI support"
|
||||
depends on PCI && SCSI
|
||||
@ -512,18 +500,6 @@ config SCSI_ADVANSYS
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called advansys.
|
||||
|
||||
config SCSI_IN2000
|
||||
tristate "Always IN2000 SCSI support"
|
||||
depends on ISA && SCSI
|
||||
help
|
||||
This is support for an ISA bus SCSI host adapter. You'll find more
|
||||
information in <file:Documentation/scsi/in2000.txt>. If it doesn't work
|
||||
out of the box, you may have to change the jumpers for IRQ or
|
||||
address selection.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called in2000.
|
||||
|
||||
config SCSI_ARCMSR
|
||||
tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter"
|
||||
depends on PCI && SCSI
|
||||
@ -540,6 +516,7 @@ config SCSI_ARCMSR
|
||||
source "drivers/scsi/esas2r/Kconfig"
|
||||
source "drivers/scsi/megaraid/Kconfig.megaraid"
|
||||
source "drivers/scsi/mpt3sas/Kconfig"
|
||||
source "drivers/scsi/smartpqi/Kconfig"
|
||||
source "drivers/scsi/ufs/Kconfig"
|
||||
|
||||
config SCSI_HPTIOP
|
||||
@ -660,20 +637,6 @@ config SCSI_DMX3191D
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dmx3191d.
|
||||
|
||||
config SCSI_DTC3280
|
||||
tristate "DTC3180/3280 SCSI support"
|
||||
depends on ISA && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
select CHECK_SIGNATURE
|
||||
help
|
||||
This is support for DTC 3180/3280 SCSI Host Adapters. Please read
|
||||
the SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>, and the file
|
||||
<file:Documentation/scsi/dtc3x80.txt>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dtc.
|
||||
|
||||
config SCSI_EATA
|
||||
tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support"
|
||||
depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
|
||||
@ -1248,20 +1211,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT
|
||||
not allow targets to disconnect is not reasonable if there is more
|
||||
than 1 device on a SCSI bus. The normal answer therefore is N.
|
||||
|
||||
config SCSI_PAS16
|
||||
tristate "PAS16 SCSI support"
|
||||
depends on ISA && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
---help---
|
||||
This is support for a SCSI host adapter. It is explained in section
|
||||
3.10 of the SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. If it doesn't work out
|
||||
of the box, you may have to change some settings in
|
||||
<file:drivers/scsi/pas16.h>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pas16.
|
||||
|
||||
config SCSI_QLOGIC_FAS
|
||||
tristate "Qlogic FAS SCSI support"
|
||||
depends on ISA && SCSI
|
||||
@ -1382,89 +1331,6 @@ config SCSI_AM53C974
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called am53c974.
|
||||
|
||||
config SCSI_T128
|
||||
tristate "Trantor T128/T128F/T228 SCSI support"
|
||||
depends on ISA && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
select CHECK_SIGNATURE
|
||||
---help---
|
||||
This is support for a SCSI host adapter. It is explained in section
|
||||
3.11 of the SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. If it doesn't work out
|
||||
of the box, you may have to change some settings in
|
||||
<file:drivers/scsi/t128.h>. Note that Trantor was purchased by
|
||||
Adaptec, and some former Trantor products are being sold under the
|
||||
Adaptec name.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called t128.
|
||||
|
||||
config SCSI_U14_34F
|
||||
tristate "UltraStor 14F/34F support"
|
||||
depends on ISA && SCSI && ISA_DMA_API
|
||||
---help---
|
||||
This is support for the UltraStor 14F and 34F SCSI-2 host adapters.
|
||||
The source at <file:drivers/scsi/u14-34f.c> contains some
|
||||
information about this hardware. If the driver doesn't work out of
|
||||
the box, you may have to change some settings in
|
||||
<file: drivers/scsi/u14-34f.c>. Read the SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. Note that there is also
|
||||
another driver for the same hardware: "UltraStor SCSI support",
|
||||
below. You should say Y to both only if you want 24F support as
|
||||
well.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called u14-34f.
|
||||
|
||||
config SCSI_U14_34F_TAGGED_QUEUE
|
||||
bool "enable tagged command queueing"
|
||||
depends on SCSI_U14_34F
|
||||
help
|
||||
This is a feature of SCSI-2 which improves performance: the host
|
||||
adapter can send several SCSI commands to a device's queue even if
|
||||
previous commands haven't finished yet.
|
||||
This is equivalent to the "u14-34f=tc:y" boot option.
|
||||
|
||||
config SCSI_U14_34F_LINKED_COMMANDS
|
||||
bool "enable elevator sorting"
|
||||
depends on SCSI_U14_34F
|
||||
help
|
||||
This option enables elevator sorting for all probed SCSI disks and
|
||||
CD-ROMs. It definitely reduces the average seek distance when doing
|
||||
random seeks, but this does not necessarily result in a noticeable
|
||||
performance improvement: your mileage may vary...
|
||||
This is equivalent to the "u14-34f=lc:y" boot option.
|
||||
|
||||
config SCSI_U14_34F_MAX_TAGS
|
||||
int "maximum number of queued commands"
|
||||
depends on SCSI_U14_34F
|
||||
default "8"
|
||||
help
|
||||
This specifies how many SCSI commands can be maximally queued for
|
||||
each probed SCSI device. You should reduce the default value of 8
|
||||
only if you have disks with buggy or limited tagged command support.
|
||||
Minimum is 2 and maximum is 14. This value is also the window size
|
||||
used by the elevator sorting option above. The effective value used
|
||||
by the driver for each probed SCSI device is reported at boot time.
|
||||
This is equivalent to the "u14-34f=mq:8" boot option.
|
||||
|
||||
config SCSI_ULTRASTOR
|
||||
tristate "UltraStor SCSI support"
|
||||
depends on X86 && ISA && SCSI && ISA_DMA_API
|
||||
---help---
|
||||
This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
|
||||
adapter family. This driver is explained in section 3.12 of the
|
||||
SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. If it doesn't work out
|
||||
of the box, you may have to change some settings in
|
||||
<file:drivers/scsi/ultrastor.h>.
|
||||
|
||||
Note that there is also another driver for the same hardware:
|
||||
"UltraStor 14F/34F support", above.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ultrastor.
|
||||
|
||||
config SCSI_NSP32
|
||||
tristate "Workbit NinjaSCSI-32Bi/UDE support"
|
||||
depends on PCI && SCSI && !64BIT
|
||||
|
@ -61,9 +61,7 @@ obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o
|
||||
obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o
|
||||
obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o
|
||||
obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o
|
||||
obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o
|
||||
obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/
|
||||
obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o
|
||||
obj-$(CONFIG_SCSI_AHA152X) += aha152x.o
|
||||
obj-$(CONFIG_SCSI_AHA1542) += aha1542.o
|
||||
obj-$(CONFIG_SCSI_AHA1740) += aha1740.o
|
||||
@ -75,7 +73,6 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/
|
||||
obj-$(CONFIG_SCSI_ISCI) += isci/
|
||||
obj-$(CONFIG_SCSI_IPS) += ips.o
|
||||
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
|
||||
obj-$(CONFIG_SCSI_IN2000) += in2000.o
|
||||
obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
|
||||
obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o
|
||||
obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o
|
||||
@ -90,15 +87,12 @@ obj-$(CONFIG_SCSI_QLA_ISCSI) += libiscsi.o qla4xxx/
|
||||
obj-$(CONFIG_SCSI_LPFC) += lpfc/
|
||||
obj-$(CONFIG_SCSI_BFA_FC) += bfa/
|
||||
obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/
|
||||
obj-$(CONFIG_SCSI_PAS16) += pas16.o
|
||||
obj-$(CONFIG_SCSI_T128) += t128.o
|
||||
obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o
|
||||
obj-$(CONFIG_SCSI_HPSA) += hpsa.o
|
||||
obj-$(CONFIG_SCSI_DTC3280) += dtc.o
|
||||
obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/
|
||||
obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
|
||||
obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
|
||||
obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
|
||||
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
|
||||
obj-$(CONFIG_SCSI_EATA) += eata.o
|
||||
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
|
||||
obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
|
||||
|
@ -230,13 +230,6 @@ static int NCR5380_poll_politely2(struct Scsi_Host *instance,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
|
||||
int reg, int bit, int val, int wait)
|
||||
{
|
||||
return NCR5380_poll_politely2(instance, reg, bit, val,
|
||||
reg, bit, val, wait);
|
||||
}
|
||||
|
||||
#if NDEBUG
|
||||
static struct {
|
||||
unsigned char mask;
|
||||
@ -1854,11 +1847,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
|
||||
/* XXX - need to source or sink data here, as appropriate */
|
||||
}
|
||||
} else {
|
||||
/* Break up transfer into 3 ms chunks,
|
||||
* presuming 6 accesses per handshake.
|
||||
/* Transfer a small chunk so that the
|
||||
* irq mode lock is not held too long.
|
||||
*/
|
||||
transfersize = min((unsigned long)cmd->SCp.this_residual,
|
||||
hostdata->accesses_per_ms / 2);
|
||||
transfersize = min(cmd->SCp.this_residual,
|
||||
NCR5380_PIO_CHUNK_SIZE);
|
||||
len = transfersize;
|
||||
NCR5380_transfer_pio(instance, &phase, &len,
|
||||
(unsigned char **)&cmd->SCp.ptr);
|
||||
|
@ -250,6 +250,8 @@ struct NCR5380_cmd {
|
||||
|
||||
#define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd))
|
||||
|
||||
#define NCR5380_PIO_CHUNK_SIZE 256
|
||||
|
||||
static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr)
|
||||
{
|
||||
return ((struct scsi_cmnd *)ncmd_ptr) - 1;
|
||||
@ -292,8 +294,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance);
|
||||
static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
|
||||
static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
|
||||
static int NCR5380_poll_politely(struct Scsi_Host *, int, int, int, int);
|
||||
static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, int, int);
|
||||
|
||||
static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
|
||||
int reg, int bit, int val, int wait)
|
||||
{
|
||||
return NCR5380_poll_politely2(instance, reg, bit, val,
|
||||
reg, bit, val, wait);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* NCR5380_H */
|
||||
|
@ -613,7 +613,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
|
||||
* @dev: Adapter
|
||||
* @comm: communications method
|
||||
*/
|
||||
int aac_src_select_comm(struct aac_dev *dev, int comm)
|
||||
static int aac_src_select_comm(struct aac_dev *dev, int comm)
|
||||
{
|
||||
switch (comm) {
|
||||
case AAC_COMM_MESSAGE:
|
||||
|
@ -632,7 +632,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha)
|
||||
pci_name(asd_ha->pcidev));
|
||||
return err;
|
||||
}
|
||||
pci_write_config_dword(asd_ha->pcidev, PCIC_HSTPCIX_CNTRL,
|
||||
err = pci_write_config_dword(asd_ha->pcidev, PCIC_HSTPCIX_CNTRL,
|
||||
v | SC_TMR_DIS);
|
||||
if (err) {
|
||||
asd_printk("couldn't disable split completion timer of %s\n",
|
||||
|
@ -2388,15 +2388,23 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
|
||||
}
|
||||
case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
|
||||
unsigned char *ver_addr;
|
||||
int32_t user_len, cnt2end;
|
||||
uint32_t user_len;
|
||||
int32_t cnt2end;
|
||||
uint8_t *pQbuffer, *ptmpuserbuffer;
|
||||
|
||||
user_len = pcmdmessagefld->cmdmessage.Length;
|
||||
if (user_len > ARCMSR_API_DATA_BUFLEN) {
|
||||
retvalue = ARCMSR_MESSAGE_FAIL;
|
||||
goto message_out;
|
||||
}
|
||||
|
||||
ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC);
|
||||
if (!ver_addr) {
|
||||
retvalue = ARCMSR_MESSAGE_FAIL;
|
||||
goto message_out;
|
||||
}
|
||||
ptmpuserbuffer = ver_addr;
|
||||
user_len = pcmdmessagefld->cmdmessage.Length;
|
||||
|
||||
memcpy(ptmpuserbuffer,
|
||||
pcmdmessagefld->messagedatabuffer, user_len);
|
||||
spin_lock_irqsave(&acb->wqbuffer_lock, flags);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2015 Emulex
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -8,7 +8,7 @@
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@avagotech.com
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
@ -89,7 +89,7 @@ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
|
||||
u32 max_eqd; /* in usecs */
|
||||
u32 prev_eqd; /* in usecs */
|
||||
u32 et_eqd; /* configured val when aic is off */
|
||||
ulong jiffs;
|
||||
ulong jiffies;
|
||||
u64 eq_prev; /* Used to calculate eqe */
|
||||
};
|
||||
|
||||
@ -100,7 +100,7 @@ struct be_eq_obj {
|
||||
struct be_queue_info q;
|
||||
struct beiscsi_hba *phba;
|
||||
struct be_queue_info *cq;
|
||||
struct work_struct work_cqs; /* Work Item */
|
||||
struct work_struct mcc_work; /* Work Item */
|
||||
struct irq_poll iopoll;
|
||||
};
|
||||
|
||||
@ -111,8 +111,11 @@ struct be_mcc_obj {
|
||||
|
||||
struct beiscsi_mcc_tag_state {
|
||||
unsigned long tag_state;
|
||||
#define MCC_TAG_STATE_RUNNING 1
|
||||
#define MCC_TAG_STATE_TIMEOUT 2
|
||||
#define MCC_TAG_STATE_RUNNING 0
|
||||
#define MCC_TAG_STATE_TIMEOUT 1
|
||||
#define MCC_TAG_STATE_ASYNC 2
|
||||
#define MCC_TAG_STATE_IGNORE 3
|
||||
void (*cbfn)(struct beiscsi_hba *, unsigned int);
|
||||
struct be_dma_mem tag_mem_state;
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2015 Emulex
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -8,7 +8,7 @@
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@avagotech.com
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
@ -57,6 +57,7 @@ struct be_mcc_wrb {
|
||||
#define MCC_STATUS_ILLEGAL_REQUEST 0x2
|
||||
#define MCC_STATUS_ILLEGAL_FIELD 0x3
|
||||
#define MCC_STATUS_INSUFFICIENT_BUFFER 0x4
|
||||
#define MCC_STATUS_INVALID_LENGTH 0x74
|
||||
|
||||
#define CQE_STATUS_COMPL_MASK 0xFFFF
|
||||
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
|
||||
@ -97,11 +98,23 @@ struct be_mcc_compl {
|
||||
#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */
|
||||
#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */
|
||||
|
||||
/********** MPU semphore ******************/
|
||||
#define MPU_EP_SEMAPHORE_OFFSET 0xac
|
||||
#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
|
||||
#define EP_SEMAPHORE_POST_ERR_MASK 0x1
|
||||
#define EP_SEMAPHORE_POST_ERR_SHIFT 31
|
||||
/********** MPU semphore: used for SH & BE ******************/
|
||||
#define SLIPORT_SOFTRESET_OFFSET 0x5c /* CSR BAR offset */
|
||||
#define SLIPORT_SEMAPHORE_OFFSET_BEx 0xac /* CSR BAR offset */
|
||||
#define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 /* PCI-CFG offset */
|
||||
#define POST_STAGE_MASK 0x0000FFFF
|
||||
#define POST_ERROR_BIT 0x80000000
|
||||
#define POST_ERR_RECOVERY_CODE_MASK 0xF000
|
||||
|
||||
/* Soft Reset register masks */
|
||||
#define SLIPORT_SOFTRESET_SR_MASK 0x00000080 /* SR bit */
|
||||
|
||||
/* MPU semphore POST stage values */
|
||||
#define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */
|
||||
#define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */
|
||||
#define POST_STAGE_BE_RESET 0x3 /* Host wants to reset chip */
|
||||
#define POST_STAGE_ARMFW_RDY 0xC000 /* FW is done with POST */
|
||||
#define POST_STAGE_RECOVERABLE_ERR 0xE000 /* Recoverable err detected */
|
||||
|
||||
/********** MCC door bell ************/
|
||||
#define DB_MCCQ_OFFSET 0x140
|
||||
@ -109,9 +122,6 @@ struct be_mcc_compl {
|
||||
/* Number of entries posted */
|
||||
#define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */
|
||||
|
||||
/* MPU semphore POST stage values */
|
||||
#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */
|
||||
|
||||
/**
|
||||
* When the async bit of mcc_compl is set, the last 4 bytes of
|
||||
* mcc_compl is interpreted as follows:
|
||||
@ -217,6 +227,7 @@ struct be_mcc_mailbox {
|
||||
#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
|
||||
#define OPCODE_COMMON_FUNCTION_RESET 61
|
||||
#define OPCODE_COMMON_GET_PORT_NAME 77
|
||||
#define OPCODE_COMMON_SET_FEATURES 191
|
||||
|
||||
/**
|
||||
* LIST of opcodes that are common between Initiator and Target
|
||||
@ -345,8 +356,8 @@ struct be_cmd_req_logout_fw_sess {
|
||||
|
||||
struct be_cmd_resp_logout_fw_sess {
|
||||
struct be_cmd_resp_hdr hdr; /* dw[4] */
|
||||
#define BEISCSI_MGMT_SESSION_CLOSE 0x20
|
||||
uint32_t session_status;
|
||||
#define BE_SESS_STATUS_CLOSE 0x20
|
||||
} __packed;
|
||||
|
||||
struct mgmt_conn_login_options {
|
||||
@ -365,6 +376,14 @@ struct ip_addr_format {
|
||||
u16 size_of_structure;
|
||||
u8 reserved;
|
||||
u8 ip_type;
|
||||
#define BEISCSI_IP_TYPE_V4 0x1
|
||||
#define BEISCSI_IP_TYPE_STATIC_V4 0x3
|
||||
#define BEISCSI_IP_TYPE_DHCP_V4 0x5
|
||||
/* type v4 values < type v6 values */
|
||||
#define BEISCSI_IP_TYPE_V6 0x10
|
||||
#define BEISCSI_IP_TYPE_ROUTABLE_V6 0x30
|
||||
#define BEISCSI_IP_TYPE_LINK_LOCAL_V6 0x50
|
||||
#define BEISCSI_IP_TYPE_AUTO_V6 0x90
|
||||
u8 addr[16];
|
||||
u32 rsvd0;
|
||||
} __packed;
|
||||
@ -430,8 +449,13 @@ struct be_cmd_get_boot_target_req {
|
||||
|
||||
struct be_cmd_get_boot_target_resp {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
u32 boot_session_count;
|
||||
int boot_session_handle;
|
||||
u32 boot_session_count;
|
||||
u32 boot_session_handle;
|
||||
/**
|
||||
* FW returns 0xffffffff if it couldn't establish connection with
|
||||
* configured boot target.
|
||||
*/
|
||||
#define BE_BOOT_INVALID_SHANDLE 0xffffffff
|
||||
};
|
||||
|
||||
struct be_cmd_reopen_session_req {
|
||||
@ -699,16 +723,59 @@ struct be_cmd_get_nic_conf_resp {
|
||||
u8 mac_address[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
#define BEISCSI_ALIAS_LEN 32
|
||||
/******************** Get HBA NAME *******************/
|
||||
|
||||
struct be_cmd_hba_name {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 flags;
|
||||
u16 rsvd0;
|
||||
u8 initiator_name[ISCSI_NAME_LEN];
|
||||
u8 initiator_alias[BEISCSI_ALIAS_LEN];
|
||||
#define BE_INI_ALIAS_LEN 32
|
||||
u8 initiator_alias[BE_INI_ALIAS_LEN];
|
||||
} __packed;
|
||||
|
||||
/******************** COMMON SET Features *******************/
|
||||
#define BE_CMD_SET_FEATURE_UER 0x10
|
||||
#define BE_CMD_UER_SUPP_BIT 0x1
|
||||
struct be_uer_req {
|
||||
u32 uer;
|
||||
u32 rsvd;
|
||||
};
|
||||
|
||||
struct be_uer_resp {
|
||||
u32 uer;
|
||||
u16 ue2rp;
|
||||
u16 ue2sr;
|
||||
};
|
||||
|
||||
struct be_cmd_set_features {
|
||||
union {
|
||||
struct be_cmd_req_hdr req_hdr;
|
||||
struct be_cmd_resp_hdr resp_hdr;
|
||||
} h;
|
||||
u32 feature;
|
||||
u32 param_len;
|
||||
union {
|
||||
struct be_uer_req req;
|
||||
struct be_uer_resp resp;
|
||||
u32 rsvd[2];
|
||||
} param;
|
||||
} __packed;
|
||||
|
||||
int beiscsi_cmd_function_reset(struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load);
|
||||
|
||||
int beiscsi_check_fw_rdy(struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_init_sliport(struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num);
|
||||
|
||||
int beiscsi_detect_ue(struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_detect_tpe(struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *eq, int eq_delay);
|
||||
|
||||
@ -723,24 +790,21 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
|
||||
struct be_queue_info *mccq,
|
||||
struct be_queue_info *cq);
|
||||
|
||||
int be_poll_mcc(struct be_ctrl_info *ctrl);
|
||||
int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba);
|
||||
unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
|
||||
|
||||
void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag);
|
||||
|
||||
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *,
|
||||
int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *,
|
||||
int num);
|
||||
int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba,
|
||||
uint32_t tag, struct be_mcc_wrb **wrb,
|
||||
unsigned int tag,
|
||||
struct be_mcc_wrb **wrb,
|
||||
struct be_dma_mem *mbx_cmd_mem);
|
||||
/*ISCSI Functuions */
|
||||
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
|
||||
int be_cmd_fw_uninit(struct be_ctrl_info *ctrl);
|
||||
|
||||
int __beiscsi_mcc_compl_status(struct beiscsi_hba *phba,
|
||||
unsigned int tag,
|
||||
struct be_mcc_wrb **wrb,
|
||||
struct be_dma_mem *mbx_cmd_mem);
|
||||
struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
|
||||
int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag);
|
||||
void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag);
|
||||
struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba,
|
||||
unsigned int *ref_tag);
|
||||
@ -749,9 +813,6 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba,
|
||||
int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl,
|
||||
struct be_mcc_compl *compl);
|
||||
|
||||
|
||||
int be_mbox_notify(struct be_ctrl_info *ctrl);
|
||||
|
||||
int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
|
||||
struct be_queue_info *cq,
|
||||
struct be_queue_info *dq, int length,
|
||||
@ -767,8 +828,6 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
|
||||
struct be_dma_mem *q_mem, u32 page_offset,
|
||||
u32 num_pages);
|
||||
|
||||
int beiscsi_cmd_reset_function(struct beiscsi_hba *phba);
|
||||
|
||||
int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
|
||||
struct be_queue_info *wrbq,
|
||||
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,
|
||||
/* Configuration Functions */
|
||||
int be_cmd_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
|
||||
|
||||
int beiscsi_check_supported_fw(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_set_uer_feature(struct beiscsi_hba *phba);
|
||||
|
||||
struct be_default_pdu_context {
|
||||
u32 dw[4];
|
||||
} __packed;
|
||||
@ -999,7 +1067,16 @@ struct iscsi_cleanup_req {
|
||||
u16 chute;
|
||||
u8 hdr_ring_id;
|
||||
u8 data_ring_id;
|
||||
} __packed;
|
||||
|
||||
struct iscsi_cleanup_req_v1 {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 chute;
|
||||
u16 rsvd1;
|
||||
u16 hdr_ring_id;
|
||||
u16 rsvd2;
|
||||
u16 data_ring_id;
|
||||
u16 rsvd3;
|
||||
} __packed;
|
||||
|
||||
struct eq_delay {
|
||||
@ -1368,14 +1445,9 @@ struct be_cmd_get_port_name {
|
||||
* the cxn
|
||||
*/
|
||||
|
||||
int beiscsi_pci_soft_reset(struct beiscsi_hba *phba);
|
||||
int be_chk_reset_complete(struct beiscsi_hba *phba);
|
||||
|
||||
void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
|
||||
bool embedded, u8 sge_cnt);
|
||||
|
||||
void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
|
||||
u8 subsystem, u8 opcode, int cmd_len);
|
||||
|
||||
void beiscsi_fail_session(struct iscsi_cls_session *cls_session);
|
||||
#endif /* !BEISCSI_CMDS_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2015 Emulex
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -7,10 +7,10 @@
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com)
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@avagotech.com
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
@ -52,22 +52,20 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
|
||||
|
||||
|
||||
if (!ep) {
|
||||
printk(KERN_ERR
|
||||
"beiscsi_session_create: invalid ep\n");
|
||||
pr_err("beiscsi_session_create: invalid ep\n");
|
||||
return NULL;
|
||||
}
|
||||
beiscsi_ep = ep->dd_data;
|
||||
phba = beiscsi_ep->phba;
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : PCI_ERROR Recovery\n");
|
||||
return NULL;
|
||||
} else {
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In beiscsi_session_create\n");
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In beiscsi_session_create\n");
|
||||
if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Cannot handle %d cmds."
|
||||
@ -119,6 +117,16 @@ void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
|
||||
iscsi_session_teardown(cls_session);
|
||||
}
|
||||
|
||||
/**
|
||||
* beiscsi_session_fail(): Closing session with appropriate error
|
||||
* @cls_session: ptr to session
|
||||
**/
|
||||
void beiscsi_session_fail(struct iscsi_cls_session *cls_session)
|
||||
{
|
||||
iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* beiscsi_conn_create - create an instance of iscsi connection
|
||||
* @cls_session: ptr to iscsi_cls_session
|
||||
@ -237,7 +245,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
|
||||
return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
|
||||
}
|
||||
|
||||
static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba)
|
||||
static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
|
||||
{
|
||||
if (phba->ipv4_iface)
|
||||
return 0;
|
||||
@ -256,7 +264,7 @@ static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
|
||||
static int beiscsi_iface_create_ipv6(struct beiscsi_hba *phba)
|
||||
{
|
||||
if (phba->ipv6_iface)
|
||||
return 0;
|
||||
@ -275,79 +283,31 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void beiscsi_create_def_ifaces(struct beiscsi_hba *phba)
|
||||
void beiscsi_iface_create_default(struct beiscsi_hba *phba)
|
||||
{
|
||||
struct be_cmd_get_if_info_resp *if_info;
|
||||
|
||||
if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) {
|
||||
beiscsi_create_ipv4_iface(phba);
|
||||
if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) {
|
||||
beiscsi_iface_create_ipv4(phba);
|
||||
kfree(if_info);
|
||||
}
|
||||
|
||||
if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) {
|
||||
beiscsi_create_ipv6_iface(phba);
|
||||
if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) {
|
||||
beiscsi_iface_create_ipv6(phba);
|
||||
kfree(if_info);
|
||||
}
|
||||
}
|
||||
|
||||
void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
|
||||
void beiscsi_iface_destroy_default(struct beiscsi_hba *phba)
|
||||
{
|
||||
if (phba->ipv6_iface)
|
||||
if (phba->ipv6_iface) {
|
||||
iscsi_destroy_iface(phba->ipv6_iface);
|
||||
if (phba->ipv4_iface)
|
||||
phba->ipv6_iface = NULL;
|
||||
}
|
||||
if (phba->ipv4_iface) {
|
||||
iscsi_destroy_iface(phba->ipv4_iface);
|
||||
}
|
||||
|
||||
static int
|
||||
beiscsi_set_static_ip(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *iface_param,
|
||||
void *data, uint32_t dt_len)
|
||||
{
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
struct iscsi_iface_param_info *iface_ip = NULL;
|
||||
struct iscsi_iface_param_info *iface_subnet = NULL;
|
||||
struct nlattr *nla;
|
||||
int ret;
|
||||
|
||||
|
||||
switch (iface_param->param) {
|
||||
case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
|
||||
nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
|
||||
if (nla)
|
||||
iface_ip = nla_data(nla);
|
||||
|
||||
nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
|
||||
if (nla)
|
||||
iface_subnet = nla_data(nla);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV4_ADDR:
|
||||
iface_ip = iface_param;
|
||||
nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
|
||||
if (nla)
|
||||
iface_subnet = nla_data(nla);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV4_SUBNET:
|
||||
iface_subnet = iface_param;
|
||||
nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
|
||||
if (nla)
|
||||
iface_ip = nla_data(nla);
|
||||
break;
|
||||
default:
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Unsupported param %d\n",
|
||||
iface_param->param);
|
||||
phba->ipv4_iface = NULL;
|
||||
}
|
||||
|
||||
if (!iface_ip || !iface_subnet) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : IP and Subnet Mask required\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mgmt_set_ip(phba, iface_ip, iface_subnet,
|
||||
ISCSI_BOOTPROTO_STATIC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -363,137 +323,141 @@ beiscsi_set_static_ip(struct Scsi_Host *shost,
|
||||
* Failure: Non-Zero Value
|
||||
**/
|
||||
static int
|
||||
beiscsi_set_vlan_tag(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *iface_param)
|
||||
beiscsi_iface_config_vlan(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *iface_param)
|
||||
{
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
int ret;
|
||||
|
||||
/* Get the Interface Handle */
|
||||
ret = mgmt_get_all_if_id(phba);
|
||||
if (ret) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Getting Interface Handle Failed\n");
|
||||
return ret;
|
||||
}
|
||||
int ret = -EPERM;
|
||||
|
||||
switch (iface_param->param) {
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
ret = 0;
|
||||
if (iface_param->value[0] != ISCSI_VLAN_ENABLE)
|
||||
ret = mgmt_set_vlan(phba, BEISCSI_VLAN_DISABLE);
|
||||
ret = beiscsi_if_set_vlan(phba, BEISCSI_VLAN_DISABLE);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_TAG:
|
||||
ret = mgmt_set_vlan(phba,
|
||||
*((uint16_t *)iface_param->value));
|
||||
ret = beiscsi_if_set_vlan(phba,
|
||||
*((uint16_t *)iface_param->value));
|
||||
break;
|
||||
default:
|
||||
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Unknown Param Type : %d\n",
|
||||
iface_param->param);
|
||||
return -ENOSYS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
beiscsi_set_ipv4(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *iface_param,
|
||||
void *data, uint32_t dt_len)
|
||||
beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *info,
|
||||
void *data, uint32_t dt_len)
|
||||
{
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
int ret = 0;
|
||||
u8 *ip = NULL, *subnet = NULL, *gw;
|
||||
struct nlattr *nla;
|
||||
int ret = -EPERM;
|
||||
|
||||
/* Check the param */
|
||||
switch (iface_param->param) {
|
||||
switch (info->param) {
|
||||
case ISCSI_NET_PARAM_IFACE_ENABLE:
|
||||
if (info->value[0] == ISCSI_IFACE_ENABLE)
|
||||
ret = beiscsi_iface_create_ipv4(phba);
|
||||
else {
|
||||
iscsi_destroy_iface(phba->ipv4_iface);
|
||||
phba->ipv4_iface = NULL;
|
||||
}
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV4_GW:
|
||||
ret = mgmt_set_gateway(phba, iface_param);
|
||||
gw = info->value;
|
||||
ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
|
||||
if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
|
||||
ret = mgmt_set_ip(phba, iface_param,
|
||||
NULL, ISCSI_BOOTPROTO_DHCP);
|
||||
else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
|
||||
ret = beiscsi_set_static_ip(shost, iface_param,
|
||||
data, dt_len);
|
||||
if (info->value[0] == ISCSI_BOOTPROTO_DHCP)
|
||||
ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4);
|
||||
else if (info->value[0] == ISCSI_BOOTPROTO_STATIC)
|
||||
/* release DHCP IP address */
|
||||
ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
|
||||
NULL, NULL);
|
||||
else
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Invalid BOOTPROTO: %d\n",
|
||||
iface_param->value[0]);
|
||||
info->value[0]);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IFACE_ENABLE:
|
||||
if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
|
||||
ret = beiscsi_create_ipv4_iface(phba);
|
||||
else
|
||||
iscsi_destroy_iface(phba->ipv4_iface);
|
||||
case ISCSI_NET_PARAM_IPV4_ADDR:
|
||||
ip = info->value;
|
||||
nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
|
||||
if (nla) {
|
||||
info = nla_data(nla);
|
||||
subnet = info->value;
|
||||
}
|
||||
ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
|
||||
ip, subnet);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV4_SUBNET:
|
||||
case ISCSI_NET_PARAM_IPV4_ADDR:
|
||||
ret = beiscsi_set_static_ip(shost, iface_param,
|
||||
data, dt_len);
|
||||
/*
|
||||
* OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP
|
||||
* and subnet both. Find IP to be applied for this subnet.
|
||||
*/
|
||||
subnet = info->value;
|
||||
nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
|
||||
if (nla) {
|
||||
info = nla_data(nla);
|
||||
ip = info->value;
|
||||
}
|
||||
ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
|
||||
ip, subnet);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
case ISCSI_NET_PARAM_VLAN_TAG:
|
||||
ret = beiscsi_set_vlan_tag(shost, iface_param);
|
||||
break;
|
||||
default:
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Param %d not supported\n",
|
||||
iface_param->param);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
beiscsi_set_ipv6(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *iface_param,
|
||||
void *data, uint32_t dt_len)
|
||||
beiscsi_iface_config_ipv6(struct Scsi_Host *shost,
|
||||
struct iscsi_iface_param_info *iface_param,
|
||||
void *data, uint32_t dt_len)
|
||||
{
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
int ret = 0;
|
||||
int ret = -EPERM;
|
||||
|
||||
switch (iface_param->param) {
|
||||
case ISCSI_NET_PARAM_IFACE_ENABLE:
|
||||
if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
|
||||
ret = beiscsi_create_ipv6_iface(phba);
|
||||
ret = beiscsi_iface_create_ipv6(phba);
|
||||
else {
|
||||
iscsi_destroy_iface(phba->ipv6_iface);
|
||||
ret = 0;
|
||||
phba->ipv6_iface = NULL;
|
||||
}
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV6_ADDR:
|
||||
ret = mgmt_set_ip(phba, iface_param, NULL,
|
||||
ISCSI_BOOTPROTO_STATIC);
|
||||
ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6,
|
||||
iface_param->value, NULL);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
case ISCSI_NET_PARAM_VLAN_TAG:
|
||||
ret = beiscsi_set_vlan_tag(shost, iface_param);
|
||||
break;
|
||||
default:
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Param %d not supported\n",
|
||||
iface_param->param);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int be2iscsi_iface_set_param(struct Scsi_Host *shost,
|
||||
void *data, uint32_t dt_len)
|
||||
int beiscsi_iface_set_param(struct Scsi_Host *shost,
|
||||
void *data, uint32_t dt_len)
|
||||
{
|
||||
struct iscsi_iface_param_info *iface_param = NULL;
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
struct nlattr *attrib;
|
||||
uint32_t rm_len = dt_len;
|
||||
int ret = 0 ;
|
||||
int ret;
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In PCI_ERROR Recovery\n");
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* update interface_handle */
|
||||
ret = beiscsi_if_get_handle(phba);
|
||||
if (ret) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Getting Interface Handle Failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
nla_for_each_attr(attrib, data, dt_len, rm_len) {
|
||||
iface_param = nla_data(attrib);
|
||||
|
||||
@ -512,40 +476,58 @@ int be2iscsi_iface_set_param(struct Scsi_Host *shost,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (iface_param->iface_type) {
|
||||
case ISCSI_IFACE_TYPE_IPV4:
|
||||
ret = beiscsi_set_ipv4(shost, iface_param,
|
||||
data, dt_len);
|
||||
break;
|
||||
case ISCSI_IFACE_TYPE_IPV6:
|
||||
ret = beiscsi_set_ipv6(shost, iface_param,
|
||||
data, dt_len);
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : %s.0 set param %d",
|
||||
(iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ?
|
||||
"ipv4" : "ipv6", iface_param->param);
|
||||
|
||||
ret = -EPERM;
|
||||
switch (iface_param->param) {
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
case ISCSI_NET_PARAM_VLAN_TAG:
|
||||
ret = beiscsi_iface_config_vlan(shost, iface_param);
|
||||
break;
|
||||
default:
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : Invalid iface type :%d passed\n",
|
||||
iface_param->iface_type);
|
||||
break;
|
||||
switch (iface_param->iface_type) {
|
||||
case ISCSI_IFACE_TYPE_IPV4:
|
||||
ret = beiscsi_iface_config_ipv4(shost,
|
||||
iface_param,
|
||||
data, dt_len);
|
||||
break;
|
||||
case ISCSI_IFACE_TYPE_IPV6:
|
||||
ret = beiscsi_iface_config_ipv6(shost,
|
||||
iface_param,
|
||||
data, dt_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == -EPERM) {
|
||||
__beiscsi_log(phba, KERN_ERR,
|
||||
"BS_%d : %s.0 set param %d not permitted",
|
||||
(iface_param->iface_type ==
|
||||
ISCSI_IFACE_TYPE_IPV4) ? "ipv4" : "ipv6",
|
||||
iface_param->param);
|
||||
ret = 0;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
|
||||
struct iscsi_iface *iface, int param,
|
||||
char *buf)
|
||||
static int __beiscsi_iface_get_param(struct beiscsi_hba *phba,
|
||||
struct iscsi_iface *iface,
|
||||
int param, char *buf)
|
||||
{
|
||||
struct be_cmd_get_if_info_resp *if_info;
|
||||
int len, ip_type = BE2_IPV4;
|
||||
int len, ip_type = BEISCSI_IP_TYPE_V4;
|
||||
|
||||
if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
|
||||
ip_type = BE2_IPV6;
|
||||
ip_type = BEISCSI_IP_TYPE_V6;
|
||||
|
||||
len = mgmt_get_if_info(phba, ip_type, &if_info);
|
||||
len = beiscsi_if_get_info(phba, ip_type, &if_info);
|
||||
if (len)
|
||||
return len;
|
||||
|
||||
@ -567,24 +549,24 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
len = sprintf(buf, "%s\n",
|
||||
(if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
? "Disabled\n" : "Enabled\n");
|
||||
(if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ?
|
||||
"disable" : "enable");
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_ID:
|
||||
if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
len = -EINVAL;
|
||||
else
|
||||
len = sprintf(buf, "%d\n",
|
||||
(if_info->vlan_priority &
|
||||
ISCSI_MAX_VLAN_ID));
|
||||
(if_info->vlan_priority &
|
||||
ISCSI_MAX_VLAN_ID));
|
||||
break;
|
||||
case ISCSI_NET_PARAM_VLAN_PRIORITY:
|
||||
if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
|
||||
len = -EINVAL;
|
||||
else
|
||||
len = sprintf(buf, "%d\n",
|
||||
((if_info->vlan_priority >> 13) &
|
||||
ISCSI_MAX_VLAN_PRIORITY));
|
||||
((if_info->vlan_priority >> 13) &
|
||||
ISCSI_MAX_VLAN_PRIORITY));
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
@ -594,18 +576,20 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
|
||||
return len;
|
||||
}
|
||||
|
||||
int be2iscsi_iface_get_param(struct iscsi_iface *iface,
|
||||
enum iscsi_param_type param_type,
|
||||
int param, char *buf)
|
||||
int beiscsi_iface_get_param(struct iscsi_iface *iface,
|
||||
enum iscsi_param_type param_type,
|
||||
int param, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
struct be_cmd_get_def_gateway_resp gateway;
|
||||
int len = -ENOSYS;
|
||||
int len = -EPERM;
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In PCI_ERROR Recovery\n");
|
||||
if (param_type != ISCSI_NET_PARAM)
|
||||
return 0;
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -617,19 +601,22 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface,
|
||||
case ISCSI_NET_PARAM_VLAN_ENABLED:
|
||||
case ISCSI_NET_PARAM_VLAN_ID:
|
||||
case ISCSI_NET_PARAM_VLAN_PRIORITY:
|
||||
len = be2iscsi_get_if_param(phba, iface, param, buf);
|
||||
len = __beiscsi_iface_get_param(phba, iface, param, buf);
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IFACE_ENABLE:
|
||||
len = sprintf(buf, "enabled\n");
|
||||
if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
|
||||
len = sprintf(buf, "%s\n",
|
||||
phba->ipv4_iface ? "enable" : "disable");
|
||||
else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
|
||||
len = sprintf(buf, "%s\n",
|
||||
phba->ipv6_iface ? "enable" : "disable");
|
||||
break;
|
||||
case ISCSI_NET_PARAM_IPV4_GW:
|
||||
memset(&gateway, 0, sizeof(gateway));
|
||||
len = mgmt_get_gateway(phba, BE2_IPV4, &gateway);
|
||||
len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway);
|
||||
if (!len)
|
||||
len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
|
||||
break;
|
||||
default:
|
||||
len = -ENOSYS;
|
||||
}
|
||||
|
||||
return len;
|
||||
@ -647,7 +634,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
|
||||
enum iscsi_param param, char *buf)
|
||||
{
|
||||
struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
|
||||
int len = 0;
|
||||
int len;
|
||||
|
||||
beiscsi_log(beiscsi_ep->phba, KERN_INFO,
|
||||
BEISCSI_LOG_CONFIG,
|
||||
@ -659,13 +646,13 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
|
||||
len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
|
||||
break;
|
||||
case ISCSI_PARAM_CONN_ADDRESS:
|
||||
if (beiscsi_ep->ip_type == BE2_IPV4)
|
||||
if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4)
|
||||
len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
|
||||
else
|
||||
len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
len = -EPERM;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@ -758,7 +745,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost)
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
struct iscsi_cls_host *ihost = shost->shost_data;
|
||||
|
||||
ihost->port_state = (phba->state & BE_ADAPTER_LINK_UP) ?
|
||||
ihost->port_state = test_bit(BEISCSI_HBA_LINK_UP, &phba->state) ?
|
||||
ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
|
||||
}
|
||||
|
||||
@ -810,16 +797,13 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
|
||||
struct beiscsi_hba *phba = iscsi_host_priv(shost);
|
||||
int status = 0;
|
||||
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In PCI_ERROR Recovery\n");
|
||||
return -EBUSY;
|
||||
} else {
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In beiscsi_get_host_param,"
|
||||
" param = %d\n", param);
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
return -EBUSY;
|
||||
}
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In beiscsi_get_host_param, param = %d\n", param);
|
||||
|
||||
switch (param) {
|
||||
case ISCSI_HOST_PARAM_HWADDRESS:
|
||||
@ -961,15 +945,13 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
|
||||
|
||||
phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In PCI_ERROR Recovery\n");
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
return -EBUSY;
|
||||
} else {
|
||||
beiscsi_log(beiscsi_conn->phba, KERN_INFO,
|
||||
BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In beiscsi_conn_start\n");
|
||||
}
|
||||
beiscsi_log(beiscsi_conn->phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In beiscsi_conn_start\n");
|
||||
|
||||
memset(¶ms, 0, sizeof(struct beiscsi_offload_params));
|
||||
beiscsi_ep = beiscsi_conn->ep;
|
||||
@ -1186,28 +1168,20 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
|
||||
struct iscsi_endpoint *ep;
|
||||
int ret;
|
||||
|
||||
if (shost)
|
||||
phba = iscsi_host_priv(shost);
|
||||
else {
|
||||
if (!shost) {
|
||||
ret = -ENXIO;
|
||||
printk(KERN_ERR
|
||||
"beiscsi_ep_connect shost is NULL\n");
|
||||
pr_err("beiscsi_ep_connect shost is NULL\n");
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (beiscsi_error(phba)) {
|
||||
phba = iscsi_host_priv(shost);
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
ret = -EIO;
|
||||
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : The FW state Not Stable!!!\n");
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
ret = -EBUSY;
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : In PCI_ERROR Recovery\n");
|
||||
return ERR_PTR(ret);
|
||||
} else if (phba->state & BE_ADAPTER_LINK_DOWN) {
|
||||
if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) {
|
||||
ret = -EBUSY;
|
||||
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : The Adapter Port state is Down!!!\n");
|
||||
@ -1361,9 +1335,9 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
|
||||
tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
|
||||
}
|
||||
|
||||
if (phba->state & BE_ADAPTER_PCI_ERR) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : PCI_ERROR Recovery\n");
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
goto free_ep;
|
||||
}
|
||||
|
||||
@ -1386,7 +1360,7 @@ free_ep:
|
||||
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
|
||||
}
|
||||
|
||||
umode_t be2iscsi_attr_is_visible(int param_type, int param)
|
||||
umode_t beiscsi_attr_is_visible(int param_type, int param)
|
||||
{
|
||||
switch (param_type) {
|
||||
case ISCSI_NET_PARAM:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2015 Avago Technologies
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -7,10 +7,10 @@
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com)
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@avagotech.com
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Avago Technologies
|
||||
* 3333 Susan Street
|
||||
@ -23,25 +23,18 @@
|
||||
#include "be_main.h"
|
||||
#include "be_mgmt.h"
|
||||
|
||||
#define BE2_IPV4 0x1
|
||||
#define BE2_IPV6 0x10
|
||||
#define BE2_DHCP_V4 0x05
|
||||
void beiscsi_iface_create_default(struct beiscsi_hba *phba);
|
||||
|
||||
#define NON_BLOCKING 0x0
|
||||
#define BLOCKING 0x1
|
||||
void beiscsi_iface_destroy_default(struct beiscsi_hba *phba);
|
||||
|
||||
void beiscsi_create_def_ifaces(struct beiscsi_hba *phba);
|
||||
|
||||
void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba);
|
||||
|
||||
int be2iscsi_iface_get_param(struct iscsi_iface *iface,
|
||||
int beiscsi_iface_get_param(struct iscsi_iface *iface,
|
||||
enum iscsi_param_type param_type,
|
||||
int param, char *buf);
|
||||
|
||||
int be2iscsi_iface_set_param(struct Scsi_Host *shost,
|
||||
int beiscsi_iface_set_param(struct Scsi_Host *shost,
|
||||
void *data, uint32_t count);
|
||||
|
||||
umode_t be2iscsi_attr_is_visible(int param_type, int param);
|
||||
umode_t beiscsi_attr_is_visible(int param_type, int param);
|
||||
|
||||
void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
|
||||
struct beiscsi_offload_params *params);
|
||||
@ -57,6 +50,8 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
|
||||
|
||||
void beiscsi_session_destroy(struct iscsi_cls_session *cls_session);
|
||||
|
||||
void beiscsi_session_fail(struct iscsi_cls_session *cls_session);
|
||||
|
||||
struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session
|
||||
*cls_session, uint32_t cid);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2015 Emulex
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -7,10 +7,10 @@
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com)
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@avagotech.com
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
@ -36,7 +36,7 @@
|
||||
#include <scsi/scsi_transport_iscsi.h>
|
||||
|
||||
#define DRV_NAME "be2iscsi"
|
||||
#define BUILD_STR "11.0.0.0"
|
||||
#define BUILD_STR "11.2.0.0"
|
||||
#define BE_NAME "Emulex OneConnect" \
|
||||
"Open-iSCSI Driver version" BUILD_STR
|
||||
#define DRV_DESC BE_NAME " " "Driver"
|
||||
@ -82,36 +82,12 @@
|
||||
#define BEISCSI_MAX_FRAGS_INIT 192
|
||||
#define BE_NUM_MSIX_ENTRIES 1
|
||||
|
||||
#define MPU_EP_CONTROL 0
|
||||
#define MPU_EP_SEMAPHORE 0xac
|
||||
#define BE2_SOFT_RESET 0x5c
|
||||
#define BE2_PCI_ONLINE0 0xb0
|
||||
#define BE2_PCI_ONLINE1 0xb4
|
||||
#define BE2_SET_RESET 0x80
|
||||
#define BE2_MPU_IRAM_ONLINE 0x00000080
|
||||
|
||||
#define BE_SENSE_INFO_SIZE 258
|
||||
#define BE_ISCSI_PDU_HEADER_SIZE 64
|
||||
#define BE_MIN_MEM_SIZE 16384
|
||||
#define MAX_CMD_SZ 65536
|
||||
#define IIOC_SCSI_DATA 0x05 /* Write Operation */
|
||||
|
||||
#define INVALID_SESS_HANDLE 0xFFFFFFFF
|
||||
|
||||
/**
|
||||
* Adapter States
|
||||
**/
|
||||
#define BE_ADAPTER_LINK_UP 0x001
|
||||
#define BE_ADAPTER_LINK_DOWN 0x002
|
||||
#define BE_ADAPTER_PCI_ERR 0x004
|
||||
#define BE_ADAPTER_CHECK_BOOT 0x008
|
||||
|
||||
|
||||
#define BEISCSI_CLEAN_UNLOAD 0x01
|
||||
#define BEISCSI_EEH_UNLOAD 0x02
|
||||
|
||||
#define BE_GET_BOOT_RETRIES 45
|
||||
#define BE_GET_BOOT_TO 20
|
||||
/**
|
||||
* hardware needs the async PDU buffers to be posted in multiples of 8
|
||||
* So have atleast 8 of them by default
|
||||
@ -378,7 +354,6 @@ struct beiscsi_hba {
|
||||
struct sgl_handle **eh_sgl_hndl_base;
|
||||
spinlock_t io_sgl_lock;
|
||||
spinlock_t mgmt_sgl_lock;
|
||||
spinlock_t isr_lock;
|
||||
spinlock_t async_pdu_lock;
|
||||
unsigned int age;
|
||||
struct list_head hba_queue;
|
||||
@ -390,7 +365,6 @@ struct beiscsi_hba {
|
||||
struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT];
|
||||
struct iscsi_endpoint **ep_array;
|
||||
struct beiscsi_conn **conn_table;
|
||||
struct iscsi_boot_kset *boot_kset;
|
||||
struct Scsi_Host *shost;
|
||||
struct iscsi_iface *ipv4_iface;
|
||||
struct iscsi_iface *ipv6_iface;
|
||||
@ -418,12 +392,33 @@ struct beiscsi_hba {
|
||||
unsigned long ulp_supported;
|
||||
} fw_config;
|
||||
|
||||
unsigned int state;
|
||||
unsigned long state;
|
||||
#define BEISCSI_HBA_ONLINE 0
|
||||
#define BEISCSI_HBA_LINK_UP 1
|
||||
#define BEISCSI_HBA_BOOT_FOUND 2
|
||||
#define BEISCSI_HBA_BOOT_WORK 3
|
||||
#define BEISCSI_HBA_UER_SUPP 4
|
||||
#define BEISCSI_HBA_PCI_ERR 5
|
||||
#define BEISCSI_HBA_FW_TIMEOUT 6
|
||||
#define BEISCSI_HBA_IN_UE 7
|
||||
#define BEISCSI_HBA_IN_TPE 8
|
||||
|
||||
/* error bits */
|
||||
#define BEISCSI_HBA_IN_ERR ((1 << BEISCSI_HBA_PCI_ERR) | \
|
||||
(1 << BEISCSI_HBA_FW_TIMEOUT) | \
|
||||
(1 << BEISCSI_HBA_IN_UE) | \
|
||||
(1 << BEISCSI_HBA_IN_TPE))
|
||||
|
||||
u8 optic_state;
|
||||
int get_boot;
|
||||
bool fw_timeout;
|
||||
bool ue_detected;
|
||||
struct delayed_work beiscsi_hw_check_task;
|
||||
struct delayed_work eqd_update;
|
||||
/* update EQ delay timer every 1000ms */
|
||||
#define BEISCSI_EQD_UPDATE_INTERVAL 1000
|
||||
struct timer_list hw_check;
|
||||
/* check for UE every 1000ms */
|
||||
#define BEISCSI_UE_DETECT_INTERVAL 1000
|
||||
u32 ue2rp;
|
||||
struct delayed_work recover_port;
|
||||
struct work_struct sess_work;
|
||||
|
||||
bool mac_addr_set;
|
||||
u8 mac_address[ETH_ALEN];
|
||||
@ -435,7 +430,6 @@ struct beiscsi_hba {
|
||||
struct be_ctrl_info ctrl;
|
||||
unsigned int generation;
|
||||
unsigned int interface_handle;
|
||||
struct mgmt_session_info boot_sess;
|
||||
struct invalidate_command_table inv_tbl[128];
|
||||
|
||||
struct be_aic_obj aic_obj[MAX_CPUS];
|
||||
@ -444,8 +438,29 @@ struct beiscsi_hba {
|
||||
struct scatterlist *sg,
|
||||
uint32_t num_sg, uint32_t xferlen,
|
||||
uint32_t writedir);
|
||||
struct boot_struct {
|
||||
int retry;
|
||||
unsigned int tag;
|
||||
unsigned int s_handle;
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
enum {
|
||||
BEISCSI_BOOT_REOPEN_SESS = 1,
|
||||
BEISCSI_BOOT_GET_SHANDLE,
|
||||
BEISCSI_BOOT_GET_SINFO,
|
||||
BEISCSI_BOOT_LOGOUT_SESS,
|
||||
BEISCSI_BOOT_CREATE_KSET,
|
||||
} action;
|
||||
struct mgmt_session_info boot_sess;
|
||||
struct iscsi_boot_kset *boot_kset;
|
||||
} boot_struct;
|
||||
struct work_struct boot_work;
|
||||
};
|
||||
|
||||
#define beiscsi_hba_in_error(phba) ((phba)->state & BEISCSI_HBA_IN_ERR)
|
||||
#define beiscsi_hba_is_online(phba) \
|
||||
(!beiscsi_hba_in_error((phba)) && \
|
||||
test_bit(BEISCSI_HBA_ONLINE, &phba->state))
|
||||
|
||||
struct beiscsi_session {
|
||||
struct pci_pool *bhs_pool;
|
||||
};
|
||||
@ -508,6 +523,7 @@ struct beiscsi_io_task {
|
||||
struct sgl_handle *psgl_handle;
|
||||
struct beiscsi_conn *conn;
|
||||
struct scsi_cmnd *scsi_cmnd;
|
||||
int num_sg;
|
||||
struct hwi_wrb_context *pwrb_context;
|
||||
unsigned int cmd_sn;
|
||||
unsigned int flags;
|
||||
@ -592,80 +608,81 @@ struct amap_beiscsi_offload_params {
|
||||
u8 max_recv_data_segment_length[32];
|
||||
};
|
||||
|
||||
/* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
|
||||
struct beiscsi_hba *phba, struct sol_cqe *psol);*/
|
||||
|
||||
struct async_pdu_handle {
|
||||
struct hd_async_handle {
|
||||
struct list_head link;
|
||||
struct be_bus_address pa;
|
||||
void *pbuffer;
|
||||
unsigned int consumed;
|
||||
unsigned char index;
|
||||
unsigned char is_header;
|
||||
unsigned short cri;
|
||||
unsigned long buffer_len;
|
||||
u32 buffer_len;
|
||||
u16 index;
|
||||
u16 cri;
|
||||
u8 is_header;
|
||||
u8 is_final;
|
||||
};
|
||||
|
||||
struct hwi_async_entry {
|
||||
struct {
|
||||
unsigned char hdr_received;
|
||||
unsigned char hdr_len;
|
||||
unsigned short bytes_received;
|
||||
/**
|
||||
* This has list of async PDUs that are waiting to be processed.
|
||||
* Buffers live in this list for a brief duration before they get
|
||||
* processed and posted back to hardware.
|
||||
* Note that we don't really need one cri_wait_queue per async_entry.
|
||||
* We need one cri_wait_queue per CRI. Its easier to manage if this
|
||||
* is tagged along with the async_entry.
|
||||
*/
|
||||
struct hd_async_entry {
|
||||
struct cri_wait_queue {
|
||||
unsigned short hdr_len;
|
||||
unsigned int bytes_received;
|
||||
unsigned int bytes_needed;
|
||||
struct list_head list;
|
||||
} wait_queue;
|
||||
|
||||
struct list_head header_busy_list;
|
||||
struct list_head data_busy_list;
|
||||
} wq;
|
||||
/* handles posted to FW resides here */
|
||||
struct hd_async_handle *header;
|
||||
struct hd_async_handle *data;
|
||||
};
|
||||
|
||||
struct hwi_async_pdu_context {
|
||||
struct {
|
||||
struct be_bus_address pa_base;
|
||||
void *va_base;
|
||||
void *ring_base;
|
||||
struct async_pdu_handle *handle_base;
|
||||
struct hd_async_buf_context {
|
||||
struct be_bus_address pa_base;
|
||||
void *va_base;
|
||||
void *ring_base;
|
||||
struct hd_async_handle *handle_base;
|
||||
u16 free_entries;
|
||||
u32 buffer_size;
|
||||
/**
|
||||
* Once iSCSI layer finishes processing an async PDU, the
|
||||
* handles used for the PDU are added to this list.
|
||||
* They are posted back to FW in groups of 8.
|
||||
*/
|
||||
struct list_head free_list;
|
||||
};
|
||||
|
||||
unsigned int host_write_ptr;
|
||||
unsigned int ep_read_ptr;
|
||||
unsigned int writables;
|
||||
|
||||
unsigned int free_entries;
|
||||
unsigned int busy_entries;
|
||||
|
||||
struct list_head free_list;
|
||||
} async_header;
|
||||
|
||||
struct {
|
||||
struct be_bus_address pa_base;
|
||||
void *va_base;
|
||||
void *ring_base;
|
||||
struct async_pdu_handle *handle_base;
|
||||
|
||||
unsigned int host_write_ptr;
|
||||
unsigned int ep_read_ptr;
|
||||
unsigned int writables;
|
||||
|
||||
unsigned int free_entries;
|
||||
unsigned int busy_entries;
|
||||
struct list_head free_list;
|
||||
} async_data;
|
||||
|
||||
unsigned int buffer_size;
|
||||
unsigned int num_entries;
|
||||
/**
|
||||
* hd_async_context is declared for each ULP supporting iSCSI function.
|
||||
*/
|
||||
struct hd_async_context {
|
||||
struct hd_async_buf_context async_header;
|
||||
struct hd_async_buf_context async_data;
|
||||
u16 num_entries;
|
||||
/**
|
||||
* When unsol PDU is in, it needs to be chained till all the bytes are
|
||||
* received and then processing is done. hd_async_entry is created
|
||||
* based on the cid_count for each ULP. When unsol PDU comes in based
|
||||
* on the conn_id it needs to be added to the correct async_entry wq.
|
||||
* Below defined cid_to_async_cri_map is used to reterive the
|
||||
* async_cri_map for a particular connection.
|
||||
*
|
||||
* This array is initialized after beiscsi_create_wrb_rings returns.
|
||||
*
|
||||
* - this method takes more memory space, fixed to 2K
|
||||
* - any support for connections greater than this the array size needs
|
||||
* to be incremented
|
||||
*/
|
||||
#define BE_GET_ASYNC_CRI_FROM_CID(cid) (pasync_ctx->cid_to_async_cri_map[cid])
|
||||
unsigned short cid_to_async_cri_map[BE_MAX_SESSION];
|
||||
/**
|
||||
* This is a varying size list! Do not add anything
|
||||
* after this entry!!
|
||||
* This is a variable size array. Don`t add anything after this field!!
|
||||
*/
|
||||
struct hwi_async_entry *async_entry;
|
||||
struct hd_async_entry *async_entry;
|
||||
};
|
||||
|
||||
#define PDUCQE_CODE_MASK 0x0000003F
|
||||
#define PDUCQE_DPL_MASK 0xFFFF0000
|
||||
#define PDUCQE_INDEX_MASK 0x0000FFFF
|
||||
|
||||
struct i_t_dpdu_cqe {
|
||||
u32 dw[4];
|
||||
} __packed;
|
||||
@ -845,7 +862,6 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
|
||||
void
|
||||
free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
|
||||
|
||||
void beiscsi_process_all_cqs(struct work_struct *work);
|
||||
void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
|
||||
struct iscsi_task *task);
|
||||
|
||||
@ -856,11 +872,6 @@ void hwi_ring_cq_db(struct beiscsi_hba *phba,
|
||||
unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget);
|
||||
void beiscsi_process_mcc_cq(struct beiscsi_hba *phba);
|
||||
|
||||
static inline bool beiscsi_error(struct beiscsi_hba *phba)
|
||||
{
|
||||
return phba->ue_detected || phba->fw_timeout;
|
||||
}
|
||||
|
||||
struct pdu_nop_out {
|
||||
u32 dw[12];
|
||||
};
|
||||
@ -1067,11 +1078,18 @@ struct hwi_context_memory {
|
||||
struct be_queue_info be_cq[MAX_CPUS - 1];
|
||||
|
||||
struct be_queue_info *be_wrbq;
|
||||
/**
|
||||
* Create array of ULP number for below entries as DEFQ
|
||||
* will be created for both ULP if iSCSI Protocol is
|
||||
* loaded on both ULP.
|
||||
*/
|
||||
struct be_queue_info be_def_hdrq[BEISCSI_ULP_COUNT];
|
||||
struct be_queue_info be_def_dataq[BEISCSI_ULP_COUNT];
|
||||
struct hwi_async_pdu_context *pasync_ctx[BEISCSI_ULP_COUNT];
|
||||
struct hd_async_context *pasync_ctx[BEISCSI_ULP_COUNT];
|
||||
};
|
||||
|
||||
void beiscsi_start_boot_work(struct beiscsi_hba *phba, unsigned int s_handle);
|
||||
|
||||
/* Logging related definitions */
|
||||
#define BEISCSI_LOG_INIT 0x0001 /* Initialization events */
|
||||
#define BEISCSI_LOG_MBOX 0x0002 /* Mailbox Events */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2005 - 2015 Emulex
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@ -7,10 +7,10 @@
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com)
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@avagotech.com
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
@ -96,7 +96,6 @@ struct mcc_wrb {
|
||||
struct mcc_wrb_payload payload;
|
||||
};
|
||||
|
||||
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
|
||||
int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
struct sockaddr *dst_addr,
|
||||
struct beiscsi_endpoint *beiscsi_ep,
|
||||
@ -266,50 +265,41 @@ struct beiscsi_endpoint {
|
||||
u16 cid_vld;
|
||||
};
|
||||
|
||||
int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba);
|
||||
int mgmt_get_port_name(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba);
|
||||
|
||||
unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep,
|
||||
unsigned short cid,
|
||||
unsigned short issue_reset,
|
||||
unsigned short savecfg_flag);
|
||||
|
||||
int mgmt_set_ip(struct beiscsi_hba *phba,
|
||||
struct iscsi_iface_param_info *ip_param,
|
||||
struct iscsi_iface_param_info *subnet_param,
|
||||
uint32_t boot_proto);
|
||||
int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type);
|
||||
|
||||
unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba);
|
||||
int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
|
||||
u8 *ip, u8 *subnet);
|
||||
|
||||
unsigned int mgmt_reopen_session(struct beiscsi_hba *phba,
|
||||
unsigned int reopen_type,
|
||||
unsigned sess_handle);
|
||||
int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw);
|
||||
|
||||
unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
|
||||
u32 boot_session_handle,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type,
|
||||
struct be_cmd_get_def_gateway_resp *resp);
|
||||
|
||||
int mgmt_get_nic_conf(struct beiscsi_hba *phba,
|
||||
struct be_cmd_get_nic_conf_resp *mac);
|
||||
|
||||
int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
|
||||
struct be_cmd_get_if_info_resp **if_info);
|
||||
int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type,
|
||||
struct be_cmd_get_if_info_resp **if_info);
|
||||
|
||||
int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
|
||||
struct be_cmd_get_def_gateway_resp *gateway);
|
||||
unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba);
|
||||
|
||||
int mgmt_set_gateway(struct beiscsi_hba *phba,
|
||||
struct iscsi_iface_param_info *gateway_param);
|
||||
int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
|
||||
|
||||
int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
|
||||
unsigned int *s_handle);
|
||||
unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba);
|
||||
|
||||
unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba);
|
||||
unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba);
|
||||
|
||||
int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
|
||||
unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba);
|
||||
|
||||
unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async);
|
||||
|
||||
int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle);
|
||||
|
||||
ssize_t beiscsi_drvr_ver_disp(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
@ -339,7 +329,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
|
||||
struct wrb_handle *pwrb_handle,
|
||||
struct hwi_wrb_context *pwrb_context);
|
||||
|
||||
void beiscsi_ue_detect(struct beiscsi_hba *phba);
|
||||
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
|
||||
struct be_set_eqd *, int num);
|
||||
|
||||
|
@ -5827,13 +5827,13 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
|
||||
bfa_port_speed_t max_speed = 0;
|
||||
struct bfa_port_attr_s port_attr;
|
||||
bfa_port_speed_t port_speed, rport_speed;
|
||||
bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
|
||||
|
||||
bfa_boolean_t trl_enabled;
|
||||
|
||||
if (port == NULL)
|
||||
return 0;
|
||||
|
||||
fcs = port->fcs;
|
||||
trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
|
||||
|
||||
/* Get Physical port's current speed */
|
||||
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)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
|
||||
static void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
|
||||
{
|
||||
struct bnx2fc_mp_req *mp_req;
|
||||
struct fc_frame_header *fc_hdr, *fh;
|
||||
@ -364,7 +364,7 @@ srr_compl_done:
|
||||
kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
|
||||
}
|
||||
|
||||
void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
|
||||
static void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
|
||||
{
|
||||
struct bnx2fc_cmd *orig_io_req, *new_io_req;
|
||||
struct bnx2fc_cmd *rec_req;
|
||||
|
@ -625,7 +625,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
|
||||
*
|
||||
* @arg: ptr to bnx2fc_percpu_info structure
|
||||
*/
|
||||
int bnx2fc_percpu_io_thread(void *arg)
|
||||
static int bnx2fc_percpu_io_thread(void *arg)
|
||||
{
|
||||
struct bnx2fc_percpu_s *p = arg;
|
||||
struct bnx2fc_work *work, *tmp;
|
||||
@ -1410,9 +1410,10 @@ bind_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,
|
||||
struct net_device *netdev,
|
||||
enum fip_state fip_mode)
|
||||
static struct bnx2fc_interface *
|
||||
bnx2fc_interface_create(struct bnx2fc_hba *hba,
|
||||
struct net_device *netdev,
|
||||
enum fip_state fip_mode)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr_dev;
|
||||
struct bnx2fc_interface *interface;
|
||||
@ -2765,8 +2766,7 @@ static void __exit bnx2fc_mod_exit(void)
|
||||
* held.
|
||||
*/
|
||||
mutex_lock(&bnx2fc_dev_lock);
|
||||
list_splice(&adapter_list, &to_be_deleted);
|
||||
INIT_LIST_HEAD(&adapter_list);
|
||||
list_splice_init(&adapter_list, &to_be_deleted);
|
||||
adapter_count = 0;
|
||||
mutex_unlock(&bnx2fc_dev_lock);
|
||||
|
||||
|
@ -994,7 +994,7 @@ void bnx2fc_arm_cq(struct bnx2fc_rport *tgt)
|
||||
|
||||
}
|
||||
|
||||
struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
|
||||
static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
|
||||
{
|
||||
struct bnx2fc_work *work;
|
||||
work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC);
|
||||
|
@ -1079,7 +1079,7 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
|
||||
return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
|
||||
}
|
||||
|
||||
int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req)
|
||||
static int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req)
|
||||
{
|
||||
struct bnx2fc_rport *tgt = io_req->tgt;
|
||||
int rc = SUCCESS;
|
||||
|
@ -1721,7 +1721,7 @@ out:
|
||||
|
||||
/* Wake up waiting threads */
|
||||
csio_scsi_cmnd(req) = NULL;
|
||||
complete_all(&req->cmplobj);
|
||||
complete(&req->cmplobj);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1945,6 +1945,7 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd)
|
||||
ready = csio_is_lnode_ready(ln);
|
||||
tmo = CSIO_SCSI_ABRT_TMO_MS;
|
||||
|
||||
reinit_completion(&ioreq->cmplobj);
|
||||
spin_lock_irq(&hw->lock);
|
||||
rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE));
|
||||
spin_unlock_irq(&hw->lock);
|
||||
@ -1964,8 +1965,6 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd)
|
||||
goto inval_scmnd;
|
||||
}
|
||||
|
||||
/* Wait for completion */
|
||||
init_completion(&ioreq->cmplobj);
|
||||
wait_for_completion_timeout(&ioreq->cmplobj, msecs_to_jiffies(tmo));
|
||||
|
||||
/* FW didnt respond to abort within our timeout */
|
||||
|
@ -822,17 +822,6 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cxlflash_shutdown() - shutdown handler
|
||||
* @pdev: PCI device associated with the host.
|
||||
*/
|
||||
static void cxlflash_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct cxlflash_cfg *cfg = pci_get_drvdata(pdev);
|
||||
|
||||
notify_shutdown(cfg, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* cxlflash_remove() - PCI entry point to tear down host
|
||||
* @pdev: PCI device associated with the host.
|
||||
@ -844,6 +833,11 @@ static void cxlflash_remove(struct pci_dev *pdev)
|
||||
struct cxlflash_cfg *cfg = pci_get_drvdata(pdev);
|
||||
ulong lock_flags;
|
||||
|
||||
if (!pci_is_enabled(pdev)) {
|
||||
pr_debug("%s: Device is disabled\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If a Task Management Function is active, wait for it to complete
|
||||
* before continuing with remove.
|
||||
*/
|
||||
@ -1046,6 +1040,8 @@ static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
|
||||
do {
|
||||
msleep(delay_us / 1000);
|
||||
status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
|
||||
if (status == U64_MAX)
|
||||
nretry /= 2;
|
||||
} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE &&
|
||||
nretry--);
|
||||
|
||||
@ -1077,6 +1073,8 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
|
||||
do {
|
||||
msleep(delay_us / 1000);
|
||||
status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
|
||||
if (status == U64_MAX)
|
||||
nretry /= 2;
|
||||
} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE &&
|
||||
nretry--);
|
||||
|
||||
@ -1095,42 +1093,25 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
|
||||
* online. This toggling action can cause this routine to delay up to a few
|
||||
* seconds. When configured to use the internal LUN feature of the AFU, a
|
||||
* failure to come online is overridden.
|
||||
*
|
||||
* Return:
|
||||
* 0 when the WWPN is successfully written and the port comes back online
|
||||
* -1 when the port fails to go offline or come back up online
|
||||
*/
|
||||
static int afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs,
|
||||
u64 wwpn)
|
||||
static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs,
|
||||
u64 wwpn)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
set_port_offline(fc_regs);
|
||||
|
||||
if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US,
|
||||
FC_PORT_STATUS_RETRY_CNT)) {
|
||||
pr_debug("%s: wait on port %d to go offline timed out\n",
|
||||
__func__, port);
|
||||
rc = -1; /* but continue on to leave the port back online */
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
writeq_be(wwpn, &fc_regs[FC_PNAME / 8]);
|
||||
|
||||
/* Always return success after programming WWPN */
|
||||
rc = 0;
|
||||
writeq_be(wwpn, &fc_regs[FC_PNAME / 8]);
|
||||
|
||||
set_port_online(fc_regs);
|
||||
|
||||
if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US,
|
||||
FC_PORT_STATUS_RETRY_CNT)) {
|
||||
pr_err("%s: wait on port %d to go online timed out\n",
|
||||
__func__, port);
|
||||
pr_debug("%s: wait on port %d to go online timed out\n",
|
||||
__func__, port);
|
||||
}
|
||||
|
||||
pr_debug("%s: returning rc=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1187,7 +1168,7 @@ static const struct asyc_intr_info ainfo[] = {
|
||||
{SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR},
|
||||
{SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST},
|
||||
{SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0},
|
||||
{SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST},
|
||||
{SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0},
|
||||
{SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET},
|
||||
{SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0},
|
||||
{SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET},
|
||||
@ -1195,7 +1176,7 @@ static const struct asyc_intr_info ainfo[] = {
|
||||
{SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR},
|
||||
{SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST},
|
||||
{SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0},
|
||||
{SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST},
|
||||
{SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0},
|
||||
{0x0, "", 0, 0} /* terminator */
|
||||
};
|
||||
|
||||
@ -1631,15 +1612,10 @@ static int init_global(struct cxlflash_cfg *cfg)
|
||||
[FC_CRC_THRESH / 8]);
|
||||
|
||||
/* Set WWPNs. If already programmed, wwpn[i] is 0 */
|
||||
if (wwpn[i] != 0 &&
|
||||
afu_set_wwpn(afu, i,
|
||||
&afu->afu_map->global.fc_regs[i][0],
|
||||
wwpn[i])) {
|
||||
dev_err(dev, "%s: failed to set WWPN on port %d\n",
|
||||
__func__, i);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
if (wwpn[i] != 0)
|
||||
afu_set_wwpn(afu, i,
|
||||
&afu->afu_map->global.fc_regs[i][0],
|
||||
wwpn[i]);
|
||||
/* Programming WWPN back to back causes additional
|
||||
* offline/online transitions and a PLOGI
|
||||
*/
|
||||
@ -2048,6 +2024,11 @@ retry:
|
||||
* cxlflash_eh_host_reset_handler() - reset the host adapter
|
||||
* @scp: SCSI command from stack identifying host.
|
||||
*
|
||||
* Following a reset, the state is evaluated again in case an EEH occurred
|
||||
* during the reset. In such a scenario, the host reset will either yield
|
||||
* until the EEH recovery is complete or return success or failure based
|
||||
* upon the current device state.
|
||||
*
|
||||
* Return:
|
||||
* SUCCESS as defined in scsi/scsi.h
|
||||
* FAILED as defined in scsi/scsi.h
|
||||
@ -2080,7 +2061,8 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
|
||||
} else
|
||||
cfg->state = STATE_NORMAL;
|
||||
wake_up_all(&cfg->reset_waitq);
|
||||
break;
|
||||
ssleep(1);
|
||||
/* fall through */
|
||||
case STATE_RESET:
|
||||
wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
|
||||
if (cfg->state == STATE_NORMAL)
|
||||
@ -2596,6 +2578,9 @@ out_remove:
|
||||
* @pdev: PCI device struct.
|
||||
* @state: PCI channel state.
|
||||
*
|
||||
* When an EEH occurs during an active reset, wait until the reset is
|
||||
* complete and then take action based upon the device state.
|
||||
*
|
||||
* Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
|
||||
*/
|
||||
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,
|
||||
|
||||
switch (state) {
|
||||
case pci_channel_io_frozen:
|
||||
wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
|
||||
if (cfg->state == STATE_FAILTERM)
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
|
||||
cfg->state = STATE_RESET;
|
||||
scsi_block_requests(cfg->host);
|
||||
drain_ioctls(cfg);
|
||||
@ -2685,7 +2674,7 @@ static struct pci_driver cxlflash_driver = {
|
||||
.id_table = cxlflash_pci_table,
|
||||
.probe = cxlflash_probe,
|
||||
.remove = cxlflash_remove,
|
||||
.shutdown = cxlflash_shutdown,
|
||||
.shutdown = cxlflash_remove,
|
||||
.err_handler = &cxlflash_err_handler,
|
||||
};
|
||||
|
||||
|
@ -709,14 +709,13 @@ int cxlflash_disk_release(struct scsi_device *sdev,
|
||||
* @cfg: Internal structure associated with the host.
|
||||
* @ctxi: Context to release.
|
||||
*
|
||||
* This routine is safe to be called with a a non-initialized context
|
||||
* and is tolerant of being called with the context's mutex held (it
|
||||
* will be unlocked if necessary before freeing). Also note that the
|
||||
* routine conditionally checks for the existence of the context control
|
||||
* map before clearing the RHT registers and context capabilities because
|
||||
* it is possible to destroy a context while the context is in the error
|
||||
* state (previous mapping was removed [so there is no need to worry about
|
||||
* clearing] and context is waiting for a new mapping).
|
||||
* This routine is safe to be called with a a non-initialized context.
|
||||
* Also note that the routine conditionally checks for the existence
|
||||
* of the context control map before clearing the RHT registers and
|
||||
* context capabilities because it is possible to destroy a context
|
||||
* while the context is in the error state (previous mapping was
|
||||
* removed [so there is no need to worry about clearing] and context
|
||||
* is waiting for a new mapping).
|
||||
*/
|
||||
static void destroy_context(struct cxlflash_cfg *cfg,
|
||||
struct ctx_info *ctxi)
|
||||
@ -732,9 +731,6 @@ static void destroy_context(struct cxlflash_cfg *cfg,
|
||||
writeq_be(0, &ctxi->ctrl_map->rht_cnt_id);
|
||||
writeq_be(0, &ctxi->ctrl_map->ctx_cap);
|
||||
}
|
||||
|
||||
if (mutex_is_locked(&ctxi->mutex))
|
||||
mutex_unlock(&ctxi->mutex);
|
||||
}
|
||||
|
||||
/* Free memory associated with context */
|
||||
@ -792,32 +788,58 @@ err:
|
||||
* @cfg: Internal structure associated with the host.
|
||||
* @ctx: Previously obtained CXL context reference.
|
||||
* @ctxid: Previously obtained process element associated with CXL context.
|
||||
* @adap_fd: Previously obtained adapter fd associated with CXL context.
|
||||
* @file: Previously obtained file associated with CXL context.
|
||||
* @perms: User-specified permissions.
|
||||
*
|
||||
* Upon return, the context is marked as initialized and the context's mutex
|
||||
* is locked.
|
||||
*/
|
||||
static void init_context(struct ctx_info *ctxi, struct cxlflash_cfg *cfg,
|
||||
struct cxl_context *ctx, int ctxid, int adap_fd,
|
||||
struct file *file, u32 perms)
|
||||
struct cxl_context *ctx, int ctxid, struct file *file,
|
||||
u32 perms)
|
||||
{
|
||||
struct afu *afu = cfg->afu;
|
||||
|
||||
ctxi->rht_perms = perms;
|
||||
ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl;
|
||||
ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid);
|
||||
ctxi->lfd = adap_fd;
|
||||
ctxi->pid = current->tgid; /* tgid = pid */
|
||||
ctxi->ctx = ctx;
|
||||
ctxi->cfg = cfg;
|
||||
ctxi->file = file;
|
||||
ctxi->initialized = true;
|
||||
mutex_init(&ctxi->mutex);
|
||||
kref_init(&ctxi->kref);
|
||||
INIT_LIST_HEAD(&ctxi->luns);
|
||||
INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
|
||||
}
|
||||
|
||||
/**
|
||||
* remove_context() - context kref release handler
|
||||
* @kref: Kernel reference associated with context to be removed.
|
||||
*
|
||||
* When a context no longer has any references it can safely be removed
|
||||
* from global access and destroyed. Note that it is assumed the thread
|
||||
* relinquishing access to the context holds its mutex.
|
||||
*/
|
||||
static void remove_context(struct kref *kref)
|
||||
{
|
||||
struct ctx_info *ctxi = container_of(kref, struct ctx_info, kref);
|
||||
struct cxlflash_cfg *cfg = ctxi->cfg;
|
||||
u64 ctxid = DECODE_CTXID(ctxi->ctxid);
|
||||
|
||||
/* Remove context from table/error list */
|
||||
WARN_ON(!mutex_is_locked(&ctxi->mutex));
|
||||
ctxi->unavail = true;
|
||||
mutex_unlock(&ctxi->mutex);
|
||||
mutex_lock(&cfg->ctx_tbl_list_mutex);
|
||||
mutex_lock(&ctxi->mutex);
|
||||
|
||||
if (!list_empty(&ctxi->list))
|
||||
list_del(&ctxi->list);
|
||||
cfg->ctx_tbl[ctxid] = NULL;
|
||||
mutex_unlock(&cfg->ctx_tbl_list_mutex);
|
||||
mutex_unlock(&ctxi->mutex);
|
||||
|
||||
/* Context now completely uncoupled/unreachable */
|
||||
destroy_context(cfg, ctxi);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -845,7 +867,6 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
|
||||
|
||||
int i;
|
||||
int rc = 0;
|
||||
int lfd;
|
||||
u64 ctxid = DECODE_CTXID(detach->context_id),
|
||||
rctxid = detach->context_id;
|
||||
|
||||
@ -887,40 +908,13 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Tear down context following last LUN cleanup */
|
||||
if (list_empty(&ctxi->luns)) {
|
||||
ctxi->unavail = true;
|
||||
mutex_unlock(&ctxi->mutex);
|
||||
mutex_lock(&cfg->ctx_tbl_list_mutex);
|
||||
mutex_lock(&ctxi->mutex);
|
||||
|
||||
/* Might not have been in error list so conditionally remove */
|
||||
if (!list_empty(&ctxi->list))
|
||||
list_del(&ctxi->list);
|
||||
cfg->ctx_tbl[ctxid] = NULL;
|
||||
mutex_unlock(&cfg->ctx_tbl_list_mutex);
|
||||
mutex_unlock(&ctxi->mutex);
|
||||
|
||||
lfd = ctxi->lfd;
|
||||
destroy_context(cfg, ctxi);
|
||||
ctxi = NULL;
|
||||
/*
|
||||
* Release the context reference and the sdev reference that
|
||||
* bound this LUN to the context.
|
||||
*/
|
||||
if (kref_put(&ctxi->kref, remove_context))
|
||||
put_ctx = false;
|
||||
|
||||
/*
|
||||
* As a last step, clean up external resources when not
|
||||
* already on an external cleanup thread, i.e.: close(adap_fd).
|
||||
*
|
||||
* NOTE: this will free up the context from the CXL services,
|
||||
* allowing it to dole out the same context_id on a future
|
||||
* (or even currently in-flight) disk_attach operation.
|
||||
*/
|
||||
if (lfd != -1)
|
||||
sys_close(lfd);
|
||||
}
|
||||
|
||||
/* Release the sdev reference that bound this LUN to the context */
|
||||
scsi_device_put(sdev);
|
||||
|
||||
out:
|
||||
if (put_ctx)
|
||||
put_context(ctxi);
|
||||
@ -941,34 +935,18 @@ static int cxlflash_disk_detach(struct scsi_device *sdev,
|
||||
*
|
||||
* This routine is the release handler for the fops registered with
|
||||
* the CXL services on an initial attach for a context. It is called
|
||||
* when a close is performed on the adapter file descriptor returned
|
||||
* to the user. Programmatically, the user is not required to perform
|
||||
* the close, as it is handled internally via the detach ioctl when
|
||||
* a context is being removed. Note that nothing prevents the user
|
||||
* from performing a close, but the user should be aware that doing
|
||||
* so is considered catastrophic and subsequent usage of the superpipe
|
||||
* API with previously saved off tokens will fail.
|
||||
* when a close (explicity by the user or as part of a process tear
|
||||
* down) is performed on the adapter file descriptor returned to the
|
||||
* user. The user should be aware that explicitly performing a close
|
||||
* considered catastrophic and subsequent usage of the superpipe API
|
||||
* with previously saved off tokens will fail.
|
||||
*
|
||||
* When initiated from an external close (either by the user or via
|
||||
* a process tear down), the routine derives the context reference
|
||||
* and calls detach for each LUN associated with the context. The
|
||||
* final detach operation will cause the context itself to be freed.
|
||||
* Note that the saved off lfd is reset prior to calling detach to
|
||||
* signify that the final detach should not perform a close.
|
||||
*
|
||||
* When initiated from a detach operation as part of the tear down
|
||||
* of a context, the context is first completely freed and then the
|
||||
* close is performed. This routine will fail to derive the context
|
||||
* reference (due to the context having already been freed) and then
|
||||
* call into the CXL release entry point.
|
||||
*
|
||||
* Thus, with exception to when the CXL process element (context id)
|
||||
* lookup fails (a case that should theoretically never occur), every
|
||||
* call into this routine results in a complete freeing of a context.
|
||||
*
|
||||
* As part of the detach, all per-context resources associated with the LUN
|
||||
* are cleaned up. When detaching the last LUN for a context, the context
|
||||
* itself is cleaned up and released.
|
||||
* This routine derives the context reference and calls detach for
|
||||
* each LUN associated with the context.The final detach operation
|
||||
* causes the context itself to be freed. With exception to when the
|
||||
* CXL process element (context id) lookup fails (a case that should
|
||||
* theoretically never occur), every call into this routine results
|
||||
* in a complete freeing of a context.
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
@ -1006,11 +984,8 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file)
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: close(%d) for context %d\n",
|
||||
__func__, ctxi->lfd, ctxid);
|
||||
dev_dbg(dev, "%s: close for context %d\n", __func__, ctxid);
|
||||
|
||||
/* Reset the file descriptor to indicate we're on a close() thread */
|
||||
ctxi->lfd = -1;
|
||||
detach.context_id = ctxi->ctxid;
|
||||
list_for_each_entry_safe(lun_access, t, &ctxi->luns, list)
|
||||
_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)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: fault(%d) for context %d\n",
|
||||
__func__, ctxi->lfd, ctxid);
|
||||
dev_dbg(dev, "%s: fault for context %d\n", __func__, ctxid);
|
||||
|
||||
if (likely(!ctxi->err_recovery_active)) {
|
||||
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)
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s: mmap(%d) for context %d\n",
|
||||
__func__, ctxi->lfd, ctxid);
|
||||
dev_dbg(dev, "%s: mmap for context %d\n", __func__, ctxid);
|
||||
|
||||
rc = cxl_fd_mmap(file, vma);
|
||||
if (likely(!rc)) {
|
||||
@ -1377,12 +1350,12 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
|
||||
lun_access->lli = lli;
|
||||
lun_access->sdev = sdev;
|
||||
|
||||
/* Non-NULL context indicates reuse */
|
||||
/* Non-NULL context indicates reuse (another context reference) */
|
||||
if (ctxi) {
|
||||
dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n",
|
||||
__func__, rctxid);
|
||||
kref_get(&ctxi->kref);
|
||||
list_add(&lun_access->list, &ctxi->luns);
|
||||
fd = ctxi->lfd;
|
||||
goto out_attach;
|
||||
}
|
||||
|
||||
@ -1430,7 +1403,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
|
||||
perms = SISL_RHT_PERM(attach->hdr.flags + 1);
|
||||
|
||||
/* Context mutex is locked upon return */
|
||||
init_context(ctxi, cfg, ctx, ctxid, fd, file, perms);
|
||||
init_context(ctxi, cfg, ctx, ctxid, file, perms);
|
||||
|
||||
rc = afu_attach(cfg, ctxi);
|
||||
if (unlikely(rc)) {
|
||||
@ -1445,7 +1418,6 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
|
||||
* knows about us yet; we can be the only one holding our mutex.
|
||||
*/
|
||||
list_add(&lun_access->list, &ctxi->luns);
|
||||
mutex_unlock(&ctxi->mutex);
|
||||
mutex_lock(&cfg->ctx_tbl_list_mutex);
|
||||
mutex_lock(&ctxi->mutex);
|
||||
cfg->ctx_tbl[ctxid] = ctxi;
|
||||
@ -1453,7 +1425,11 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
|
||||
fd_install(fd, file);
|
||||
|
||||
out_attach:
|
||||
attach->hdr.return_flags = 0;
|
||||
if (fd != -1)
|
||||
attach->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD;
|
||||
else
|
||||
attach->hdr.return_flags = 0;
|
||||
|
||||
attach->context_id = ctxi->ctxid;
|
||||
attach->block_size = gli->blk_len;
|
||||
attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea);
|
||||
@ -1494,7 +1470,7 @@ err:
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
/* Cleanup our context; safe to call even with mutex locked */
|
||||
/* Cleanup our context */
|
||||
if (ctxi) {
|
||||
destroy_context(cfg, ctxi);
|
||||
ctxi = NULL;
|
||||
@ -1509,16 +1485,19 @@ err:
|
||||
* recover_context() - recovers a context in error
|
||||
* @cfg: Internal structure associated with the host.
|
||||
* @ctxi: Context to release.
|
||||
* @adap_fd: Adapter file descriptor associated with new/recovered context.
|
||||
*
|
||||
* Restablishes the state for a context-in-error.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
*/
|
||||
static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
|
||||
static int recover_context(struct cxlflash_cfg *cfg,
|
||||
struct ctx_info *ctxi,
|
||||
int *adap_fd)
|
||||
{
|
||||
struct device *dev = &cfg->dev->dev;
|
||||
int rc = 0;
|
||||
int old_fd, fd = -1;
|
||||
int fd = -1;
|
||||
int ctxid = -1;
|
||||
struct file *file;
|
||||
struct cxl_context *ctx;
|
||||
@ -1566,9 +1545,7 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
|
||||
* No error paths after this point. Once the fd is installed it's
|
||||
* visible to user space and can't be undone safely on this thread.
|
||||
*/
|
||||
old_fd = ctxi->lfd;
|
||||
ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid);
|
||||
ctxi->lfd = fd;
|
||||
ctxi->ctx = ctx;
|
||||
ctxi->file = file;
|
||||
|
||||
@ -1585,9 +1562,7 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
|
||||
cfg->ctx_tbl[ctxid] = ctxi;
|
||||
mutex_unlock(&cfg->ctx_tbl_list_mutex);
|
||||
fd_install(fd, file);
|
||||
|
||||
/* Release the original adapter fd and associated CXL resources */
|
||||
sys_close(old_fd);
|
||||
*adap_fd = fd;
|
||||
out:
|
||||
dev_dbg(dev, "%s: returning ctxid=%d fd=%d rc=%d\n",
|
||||
__func__, ctxid, fd, rc);
|
||||
@ -1646,6 +1621,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
|
||||
rctxid = recover->context_id;
|
||||
long reg;
|
||||
int lretry = 20; /* up to 2 seconds */
|
||||
int new_adap_fd = -1;
|
||||
int rc = 0;
|
||||
|
||||
atomic_inc(&cfg->recovery_threads);
|
||||
@ -1675,7 +1651,7 @@ retry:
|
||||
|
||||
if (ctxi->err_recovery_active) {
|
||||
retry_recover:
|
||||
rc = recover_context(cfg, ctxi);
|
||||
rc = recover_context(cfg, ctxi, &new_adap_fd);
|
||||
if (unlikely(rc)) {
|
||||
dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n",
|
||||
__func__, ctxid, rc);
|
||||
@ -1697,9 +1673,9 @@ retry_recover:
|
||||
|
||||
ctxi->err_recovery_active = false;
|
||||
recover->context_id = ctxi->ctxid;
|
||||
recover->adap_fd = ctxi->lfd;
|
||||
recover->adap_fd = new_adap_fd;
|
||||
recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea);
|
||||
recover->hdr.return_flags |=
|
||||
recover->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD |
|
||||
DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET;
|
||||
goto out;
|
||||
}
|
||||
|
@ -100,13 +100,14 @@ struct ctx_info {
|
||||
|
||||
struct cxl_ioctl_start_work work;
|
||||
u64 ctxid;
|
||||
int lfd;
|
||||
pid_t pid;
|
||||
bool initialized;
|
||||
bool unavail;
|
||||
bool err_recovery_active;
|
||||
struct mutex mutex; /* Context protection */
|
||||
struct kref kref;
|
||||
struct cxl_context *ctx;
|
||||
struct cxlflash_cfg *cfg;
|
||||
struct list_head luns; /* LUNs attached to this context */
|
||||
const struct vm_operations_struct *cxl_mmap_vmops;
|
||||
struct file *file;
|
||||
|
@ -1135,14 +1135,13 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
|
||||
ctxid_dst = DECODE_CTXID(clone->context_id_dst),
|
||||
rctxid_src = clone->context_id_src,
|
||||
rctxid_dst = clone->context_id_dst;
|
||||
int adap_fd_src = clone->adap_fd_src;
|
||||
int i, j;
|
||||
int rc = 0;
|
||||
bool found;
|
||||
LIST_HEAD(sidecar);
|
||||
|
||||
pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu adap_fd_src=%d\n",
|
||||
__func__, ctxid_src, ctxid_dst, adap_fd_src);
|
||||
pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu\n",
|
||||
__func__, ctxid_src, ctxid_dst);
|
||||
|
||||
/* Do not clone yourself */
|
||||
if (unlikely(rctxid_src == rctxid_dst)) {
|
||||
@ -1166,13 +1165,6 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(adap_fd_src != ctxi_src->lfd)) {
|
||||
pr_debug("%s: Invalid source adapter fd! (%d)\n",
|
||||
__func__, adap_fd_src);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Verify there is no open resource handle in the destination context */
|
||||
for (i = 0; i < MAX_RHT_PER_CONTEXT; i++)
|
||||
if (ctxi_dst->rht_start[i].nmask != 0) {
|
||||
@ -1257,7 +1249,6 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
|
||||
|
||||
out_success:
|
||||
list_splice(&sidecar, &ctxi_dst->luns);
|
||||
sys_close(adap_fd_src);
|
||||
|
||||
/* fall through */
|
||||
out:
|
||||
|
@ -583,6 +583,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
|
||||
sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n",
|
||||
ALUA_DH_NAME);
|
||||
scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
|
||||
kfree(buff);
|
||||
return err;
|
||||
}
|
||||
sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n",
|
||||
|
@ -1,447 +0,0 @@
|
||||
/*
|
||||
* DTC 3180/3280 driver, by
|
||||
* Ray Van Tassle rayvt@comm.mot.com
|
||||
*
|
||||
* taken from ...
|
||||
* Trantor T128/T128F/T228 driver by...
|
||||
*
|
||||
* Drew Eckhardt
|
||||
* Visionary Computing
|
||||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 440-4894
|
||||
*/
|
||||
|
||||
/*
|
||||
* The card is detected and initialized in one of several ways :
|
||||
* 1. Autoprobe (default) - since the board is memory mapped,
|
||||
* a BIOS signature is scanned for to locate the registers.
|
||||
* An interrupt is triggered to autoprobe for the interrupt
|
||||
* line.
|
||||
*
|
||||
* 2. With command line overrides - dtc=address,irq may be
|
||||
* used on the LILO command line to override the defaults.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/* the following will set the monitor border color (useful to find
|
||||
where something crashed or gets stuck at */
|
||||
/* 1 = blue
|
||||
2 = green
|
||||
3 = cyan
|
||||
4 = red
|
||||
5 = magenta
|
||||
6 = yellow
|
||||
7 = white
|
||||
*/
|
||||
#if 0
|
||||
#define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
|
||||
#else
|
||||
#define rtrc(i) {}
|
||||
#endif
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include "dtc.h"
|
||||
#include "NCR5380.h"
|
||||
|
||||
/*
|
||||
* The DTC3180 & 3280 boards are memory mapped.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
/* Offset from DTC_5380_OFFSET */
|
||||
#define DTC_CONTROL_REG 0x100 /* rw */
|
||||
#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */
|
||||
#define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */
|
||||
|
||||
#define CSR_RESET 0x80 /* wo Resets 53c400 */
|
||||
#define CSR_5380_REG 0x80 /* ro 5380 registers can be accessed */
|
||||
#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
|
||||
#define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */
|
||||
#define CSR_5380_INTR 0x10 /* rw Enable 5380 interrupts */
|
||||
#define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */
|
||||
#define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Host buffer not ready */
|
||||
#define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer ready */
|
||||
#define CSR_GATED_5380_IRQ 0x01 /* ro Last block xferred */
|
||||
#define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
|
||||
|
||||
|
||||
#define DTC_BLK_CNT 0x101 /* rw
|
||||
* # of 128-byte blocks to transfer */
|
||||
|
||||
|
||||
#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */
|
||||
|
||||
#define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */
|
||||
#define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer
|
||||
* after disconnect/reconnect*/
|
||||
|
||||
#define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */
|
||||
|
||||
/*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
|
||||
#define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */
|
||||
|
||||
static struct override {
|
||||
unsigned int address;
|
||||
int irq;
|
||||
} overrides
|
||||
#ifdef OVERRIDE
|
||||
[] __initdata = OVERRIDE;
|
||||
#else
|
||||
[4] __initdata = {
|
||||
{ 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }
|
||||
};
|
||||
#endif
|
||||
|
||||
#define NO_OVERRIDES ARRAY_SIZE(overrides)
|
||||
|
||||
static struct base {
|
||||
unsigned long address;
|
||||
int noauto;
|
||||
} bases[] __initdata = {
|
||||
{ 0xcc000, 0 },
|
||||
{ 0xc8000, 0 },
|
||||
{ 0xdc000, 0 },
|
||||
{ 0xd8000, 0 }
|
||||
};
|
||||
|
||||
#define NO_BASES ARRAY_SIZE(bases)
|
||||
|
||||
static const struct signature {
|
||||
const char *string;
|
||||
int offset;
|
||||
} signatures[] = {
|
||||
{"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
|
||||
};
|
||||
|
||||
#define NO_SIGNATURES ARRAY_SIZE(signatures)
|
||||
|
||||
#ifndef MODULE
|
||||
/*
|
||||
* Function : dtc_setup(char *str, int *ints)
|
||||
*
|
||||
* Purpose : LILO command line initialization of the overrides array,
|
||||
*
|
||||
* Inputs : str - unused, ints - array of integer parameters with ints[0]
|
||||
* equal to the number of ints.
|
||||
*
|
||||
*/
|
||||
|
||||
static int __init dtc_setup(char *str)
|
||||
{
|
||||
static int commandline_current;
|
||||
int i;
|
||||
int ints[10];
|
||||
|
||||
get_options(str, ARRAY_SIZE(ints), ints);
|
||||
if (ints[0] != 2)
|
||||
printk("dtc_setup: usage dtc=address,irq\n");
|
||||
else if (commandline_current < NO_OVERRIDES) {
|
||||
overrides[commandline_current].address = ints[1];
|
||||
overrides[commandline_current].irq = ints[2];
|
||||
for (i = 0; i < NO_BASES; ++i)
|
||||
if (bases[i].address == ints[1]) {
|
||||
bases[i].noauto = 1;
|
||||
break;
|
||||
}
|
||||
++commandline_current;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("dtc=", dtc_setup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function : int dtc_detect(struct scsi_host_template * tpnt)
|
||||
*
|
||||
* Purpose : detects and initializes DTC 3180/3280 controllers
|
||||
* that were autoprobed, overridden on the LILO command line,
|
||||
* or specified at compile time.
|
||||
*
|
||||
* Inputs : tpnt - template for this SCSI adapter.
|
||||
*
|
||||
* Returns : 1 if a host adapter was found, 0 if not.
|
||||
*
|
||||
*/
|
||||
|
||||
static int __init dtc_detect(struct scsi_host_template * tpnt)
|
||||
{
|
||||
static int current_override, current_base;
|
||||
struct Scsi_Host *instance;
|
||||
unsigned int addr;
|
||||
void __iomem *base;
|
||||
int sig, count;
|
||||
|
||||
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
|
||||
addr = 0;
|
||||
base = NULL;
|
||||
|
||||
if (overrides[current_override].address) {
|
||||
addr = overrides[current_override].address;
|
||||
base = ioremap(addr, 0x2000);
|
||||
if (!base)
|
||||
addr = 0;
|
||||
} else
|
||||
for (; !addr && (current_base < NO_BASES); ++current_base) {
|
||||
dprintk(NDEBUG_INIT, "dtc: probing address 0x%08x\n",
|
||||
(unsigned int)bases[current_base].address);
|
||||
if (bases[current_base].noauto)
|
||||
continue;
|
||||
base = ioremap(bases[current_base].address, 0x2000);
|
||||
if (!base)
|
||||
continue;
|
||||
for (sig = 0; sig < NO_SIGNATURES; ++sig) {
|
||||
if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
|
||||
addr = bases[current_base].address;
|
||||
dprintk(NDEBUG_INIT, "dtc: detected board\n");
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
iounmap(base);
|
||||
}
|
||||
|
||||
dprintk(NDEBUG_INIT, "dtc: addr = 0x%08x\n", addr);
|
||||
|
||||
if (!addr)
|
||||
break;
|
||||
|
||||
found:
|
||||
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if (instance == NULL)
|
||||
goto out_unmap;
|
||||
|
||||
instance->base = addr;
|
||||
((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
|
||||
|
||||
if (NCR5380_init(instance, FLAG_LATE_DMA_SETUP))
|
||||
goto out_unregister;
|
||||
|
||||
NCR5380_maybe_reset_bus(instance);
|
||||
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
|
||||
if (overrides[current_override].irq != IRQ_AUTO)
|
||||
instance->irq = overrides[current_override].irq;
|
||||
else
|
||||
instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
|
||||
|
||||
/* Compatibility with documented NCR5380 kernel parameters */
|
||||
if (instance->irq == 255)
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
/* With interrupts enabled, it will sometimes hang when doing heavy
|
||||
* reads. So better not enable them until I finger it out. */
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
if (instance->irq != NO_IRQ)
|
||||
if (request_irq(instance->irq, dtc_intr, 0,
|
||||
"dtc", instance)) {
|
||||
printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
|
||||
instance->irq = NO_IRQ;
|
||||
}
|
||||
|
||||
if (instance->irq == NO_IRQ) {
|
||||
printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
|
||||
printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
|
||||
}
|
||||
|
||||
dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n",
|
||||
instance->host_no, instance->irq);
|
||||
|
||||
++current_override;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
out_unregister:
|
||||
scsi_unregister(instance);
|
||||
out_unmap:
|
||||
iounmap(base);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip)
|
||||
*
|
||||
* Purpose : Generates a BIOS / DOS compatible H-C-S mapping for
|
||||
* the specified device / size.
|
||||
*
|
||||
* Inputs : size = size of device in sectors (512 bytes), dev = block device
|
||||
* major / minor, ip[] = {heads, sectors, cylinders}
|
||||
*
|
||||
* Returns : always 0 (success), initializes ip
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX Most SCSI boards use this mapping, I could be incorrect. Some one
|
||||
* using hard disks on a trantor should verify that this mapping corresponds
|
||||
* to that used by the BIOS / ASPI driver by running the linux fdisk program
|
||||
* and matching the H_C_S coordinates to what DOS uses.
|
||||
*/
|
||||
|
||||
static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
|
||||
sector_t capacity, int *ip)
|
||||
{
|
||||
int size = capacity;
|
||||
|
||||
ip[0] = 64;
|
||||
ip[1] = 32;
|
||||
ip[2] = size >> 11;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Function : int NCR5380_pread (struct Scsi_Host *instance,
|
||||
* unsigned char *dst, int len)
|
||||
*
|
||||
* Purpose : Fast 5380 pseudo-dma read function, reads len bytes to
|
||||
* dst
|
||||
*
|
||||
* Inputs : dst = destination, len = length in bytes
|
||||
*
|
||||
* Returns : 0 on success, non zero on a failure such as a watchdog
|
||||
* timeout.
|
||||
*/
|
||||
|
||||
static inline int dtc_pread(struct Scsi_Host *instance,
|
||||
unsigned char *dst, int len)
|
||||
{
|
||||
unsigned char *d = dst;
|
||||
int i; /* For counting time spent in the poll-loop */
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
i = 0;
|
||||
if (instance->irq == NO_IRQ)
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
|
||||
else
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
|
||||
NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
|
||||
rtrc(1);
|
||||
while (len > 0) {
|
||||
rtrc(2);
|
||||
while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
|
||||
++i;
|
||||
rtrc(3);
|
||||
memcpy_fromio(d, hostdata->base + DTC_DATA_BUF, 128);
|
||||
d += 128;
|
||||
len -= 128;
|
||||
rtrc(7);
|
||||
/*** with int's on, it sometimes hangs after here.
|
||||
* Looks like something makes HBNR go away. */
|
||||
}
|
||||
rtrc(4);
|
||||
while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
|
||||
++i;
|
||||
rtrc(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Function : int NCR5380_pwrite (struct Scsi_Host *instance,
|
||||
* unsigned char *src, int len)
|
||||
*
|
||||
* Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
|
||||
* src
|
||||
*
|
||||
* Inputs : src = source, len = length in bytes
|
||||
*
|
||||
* Returns : 0 on success, non zero on a failure such as a watchdog
|
||||
* timeout.
|
||||
*/
|
||||
|
||||
static inline int dtc_pwrite(struct Scsi_Host *instance,
|
||||
unsigned char *src, int len)
|
||||
{
|
||||
int i;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
|
||||
if (instance->irq == NO_IRQ)
|
||||
NCR5380_write(DTC_CONTROL_REG, 0);
|
||||
else
|
||||
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
|
||||
NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
|
||||
for (i = 0; len > 0; ++i) {
|
||||
rtrc(5);
|
||||
/* Poll until the host buffer can accept data. */
|
||||
while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
|
||||
++i;
|
||||
rtrc(3);
|
||||
memcpy_toio(hostdata->base + DTC_DATA_BUF, src, 128);
|
||||
src += 128;
|
||||
len -= 128;
|
||||
}
|
||||
rtrc(4);
|
||||
while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
|
||||
++i;
|
||||
rtrc(6);
|
||||
/* Wait until the last byte has been sent to the disk */
|
||||
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
|
||||
++i;
|
||||
rtrc(7);
|
||||
/* Check for parity error here. fixme. */
|
||||
rtrc(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int dtc_dma_xfer_len(struct scsi_cmnd *cmd)
|
||||
{
|
||||
int transfersize = cmd->transfersize;
|
||||
|
||||
/* Limit transfers to 32K, for xx400 & xx406
|
||||
* pseudoDMA that transfers in 128 bytes blocks.
|
||||
*/
|
||||
if (transfersize > 32 * 1024 && cmd->SCp.this_residual &&
|
||||
!(cmd->SCp.this_residual % transfersize))
|
||||
transfersize = 32 * 1024;
|
||||
|
||||
return transfersize;
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include "NCR5380.c"
|
||||
|
||||
static int dtc_release(struct Scsi_Host *shost)
|
||||
{
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(shost);
|
||||
|
||||
if (shost->irq != NO_IRQ)
|
||||
free_irq(shost->irq, shost);
|
||||
NCR5380_exit(shost);
|
||||
scsi_unregister(shost);
|
||||
iounmap(hostdata->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.name = "DTC 3180/3280",
|
||||
.detect = dtc_detect,
|
||||
.release = dtc_release,
|
||||
.proc_name = "dtc3x80",
|
||||
.info = dtc_info,
|
||||
.queuecommand = dtc_queue_command,
|
||||
.eh_abort_handler = dtc_abort,
|
||||
.eh_bus_reset_handler = dtc_bus_reset,
|
||||
.bios_param = dtc_biosparam,
|
||||
.can_queue = 32,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 2,
|
||||
.use_clustering = DISABLE_CLUSTERING,
|
||||
.cmd_size = NCR5380_CMD_SIZE,
|
||||
.max_sectors = 128,
|
||||
};
|
||||
#include "scsi_module.c"
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* DTC controller, taken from T128 driver by...
|
||||
* Copyright 1993, Drew Eckhardt
|
||||
* Visionary Computing
|
||||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 440-4894
|
||||
*/
|
||||
|
||||
#ifndef DTC3280_H
|
||||
#define DTC3280_H
|
||||
|
||||
#define NCR5380_implementation_fields \
|
||||
void __iomem *base
|
||||
|
||||
#define DTC_address(reg) \
|
||||
(((struct NCR5380_hostdata *)shost_priv(instance))->base + DTC_5380_OFFSET + reg)
|
||||
|
||||
#define NCR5380_read(reg) (readb(DTC_address(reg)))
|
||||
#define NCR5380_write(reg, value) (writeb(value, DTC_address(reg)))
|
||||
|
||||
#define NCR5380_dma_xfer_len(instance, cmd, phase) \
|
||||
dtc_dma_xfer_len(cmd)
|
||||
#define NCR5380_dma_recv_setup dtc_pread
|
||||
#define NCR5380_dma_send_setup dtc_pwrite
|
||||
#define NCR5380_dma_residual(instance) (0)
|
||||
|
||||
#define NCR5380_intr dtc_intr
|
||||
#define NCR5380_queue_command dtc_queue_command
|
||||
#define NCR5380_abort dtc_abort
|
||||
#define NCR5380_bus_reset dtc_bus_reset
|
||||
#define NCR5380_info dtc_info
|
||||
|
||||
#define NCR5380_io_delay(x) udelay(x)
|
||||
|
||||
/* 15 12 11 10
|
||||
1001 1100 0000 0000 */
|
||||
|
||||
#define DTC_IRQS 0x9c00
|
||||
|
||||
|
||||
#endif /* DTC3280_H */
|
@ -963,10 +963,6 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a,
|
||||
|
||||
/* initialize the allocated memory */
|
||||
if (test_bit(AF_FIRST_INIT, &a->flags)) {
|
||||
memset(a->req_table, 0,
|
||||
(num_requests + num_ae_requests +
|
||||
1) * sizeof(struct esas2r_request *));
|
||||
|
||||
esas2r_targ_db_initialize(a);
|
||||
|
||||
/* prime parts of the inbound list */
|
||||
|
@ -194,7 +194,7 @@ static ssize_t write_hw(struct file *file, struct kobject *kobj,
|
||||
int length = min(sizeof(struct atto_ioctl), count);
|
||||
|
||||
if (!a->local_atto_ioctl) {
|
||||
a->local_atto_ioctl = kzalloc(sizeof(struct atto_ioctl),
|
||||
a->local_atto_ioctl = kmalloc(sizeof(struct atto_ioctl),
|
||||
GFP_KERNEL);
|
||||
if (a->local_atto_ioctl == NULL) {
|
||||
esas2r_log(ESAS2R_LOG_WARN,
|
||||
|
@ -83,6 +83,41 @@ static struct notifier_block libfcoe_notifier = {
|
||||
.notifier_call = libfcoe_device_notification,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
u32 fc_port_speed;
|
||||
#define SPEED_2000 2000
|
||||
#define SPEED_4000 4000
|
||||
#define SPEED_8000 8000
|
||||
#define SPEED_16000 16000
|
||||
#define SPEED_32000 32000
|
||||
u32 eth_port_speed;
|
||||
} fcoe_port_speed_mapping[] = {
|
||||
{ FC_PORTSPEED_1GBIT, SPEED_1000 },
|
||||
{ FC_PORTSPEED_2GBIT, SPEED_2000 },
|
||||
{ FC_PORTSPEED_4GBIT, SPEED_4000 },
|
||||
{ FC_PORTSPEED_8GBIT, SPEED_8000 },
|
||||
{ FC_PORTSPEED_10GBIT, SPEED_10000 },
|
||||
{ FC_PORTSPEED_16GBIT, SPEED_16000 },
|
||||
{ FC_PORTSPEED_20GBIT, SPEED_20000 },
|
||||
{ FC_PORTSPEED_25GBIT, SPEED_25000 },
|
||||
{ FC_PORTSPEED_32GBIT, SPEED_32000 },
|
||||
{ FC_PORTSPEED_40GBIT, SPEED_40000 },
|
||||
{ FC_PORTSPEED_50GBIT, SPEED_50000 },
|
||||
{ FC_PORTSPEED_100GBIT, SPEED_100000 },
|
||||
};
|
||||
|
||||
static inline u32 eth2fc_speed(u32 eth_port_speed)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fcoe_port_speed_mapping); i++) {
|
||||
if (fcoe_port_speed_mapping[i].eth_port_speed == eth_port_speed)
|
||||
return fcoe_port_speed_mapping[i].fc_port_speed;
|
||||
}
|
||||
|
||||
return FC_PORTSPEED_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_link_speed_update() - Update the supported and actual link speeds
|
||||
* @lport: The local port to update speeds for
|
||||
@ -126,23 +161,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
|
||||
SUPPORTED_40000baseLR4_Full))
|
||||
lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
|
||||
|
||||
switch (ecmd.base.speed) {
|
||||
case SPEED_1000:
|
||||
lport->link_speed = FC_PORTSPEED_1GBIT;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
lport->link_speed = FC_PORTSPEED_10GBIT;
|
||||
break;
|
||||
case SPEED_20000:
|
||||
lport->link_speed = FC_PORTSPEED_20GBIT;
|
||||
break;
|
||||
case SPEED_40000:
|
||||
lport->link_speed = FC_PORTSPEED_40GBIT;
|
||||
break;
|
||||
default:
|
||||
lport->link_speed = FC_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
lport->link_speed = eth2fc_speed(ecmd.base.speed);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <scsi/sas_ata.h>
|
||||
#include <scsi/libsas.h>
|
||||
|
||||
#define DRV_VERSION "v1.5"
|
||||
#define DRV_VERSION "v1.6"
|
||||
|
||||
#define HISI_SAS_MAX_PHYS 9
|
||||
#define HISI_SAS_MAX_QUEUES 32
|
||||
@ -56,6 +56,11 @@ enum dev_status {
|
||||
HISI_SAS_DEV_EH,
|
||||
};
|
||||
|
||||
enum {
|
||||
HISI_SAS_INT_ABT_CMD = 0,
|
||||
HISI_SAS_INT_ABT_DEV = 1,
|
||||
};
|
||||
|
||||
enum hisi_sas_dev_type {
|
||||
HISI_SAS_DEV_TYPE_STP = 0,
|
||||
HISI_SAS_DEV_TYPE_SSP,
|
||||
@ -89,6 +94,13 @@ struct hisi_sas_port {
|
||||
|
||||
struct hisi_sas_cq {
|
||||
struct hisi_hba *hisi_hba;
|
||||
int rd_point;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct hisi_sas_dq {
|
||||
struct hisi_hba *hisi_hba;
|
||||
int wr_point;
|
||||
int id;
|
||||
};
|
||||
|
||||
@ -146,6 +158,9 @@ struct hisi_sas_hw {
|
||||
struct hisi_sas_slot *slot);
|
||||
int (*prep_stp)(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot);
|
||||
int (*prep_abort)(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot,
|
||||
int device_id, int abort_flag, int tag_to_abort);
|
||||
int (*slot_complete)(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot, int abort);
|
||||
void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
|
||||
@ -185,6 +200,7 @@ struct hisi_hba {
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
struct hisi_sas_cq cq[HISI_SAS_MAX_QUEUES];
|
||||
struct hisi_sas_dq dq[HISI_SAS_MAX_QUEUES];
|
||||
struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS];
|
||||
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
|
||||
|
||||
|
@ -17,6 +17,10 @@
|
||||
|
||||
static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
|
||||
u8 *lun, struct hisi_sas_tmf_task *tmf);
|
||||
static int
|
||||
hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
||||
struct domain_device *device,
|
||||
int abort_flag, int tag);
|
||||
|
||||
static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
|
||||
{
|
||||
@ -93,7 +97,7 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
|
||||
slot->task = NULL;
|
||||
slot->port = NULL;
|
||||
hisi_sas_slot_index_free(hisi_hba, slot->idx);
|
||||
memset(slot, 0, sizeof(*slot));
|
||||
/* slot memory is fully zeroed when it is reused */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
|
||||
|
||||
@ -116,6 +120,14 @@ static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
|
||||
return hisi_hba->hw->prep_stp(hisi_hba, slot);
|
||||
}
|
||||
|
||||
static int hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot,
|
||||
int device_id, int abort_flag, int tag_to_abort)
|
||||
{
|
||||
return hisi_hba->hw->prep_abort(hisi_hba, slot,
|
||||
device_id, abort_flag, tag_to_abort);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will issue an abort TMF regardless of whether the
|
||||
* 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,
|
||||
return rc;
|
||||
}
|
||||
port = device->port->lldd_port;
|
||||
if (port && !port->port_attached && !tmf) {
|
||||
if (sas_protocol_ata(task->task_proto)) {
|
||||
struct task_status_struct *ts = &task->task_status;
|
||||
if (port && !port->port_attached) {
|
||||
dev_info(dev, "task prep: %s port%d not attach device\n",
|
||||
(sas_protocol_ata(task->task_proto)) ?
|
||||
"SATA/STP" : "SAS",
|
||||
device->port->id);
|
||||
|
||||
dev_info(dev,
|
||||
"task prep: SATA/STP port%d not attach device\n",
|
||||
device->port->id);
|
||||
ts->resp = SAS_TASK_COMPLETE;
|
||||
ts->stat = SAS_PHY_DOWN;
|
||||
task->task_done(task);
|
||||
} else {
|
||||
struct task_status_struct *ts = &task->task_status;
|
||||
|
||||
dev_info(dev,
|
||||
"task prep: SAS port%d does not attach device\n",
|
||||
device->port->id);
|
||||
ts->resp = SAS_TASK_UNDELIVERED;
|
||||
ts->stat = SAS_PHY_DOWN;
|
||||
task->task_done(task);
|
||||
}
|
||||
return 0;
|
||||
return SAS_PHY_DOWN;
|
||||
}
|
||||
|
||||
if (!sas_protocol_ata(task->task_proto)) {
|
||||
@ -609,6 +607,9 @@ static void hisi_sas_dev_gone(struct domain_device *device)
|
||||
dev_info(dev, "found dev[%lld:%x] is gone\n",
|
||||
sas_dev->device_id, sas_dev->dev_type);
|
||||
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_DEV, 0);
|
||||
|
||||
hisi_hba->hw->free_device(hisi_hba, sas_dev);
|
||||
device->lldd_dev = NULL;
|
||||
memset(sas_dev, 0, sizeof(*sas_dev));
|
||||
@ -728,6 +729,12 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
|
||||
break;
|
||||
}
|
||||
|
||||
if (task->task_status.resp == SAS_TASK_COMPLETE &&
|
||||
task->task_status.stat == TMF_RESP_FUNC_SUCC) {
|
||||
res = TMF_RESP_FUNC_SUCC;
|
||||
break;
|
||||
}
|
||||
|
||||
if (task->task_status.resp == SAS_TASK_COMPLETE &&
|
||||
task->task_status.stat == SAS_DATA_UNDERRUN) {
|
||||
/* no error, but return the number of bytes of
|
||||
@ -826,18 +833,22 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
||||
}
|
||||
}
|
||||
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_CMD, tag);
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
|
||||
task->task_proto & SAS_PROTOCOL_STP) {
|
||||
if (task->dev->dev_type == SAS_SATA_DEV) {
|
||||
struct hisi_slot_info *slot = task->lldd_task;
|
||||
|
||||
dev_notice(dev, "abort task: hba=%p task=%p slot=%p\n",
|
||||
hisi_hba, task, slot);
|
||||
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_DEV, 0);
|
||||
rc = TMF_RESP_FUNC_COMPLETE;
|
||||
goto out;
|
||||
}
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
|
||||
/* SMP */
|
||||
struct hisi_sas_slot *slot = task->lldd_task;
|
||||
u32 tag = slot->idx;
|
||||
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_CMD, tag);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -954,6 +965,157 @@ static int hisi_sas_query_task(struct sas_task *task)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id,
|
||||
struct sas_task *task, int abort_flag,
|
||||
int task_tag)
|
||||
{
|
||||
struct domain_device *device = task->dev;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct hisi_sas_port *port;
|
||||
struct hisi_sas_slot *slot;
|
||||
struct hisi_sas_cmd_hdr *cmd_hdr_base;
|
||||
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
|
||||
|
||||
if (!device->port)
|
||||
return -1;
|
||||
|
||||
port = device->port->lldd_port;
|
||||
|
||||
/* simply get a slot and send abort command */
|
||||
rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue,
|
||||
&dlvry_queue_slot);
|
||||
if (rc)
|
||||
goto err_out_tag;
|
||||
|
||||
slot = &hisi_hba->slot_info[slot_idx];
|
||||
memset(slot, 0, sizeof(struct hisi_sas_slot));
|
||||
|
||||
slot->idx = slot_idx;
|
||||
slot->n_elem = n_elem;
|
||||
slot->dlvry_queue = dlvry_queue;
|
||||
slot->dlvry_queue_slot = dlvry_queue_slot;
|
||||
cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue];
|
||||
slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
|
||||
slot->task = task;
|
||||
slot->port = port;
|
||||
task->lldd_task = slot;
|
||||
|
||||
memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
|
||||
|
||||
rc = hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
|
||||
abort_flag, task_tag);
|
||||
if (rc)
|
||||
goto err_out_tag;
|
||||
|
||||
/* Port structure is static for the HBA, so
|
||||
* even if the port is deformed it is ok
|
||||
* to reference.
|
||||
*/
|
||||
list_add_tail(&slot->entry, &port->list);
|
||||
spin_lock(&task->task_state_lock);
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock(&task->task_state_lock);
|
||||
|
||||
hisi_hba->slot_prep = slot;
|
||||
|
||||
sas_dev->running_req++;
|
||||
/* send abort command to our chip */
|
||||
hisi_hba->hw->start_delivery(hisi_hba);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_tag:
|
||||
hisi_sas_slot_index_free(hisi_hba, slot_idx);
|
||||
err_out:
|
||||
dev_err(dev, "internal abort task prep: failed[%d]!\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hisi_sas_internal_task_abort -- execute an internal
|
||||
* abort command for single IO command or a device
|
||||
* @hisi_hba: host controller struct
|
||||
* @device: domain device
|
||||
* @abort_flag: mode of operation, device or single IO
|
||||
* @tag: tag of IO to be aborted (only relevant to single
|
||||
* IO mode)
|
||||
*/
|
||||
static int
|
||||
hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
||||
struct domain_device *device,
|
||||
int abort_flag, int tag)
|
||||
{
|
||||
struct sas_task *task;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
int res;
|
||||
unsigned long flags;
|
||||
|
||||
if (!hisi_hba->hw->prep_abort)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
task = sas_alloc_slow_task(GFP_KERNEL);
|
||||
if (!task)
|
||||
return -ENOMEM;
|
||||
|
||||
task->dev = device;
|
||||
task->task_proto = device->tproto;
|
||||
task->task_done = hisi_sas_task_done;
|
||||
task->slow_task->timer.data = (unsigned long)task;
|
||||
task->slow_task->timer.function = hisi_sas_tmf_timedout;
|
||||
task->slow_task->timer.expires = jiffies + 20*HZ;
|
||||
add_timer(&task->slow_task->timer);
|
||||
|
||||
/* Lock as we are alloc'ing a slot, which cannot be interrupted */
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id,
|
||||
task, abort_flag, tag);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
if (res) {
|
||||
del_timer(&task->slow_task->timer);
|
||||
dev_err(dev, "internal task abort: executing internal task failed: %d\n",
|
||||
res);
|
||||
goto exit;
|
||||
}
|
||||
wait_for_completion(&task->slow_task->completion);
|
||||
res = TMF_RESP_FUNC_FAILED;
|
||||
|
||||
if (task->task_status.resp == SAS_TASK_COMPLETE &&
|
||||
task->task_status.stat == TMF_RESP_FUNC_COMPLETE) {
|
||||
res = TMF_RESP_FUNC_COMPLETE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* TMF timed out, return direct. */
|
||||
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
|
||||
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
|
||||
dev_err(dev, "internal task abort: timeout.\n");
|
||||
if (task->lldd_task) {
|
||||
struct hisi_sas_slot *slot = task->lldd_task;
|
||||
|
||||
hisi_sas_slot_task_free(hisi_hba, task, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
dev_info(dev, "internal task abort: task to dev %016llx task=%p "
|
||||
"resp: 0x%x sts 0x%x\n",
|
||||
SAS_ADDR(device->sas_addr),
|
||||
task,
|
||||
task->task_status.resp, /* 0 is complete, -1 is undelivered */
|
||||
task->task_status.stat);
|
||||
sas_free_task(task);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
|
||||
{
|
||||
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)
|
||||
|
||||
for (i = 0; i < hisi_hba->queue_count; i++) {
|
||||
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
|
||||
struct hisi_sas_dq *dq = &hisi_hba->dq[i];
|
||||
|
||||
/* Completion queue structure */
|
||||
cq->id = i;
|
||||
cq->hisi_hba = hisi_hba;
|
||||
|
||||
/* Delivery queue structure */
|
||||
dq->id = i;
|
||||
dq->hisi_hba = hisi_hba;
|
||||
|
||||
/* Delivery queue */
|
||||
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
|
||||
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)
|
||||
memset(hisi_hba->breakpoint, 0, s);
|
||||
|
||||
hisi_hba->slot_index_count = max_command_entries;
|
||||
s = hisi_hba->slot_index_count / sizeof(unsigned long);
|
||||
s = hisi_hba->slot_index_count / BITS_PER_BYTE;
|
||||
hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
|
||||
if (!hisi_hba->slot_index_tags)
|
||||
goto err_out;
|
||||
@ -1272,6 +1439,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
|
||||
&hisi_hba->queue_count))
|
||||
goto err_out;
|
||||
|
||||
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
|
||||
dev_err(dev, "No usable DMA addressing method\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hisi_hba->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(hisi_hba->regs))
|
||||
@ -1319,13 +1492,6 @@ int hisi_sas_probe(struct platform_device *pdev,
|
||||
hisi_hba = shost_priv(shost);
|
||||
platform_set_drvdata(pdev, sha);
|
||||
|
||||
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
|
||||
dev_err(dev, "No usable DMA addressing method\n");
|
||||
rc = -EIO;
|
||||
goto err_out_ha;
|
||||
}
|
||||
|
||||
phy_nr = port_nr = hisi_hba->n_phy;
|
||||
|
||||
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)
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
|
||||
__swab32(identify_buffer[0]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
|
||||
identify_buffer[2]);
|
||||
__swab32(identify_buffer[1]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
|
||||
identify_buffer[1]);
|
||||
__swab32(identify_buffer[2]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
|
||||
identify_buffer[4]);
|
||||
__swab32(identify_buffer[3]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
|
||||
identify_buffer[3]);
|
||||
__swab32(identify_buffer[4]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
|
||||
__swab32(identify_buffer[5]));
|
||||
}
|
||||
|
||||
static void init_id_frame_v1_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hisi_hba->n_phy; i++)
|
||||
config_id_frame_v1_hw(hisi_hba, i);
|
||||
}
|
||||
|
||||
static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_device *sas_dev)
|
||||
{
|
||||
@ -774,8 +766,6 @@ static int hw_init_v1_hw(struct hisi_hba *hisi_hba)
|
||||
msleep(100);
|
||||
init_reg_v1_hw(hisi_hba);
|
||||
|
||||
init_id_frame_v1_hw(hisi_hba);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -875,12 +865,13 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
|
||||
static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s)
|
||||
{
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct hisi_sas_dq *dq;
|
||||
u32 r, w;
|
||||
int queue = hisi_hba->queue;
|
||||
|
||||
while (1) {
|
||||
w = hisi_sas_read32_relaxed(hisi_hba,
|
||||
DLVRY_Q_0_WR_PTR + (queue * 0x14));
|
||||
dq = &hisi_hba->dq[queue];
|
||||
w = dq->wr_point;
|
||||
r = hisi_sas_read32_relaxed(hisi_hba,
|
||||
DLVRY_Q_0_RD_PTR + (queue * 0x14));
|
||||
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
|
||||
@ -903,10 +894,11 @@ static void start_delivery_v1_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int dlvry_queue = hisi_hba->slot_prep->dlvry_queue;
|
||||
int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot;
|
||||
struct hisi_sas_dq *dq = &hisi_hba->dq[dlvry_queue];
|
||||
|
||||
hisi_sas_write32(hisi_hba,
|
||||
DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
|
||||
++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS);
|
||||
dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
|
||||
hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
|
||||
dq->wr_point);
|
||||
}
|
||||
|
||||
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)
|
||||
struct hisi_sas_complete_v1_hdr *complete_queue =
|
||||
(struct hisi_sas_complete_v1_hdr *)
|
||||
hisi_hba->complete_hdr[queue];
|
||||
u32 irq_value, rd_point, wr_point;
|
||||
u32 irq_value, rd_point = cq->rd_point, wr_point;
|
||||
|
||||
irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
|
||||
|
||||
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
|
||||
|
||||
rd_point = hisi_sas_read32(hisi_hba,
|
||||
COMPL_Q_0_RD_PTR + (0x14 * queue));
|
||||
wr_point = hisi_sas_read32(hisi_hba,
|
||||
COMPL_Q_0_WR_PTR + (0x14 * queue));
|
||||
|
||||
@ -1600,6 +1589,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
|
||||
}
|
||||
|
||||
/* update rd_point */
|
||||
cq->rd_point = rd_point;
|
||||
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -117,6 +117,8 @@
|
||||
#define SL_CONTROL (PORT_BASE + 0x94)
|
||||
#define SL_CONTROL_NOTIFY_EN_OFF 0
|
||||
#define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF)
|
||||
#define SL_CONTROL_CTA_OFF 17
|
||||
#define SL_CONTROL_CTA_MSK (0x1 << SL_CONTROL_CTA_OFF)
|
||||
#define TX_ID_DWORD0 (PORT_BASE + 0x9c)
|
||||
#define TX_ID_DWORD1 (PORT_BASE + 0xa0)
|
||||
#define TX_ID_DWORD2 (PORT_BASE + 0xa4)
|
||||
@ -124,6 +126,9 @@
|
||||
#define TX_ID_DWORD4 (PORT_BASE + 0xaC)
|
||||
#define TX_ID_DWORD5 (PORT_BASE + 0xb0)
|
||||
#define TX_ID_DWORD6 (PORT_BASE + 0xb4)
|
||||
#define TXID_AUTO (PORT_BASE + 0xb8)
|
||||
#define TXID_AUTO_CT3_OFF 1
|
||||
#define TXID_AUTO_CT3_MSK (0x1 << TXID_AUTO_CT3_OFF)
|
||||
#define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
|
||||
#define RX_IDAF_DWORD1 (PORT_BASE + 0xc8)
|
||||
#define RX_IDAF_DWORD2 (PORT_BASE + 0xcc)
|
||||
@ -174,6 +179,10 @@
|
||||
/* HW dma structures */
|
||||
/* Delivery queue header */
|
||||
/* dw0 */
|
||||
#define CMD_HDR_ABORT_FLAG_OFF 0
|
||||
#define CMD_HDR_ABORT_FLAG_MSK (0x3 << CMD_HDR_ABORT_FLAG_OFF)
|
||||
#define CMD_HDR_ABORT_DEVICE_TYPE_OFF 2
|
||||
#define CMD_HDR_ABORT_DEVICE_TYPE_MSK (0x1 << CMD_HDR_ABORT_DEVICE_TYPE_OFF)
|
||||
#define CMD_HDR_RESP_REPORT_OFF 5
|
||||
#define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF)
|
||||
#define CMD_HDR_TLR_CTRL_OFF 6
|
||||
@ -214,6 +223,8 @@
|
||||
#define CMD_HDR_DIF_SGL_LEN_MSK (0xffff << CMD_HDR_DIF_SGL_LEN_OFF)
|
||||
#define CMD_HDR_DATA_SGL_LEN_OFF 16
|
||||
#define CMD_HDR_DATA_SGL_LEN_MSK (0xffff << CMD_HDR_DATA_SGL_LEN_OFF)
|
||||
#define CMD_HDR_ABORT_IPTT_OFF 16
|
||||
#define CMD_HDR_ABORT_IPTT_MSK (0xffff << CMD_HDR_ABORT_IPTT_OFF)
|
||||
|
||||
/* Completion header */
|
||||
/* dw0 */
|
||||
@ -221,6 +232,13 @@
|
||||
#define CMPLT_HDR_RSPNS_XFRD_MSK (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
|
||||
#define CMPLT_HDR_ERX_OFF 12
|
||||
#define CMPLT_HDR_ERX_MSK (0x1 << CMPLT_HDR_ERX_OFF)
|
||||
#define CMPLT_HDR_ABORT_STAT_OFF 13
|
||||
#define CMPLT_HDR_ABORT_STAT_MSK (0x7 << CMPLT_HDR_ABORT_STAT_OFF)
|
||||
/* abort_stat */
|
||||
#define STAT_IO_NOT_VALID 0x1
|
||||
#define STAT_IO_NO_DEVICE 0x2
|
||||
#define STAT_IO_COMPLETE 0x3
|
||||
#define STAT_IO_ABORTED 0x4
|
||||
/* dw1 */
|
||||
#define CMPLT_HDR_IPTT_OFF 0
|
||||
#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)
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
|
||||
__swab32(identify_buffer[0]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
|
||||
identify_buffer[2]);
|
||||
__swab32(identify_buffer[1]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
|
||||
identify_buffer[1]);
|
||||
__swab32(identify_buffer[2]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
|
||||
identify_buffer[4]);
|
||||
__swab32(identify_buffer[3]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
|
||||
identify_buffer[3]);
|
||||
__swab32(identify_buffer[4]));
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
|
||||
__swab32(identify_buffer[5]));
|
||||
}
|
||||
|
||||
static void init_id_frame_v2_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hisi_hba->n_phy; i++)
|
||||
config_id_frame_v2_hw(hisi_hba, i);
|
||||
}
|
||||
|
||||
static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_device *sas_dev)
|
||||
{
|
||||
@ -589,6 +599,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
|
||||
qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF;
|
||||
break;
|
||||
case SAS_SATA_DEV:
|
||||
case SAS_SATA_PENDING:
|
||||
if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
|
||||
qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF;
|
||||
else
|
||||
@ -672,9 +683,7 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
|
||||
else
|
||||
reset_val = 0x7ffff;
|
||||
|
||||
/* Disable all of the DQ */
|
||||
for (i = 0; i < HISI_SAS_MAX_QUEUES; i++)
|
||||
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
|
||||
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
|
||||
|
||||
/* Disable all of the PHYs */
|
||||
for (i = 0; i < hisi_hba->n_phy; i++) {
|
||||
@ -810,6 +819,8 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
|
||||
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
|
||||
hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2);
|
||||
hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x10);
|
||||
hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
|
||||
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)
|
||||
msleep(100);
|
||||
init_reg_v2_hw(hisi_hba);
|
||||
|
||||
init_id_frame_v2_hw(hisi_hba);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -952,14 +961,8 @@ static void start_phys_v2_hw(unsigned long data)
|
||||
|
||||
static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i;
|
||||
struct timer_list *timer = &hisi_hba->timer;
|
||||
|
||||
for (i = 0; i < hisi_hba->n_phy; i++) {
|
||||
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x6a);
|
||||
hisi_sas_phy_read32(hisi_hba, i, CHL_INT2_MSK);
|
||||
}
|
||||
|
||||
setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
|
||||
mod_timer(timer, jiffies + HZ);
|
||||
}
|
||||
@ -1010,12 +1013,13 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
|
||||
static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s)
|
||||
{
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct hisi_sas_dq *dq;
|
||||
u32 r, w;
|
||||
int queue = hisi_hba->queue;
|
||||
|
||||
while (1) {
|
||||
w = hisi_sas_read32_relaxed(hisi_hba,
|
||||
DLVRY_Q_0_WR_PTR + (queue * 0x14));
|
||||
dq = &hisi_hba->dq[queue];
|
||||
w = dq->wr_point;
|
||||
r = hisi_sas_read32_relaxed(hisi_hba,
|
||||
DLVRY_Q_0_RD_PTR + (queue * 0x14));
|
||||
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
|
||||
@ -1038,9 +1042,11 @@ static void start_delivery_v2_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int dlvry_queue = hisi_hba->slot_prep->dlvry_queue;
|
||||
int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot;
|
||||
struct hisi_sas_dq *dq = &hisi_hba->dq[dlvry_queue];
|
||||
|
||||
dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
|
||||
hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
|
||||
++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS);
|
||||
dq->wr_point);
|
||||
}
|
||||
|
||||
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,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Use SAS+TMF status codes */
|
||||
switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK)
|
||||
>> CMPLT_HDR_ABORT_STAT_OFF) {
|
||||
case STAT_IO_ABORTED:
|
||||
/* this io has been aborted by abort command */
|
||||
ts->stat = SAS_ABORTED_TASK;
|
||||
goto out;
|
||||
case STAT_IO_COMPLETE:
|
||||
/* internal abort command complete */
|
||||
ts->stat = TMF_RESP_FUNC_COMPLETE;
|
||||
goto out;
|
||||
case STAT_IO_NO_DEVICE:
|
||||
ts->stat = TMF_RESP_FUNC_COMPLETE;
|
||||
goto out;
|
||||
case STAT_IO_NOT_VALID:
|
||||
/* abort single io, controller don't find
|
||||
* the io need to abort
|
||||
*/
|
||||
ts->stat = TMF_RESP_FUNC_FAILED;
|
||||
goto out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) &&
|
||||
(!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
|
||||
|
||||
@ -1775,6 +1805,32 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot,
|
||||
int device_id, int abort_flag, int tag_to_abort)
|
||||
{
|
||||
struct sas_task *task = slot->task;
|
||||
struct domain_device *dev = task->dev;
|
||||
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
|
||||
struct hisi_sas_port *port = slot->port;
|
||||
|
||||
/* dw0 */
|
||||
hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
|
||||
(port->id << CMD_HDR_PORT_OFF) |
|
||||
((dev_is_sata(dev) ? 1:0) <<
|
||||
CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
|
||||
(abort_flag << CMD_HDR_ABORT_FLAG_OFF));
|
||||
|
||||
/* dw1 */
|
||||
hdr->dw1 = cpu_to_le32(device_id << CMD_HDR_DEV_ID_OFF);
|
||||
|
||||
/* dw7 */
|
||||
hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
|
||||
hdr->transfer_tags = cpu_to_le32(slot->idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i, res = 0;
|
||||
@ -1818,9 +1874,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
frame_rcvd[i] = __swab32(idaf);
|
||||
}
|
||||
|
||||
/* Get the linkrates */
|
||||
link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
|
||||
link_rate = (link_rate >> (phy_no * 4)) & 0xf;
|
||||
sas_phy->linkrate = link_rate;
|
||||
hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
|
||||
HARD_PHY_LINKRATE);
|
||||
@ -1855,16 +1908,21 @@ end:
|
||||
static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int res = 0;
|
||||
u32 phy_cfg, phy_state;
|
||||
u32 phy_state, sl_ctrl, txid_auto;
|
||||
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
|
||||
|
||||
phy_cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
|
||||
|
||||
phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
|
||||
|
||||
hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0);
|
||||
|
||||
sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL,
|
||||
sl_ctrl & ~SL_CONTROL_CTA_MSK);
|
||||
|
||||
txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
|
||||
txid_auto | TXID_AUTO_CT3_MSK);
|
||||
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
|
||||
|
||||
@ -1986,7 +2044,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
|
||||
struct hisi_sas_slot *slot;
|
||||
struct hisi_sas_itct *itct;
|
||||
struct hisi_sas_complete_v2_hdr *complete_queue;
|
||||
u32 irq_value, rd_point, wr_point, dev_id;
|
||||
u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id;
|
||||
int queue = cq->id;
|
||||
|
||||
complete_queue = hisi_hba->complete_hdr[queue];
|
||||
@ -1994,8 +2052,6 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
|
||||
|
||||
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
|
||||
|
||||
rd_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_RD_PTR +
|
||||
(0x14 * queue));
|
||||
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
|
||||
(0x14 * queue));
|
||||
|
||||
@ -2043,6 +2099,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
|
||||
}
|
||||
|
||||
/* update rd_point */
|
||||
cq->rd_point = rd_point;
|
||||
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -2239,6 +2296,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
|
||||
.prep_smp = prep_smp_v2_hw,
|
||||
.prep_ssp = prep_ssp_v2_hw,
|
||||
.prep_stp = prep_ata_v2_hw,
|
||||
.prep_abort = prep_abort_v2_hw,
|
||||
.get_free_slot = get_free_slot_v2_hw,
|
||||
.start_delivery = start_delivery_v2_hw,
|
||||
.slot_complete = slot_complete_v2_hw,
|
||||
|
@ -246,10 +246,6 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
|
||||
|
||||
shost->dma_dev = dma_dev;
|
||||
|
||||
error = device_add(&shost->shost_gendev);
|
||||
if (error)
|
||||
goto out_destroy_freelist;
|
||||
|
||||
/*
|
||||
* Increase usage count temporarily here so that calling
|
||||
* 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,
|
||||
pm_runtime_enable(&shost->shost_gendev);
|
||||
device_enable_async_suspend(&shost->shost_gendev);
|
||||
|
||||
error = device_add(&shost->shost_gendev);
|
||||
if (error)
|
||||
goto out_destroy_freelist;
|
||||
|
||||
scsi_host_set_state(shost, SHOST_RUNNING);
|
||||
get_device(shost->shost_gendev.parent);
|
||||
|
||||
@ -309,6 +309,10 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
|
||||
out_del_gendev:
|
||||
device_del(&shost->shost_gendev);
|
||||
out_destroy_freelist:
|
||||
device_disable_async_suspend(&shost->shost_gendev);
|
||||
pm_runtime_disable(&shost->shost_gendev);
|
||||
pm_runtime_set_suspended(&shost->shost_gendev);
|
||||
pm_runtime_put_noidle(&shost->shost_gendev);
|
||||
scsi_destroy_command_freelist(shost);
|
||||
out_destroy_tags:
|
||||
if (shost_use_blk_mq(shost))
|
||||
|
@ -293,6 +293,8 @@ static int detect_controller_lockup(struct ctlr_info *h);
|
||||
static void hpsa_disable_rld_caching(struct ctlr_info *h);
|
||||
static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
|
||||
struct ReportExtendedLUNdata *buf, int bufsize);
|
||||
static bool hpsa_vpd_page_supported(struct ctlr_info *h,
|
||||
unsigned char scsi3addr[], u8 page);
|
||||
static int hpsa_luns_changed(struct ctlr_info *h);
|
||||
static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c,
|
||||
struct hpsa_scsi_dev_t *dev,
|
||||
@ -2388,7 +2390,8 @@ static void hpsa_cmd_free_and_done(struct ctlr_info *h,
|
||||
struct CommandList *c, struct scsi_cmnd *cmd)
|
||||
{
|
||||
hpsa_cmd_resolve_and_free(h, c);
|
||||
cmd->scsi_done(cmd);
|
||||
if (cmd && cmd->scsi_done)
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c)
|
||||
@ -2489,7 +2492,17 @@ static void complete_scsi_command(struct CommandList *cp)
|
||||
ei = cp->err_info;
|
||||
cmd = cp->scsi_cmd;
|
||||
h = cp->h;
|
||||
|
||||
if (!cmd->device) {
|
||||
cmd->result = DID_NO_CONNECT << 16;
|
||||
return hpsa_cmd_free_and_done(h, cp, cmd);
|
||||
}
|
||||
|
||||
dev = cmd->device->hostdata;
|
||||
if (!dev) {
|
||||
cmd->result = DID_NO_CONNECT << 16;
|
||||
return hpsa_cmd_free_and_done(h, cp, cmd);
|
||||
}
|
||||
c2 = &h->ioaccel2_cmd_pool[cp->cmdindex];
|
||||
|
||||
scsi_dma_unmap(cmd); /* undo the DMA mappings */
|
||||
@ -2504,8 +2517,15 @@ static void complete_scsi_command(struct CommandList *cp)
|
||||
cmd->result = (DID_OK << 16); /* host byte */
|
||||
cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
|
||||
|
||||
if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1)
|
||||
atomic_dec(&cp->phys_disk->ioaccel_cmds_out);
|
||||
if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1) {
|
||||
if (dev->physical_device && dev->expose_device &&
|
||||
dev->removed) {
|
||||
cmd->result = DID_NO_CONNECT << 16;
|
||||
return hpsa_cmd_free_and_done(h, cp, cmd);
|
||||
}
|
||||
if (likely(cp->phys_disk != NULL))
|
||||
atomic_dec(&cp->phys_disk->ioaccel_cmds_out);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
buf = kzalloc(64, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0xC1, buf, 64);
|
||||
|
||||
if (!hpsa_vpd_page_supported(h, scsi3addr,
|
||||
HPSA_VPD_LV_DEVICE_GEOMETRY))
|
||||
goto exit;
|
||||
|
||||
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE |
|
||||
HPSA_VPD_LV_DEVICE_GEOMETRY, buf, 64);
|
||||
|
||||
if (rc == 0)
|
||||
*raid_level = buf[8];
|
||||
if (*raid_level > RAID_UNKNOWN)
|
||||
*raid_level = RAID_UNKNOWN;
|
||||
exit:
|
||||
kfree(buf);
|
||||
return;
|
||||
}
|
||||
@ -3436,7 +3464,7 @@ static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr,
|
||||
}
|
||||
|
||||
/* Get a device id from inquiry page 0x83 */
|
||||
static int hpsa_vpd_page_supported(struct ctlr_info *h,
|
||||
static bool hpsa_vpd_page_supported(struct ctlr_info *h,
|
||||
unsigned char scsi3addr[], u8 page)
|
||||
{
|
||||
int rc;
|
||||
@ -3446,7 +3474,7 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h,
|
||||
|
||||
buf = kzalloc(256, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* Get the size of the page list first */
|
||||
rc = hpsa_scsi_do_inquiry(h, scsi3addr,
|
||||
@ -3473,10 +3501,10 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h,
|
||||
goto exit_supported;
|
||||
exit_unsupported:
|
||||
kfree(buf);
|
||||
return 0;
|
||||
return false;
|
||||
exit_supported:
|
||||
kfree(buf);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
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,
|
||||
int rc;
|
||||
unsigned char *buf;
|
||||
|
||||
if (buflen > 16)
|
||||
buflen = 16;
|
||||
/* Does controller have VPD for device id? */
|
||||
if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_DEVICE_ID))
|
||||
return 1; /* not supported */
|
||||
|
||||
buf = kzalloc(64, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64);
|
||||
if (rc == 0)
|
||||
memcpy(device_id, &buf[index], buflen);
|
||||
|
||||
rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE |
|
||||
HPSA_VPD_LV_DEVICE_ID, buf, 64);
|
||||
if (rc == 0) {
|
||||
if (buflen > 16)
|
||||
buflen = 16;
|
||||
memcpy(device_id, &buf[8], buflen);
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return rc != 0;
|
||||
return rc; /*0 - got id, otherwise, didn't */
|
||||
}
|
||||
|
||||
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,
|
||||
sizeof(this_device->model));
|
||||
memset(this_device->device_id, 0,
|
||||
sizeof(this_device->device_id));
|
||||
hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
|
||||
sizeof(this_device->device_id));
|
||||
if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
|
||||
sizeof(this_device->device_id)))
|
||||
dev_err(&h->pdev->dev,
|
||||
"hpsa%d: %s: can't get device id for host %d:C0:T%d:L%d\t%s\t%.16s\n",
|
||||
h->ctlr, __func__,
|
||||
h->scsi_host->host_no,
|
||||
this_device->target, this_device->lun,
|
||||
scsi_device_type(this_device->devtype),
|
||||
this_device->model);
|
||||
|
||||
if ((this_device->devtype == TYPE_DISK ||
|
||||
this_device->devtype == TYPE_ZBC) &&
|
||||
@ -4034,7 +4076,17 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
|
||||
struct bmic_identify_physical_device *id_phys)
|
||||
{
|
||||
int rc;
|
||||
struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
|
||||
struct ext_report_lun_entry *rle;
|
||||
|
||||
/*
|
||||
* external targets don't support BMIC
|
||||
*/
|
||||
if (dev->external) {
|
||||
dev->queue_depth = 7;
|
||||
return;
|
||||
}
|
||||
|
||||
rle = &rlep->LUN[rle_index];
|
||||
|
||||
dev->ioaccel_handle = rle->ioaccel_handle;
|
||||
if ((rle->device_flags & 0x08) && dev->ioaccel_handle)
|
||||
@ -4270,6 +4322,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
|
||||
lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
|
||||
i, nphysicals, nlogicals, physdev_list, logdev_list);
|
||||
|
||||
/* Determine if this is a lun from an external target array */
|
||||
tmpdevice->external =
|
||||
figure_external_status(h, raid_ctlr_position, i,
|
||||
nphysicals, nlocal_logicals);
|
||||
|
||||
/*
|
||||
* Skip over some devices such as a spare.
|
||||
*/
|
||||
@ -4295,11 +4352,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine if this is a lun from an external target array */
|
||||
tmpdevice->external =
|
||||
figure_external_status(h, raid_ctlr_position, i,
|
||||
nphysicals, nlocal_logicals);
|
||||
|
||||
figure_bus_target_lun(h, lunaddrbytes, tmpdevice);
|
||||
hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes);
|
||||
this_device = currentsd[ncurrent];
|
||||
@ -4513,7 +4565,9 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)
|
||||
case READ_6:
|
||||
case READ_12:
|
||||
if (*cdb_len == 6) {
|
||||
block = get_unaligned_be16(&cdb[2]);
|
||||
block = (((cdb[1] & 0x1F) << 16) |
|
||||
(cdb[2] << 8) |
|
||||
cdb[3]);
|
||||
block_cnt = cdb[4];
|
||||
if (block_cnt == 0)
|
||||
block_cnt = 256;
|
||||
@ -4638,6 +4692,9 @@ static int hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h,
|
||||
struct scsi_cmnd *cmd = c->scsi_cmd;
|
||||
struct hpsa_scsi_dev_t *dev = cmd->device->hostdata;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
c->phys_disk = dev;
|
||||
|
||||
return hpsa_scsi_ioaccel_queue_command(h, c, dev->ioaccel_handle,
|
||||
@ -4670,9 +4727,11 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h,
|
||||
*/
|
||||
switch (cmd->cmnd[0]) {
|
||||
/* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */
|
||||
case WRITE_6:
|
||||
case READ_6:
|
||||
first_block = get_unaligned_be16(&cmd->cmnd[2]);
|
||||
case WRITE_6:
|
||||
first_block = (((cmd->cmnd[1] & 0x1F) << 16) |
|
||||
(cmd->cmnd[2] << 8) |
|
||||
cmd->cmnd[3]);
|
||||
break;
|
||||
case WRITE_10:
|
||||
case READ_10:
|
||||
@ -4714,6 +4773,12 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
|
||||
u32 len;
|
||||
u32 total_len = 0;
|
||||
|
||||
if (!cmd->device)
|
||||
return -1;
|
||||
|
||||
if (!cmd->device->hostdata)
|
||||
return -1;
|
||||
|
||||
BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
|
||||
|
||||
if (fixup_ioaccel_cdb(cdb, &cdb_len)) {
|
||||
@ -4822,6 +4887,12 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
|
||||
struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
|
||||
u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk)
|
||||
{
|
||||
if (!c->scsi_cmd->device)
|
||||
return -1;
|
||||
|
||||
if (!c->scsi_cmd->device->hostdata)
|
||||
return -1;
|
||||
|
||||
/* Try to honor the device's queue depth */
|
||||
if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) >
|
||||
phys_disk->queue_depth) {
|
||||
@ -4902,12 +4973,17 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
|
||||
#endif
|
||||
int offload_to_mirror;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
/* check for valid opcode, get LBA and block count */
|
||||
switch (cmd->cmnd[0]) {
|
||||
case WRITE_6:
|
||||
is_write = 1;
|
||||
case READ_6:
|
||||
first_block = get_unaligned_be16(&cmd->cmnd[2]);
|
||||
first_block = (((cmd->cmnd[1] & 0x1F) << 16) |
|
||||
(cmd->cmnd[2] << 8) |
|
||||
cmd->cmnd[3]);
|
||||
block_cnt = cmd->cmnd[4];
|
||||
if (block_cnt == 0)
|
||||
block_cnt = 256;
|
||||
@ -5314,6 +5390,9 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h,
|
||||
struct hpsa_scsi_dev_t *dev = cmd->device->hostdata;
|
||||
int rc = IO_ACCEL_INELIGIBLE;
|
||||
|
||||
if (!dev)
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
||||
cmd->host_scribble = (unsigned char *) c;
|
||||
|
||||
if (dev->offload_enabled) {
|
||||
@ -5852,6 +5931,9 @@ static void setup_ioaccel2_abort_cmd(struct CommandList *c, struct ctlr_info *h,
|
||||
struct scsi_cmnd *scmd = command_to_abort->scsi_cmd;
|
||||
struct hpsa_scsi_dev_t *dev = scmd->device->hostdata;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We're overlaying struct hpsa_tmf_struct on top of something which
|
||||
* 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,
|
||||
"Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
psa[0], psa[1], psa[2], psa[3],
|
||||
psa[4], psa[5], psa[6], psa[7]);
|
||||
rc = hpsa_do_reset(h, dev, psa, HPSA_RESET_TYPE_TARGET, reply_queue);
|
||||
rc = hpsa_do_reset(h, dev, psa, HPSA_PHYS_TARGET_RESET, reply_queue);
|
||||
if (rc != 0) {
|
||||
dev_warn(&h->pdev->dev,
|
||||
"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,
|
||||
struct io_accel2_cmd *c2;
|
||||
|
||||
dev = abort->scsi_cmd->device->hostdata;
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
if (!dev->offload_enabled && !dev->hba_ioaccel_enabled)
|
||||
return -1;
|
||||
|
||||
|
@ -312,7 +312,6 @@ struct offline_device_entry {
|
||||
#define HPSA_DEVICE_RESET_MSG 1
|
||||
#define HPSA_RESET_TYPE_CONTROLLER 0x00
|
||||
#define HPSA_RESET_TYPE_BUS 0x01
|
||||
#define HPSA_RESET_TYPE_TARGET 0x03
|
||||
#define HPSA_RESET_TYPE_LUN 0x04
|
||||
#define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */
|
||||
#define HPSA_MSG_SEND_RETRY_LIMIT 10
|
||||
|
@ -157,6 +157,7 @@
|
||||
|
||||
/* VPD Inquiry types */
|
||||
#define HPSA_VPD_SUPPORTED_PAGES 0x00
|
||||
#define HPSA_VPD_LV_DEVICE_ID 0x83
|
||||
#define HPSA_VPD_LV_DEVICE_GEOMETRY 0xC1
|
||||
#define HPSA_VPD_LV_IOACCEL_STATUS 0xC2
|
||||
#define HPSA_VPD_LV_STATUS 0xC3
|
||||
|
@ -52,6 +52,7 @@ static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
|
||||
static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
|
||||
static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
|
||||
static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
|
||||
static unsigned int cls3_error = IBMVFC_CLS3_ERROR;
|
||||
static LIST_HEAD(ibmvfc_head);
|
||||
static DEFINE_SPINLOCK(ibmvfc_driver_lock);
|
||||
static struct scsi_transport_template *ibmvfc_transport_template;
|
||||
@ -86,6 +87,9 @@ MODULE_PARM_DESC(debug, "Enable driver debug information. "
|
||||
module_param_named(log_level, log_level, uint, 0);
|
||||
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
|
||||
"[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]");
|
||||
module_param_named(cls3_error, cls3_error, uint, 0);
|
||||
MODULE_PARM_DESC(cls3_error, "Enable FC Class 3 Error Recovery. "
|
||||
"[Default=" __stringify(IBMVFC_CLS3_ERROR) "]");
|
||||
|
||||
static const struct {
|
||||
u16 status;
|
||||
@ -717,7 +721,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
|
||||
spin_lock_irqsave(vhost->host->host_lock, flags);
|
||||
vhost->state = IBMVFC_NO_CRQ;
|
||||
vhost->logged_in = 0;
|
||||
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
|
||||
|
||||
/* Clean out the queue */
|
||||
memset(crq->msgs, 0, PAGE_SIZE);
|
||||
@ -1335,6 +1338,9 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
|
||||
struct srp_direct_buf *data = &vfc_cmd->ioba;
|
||||
struct ibmvfc_host *vhost = dev_get_drvdata(dev);
|
||||
|
||||
if (cls3_error)
|
||||
vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR);
|
||||
|
||||
sg_mapped = scsi_dma_map(scmd);
|
||||
if (!sg_mapped) {
|
||||
vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC);
|
||||
@ -3381,6 +3387,10 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
|
||||
prli->parms.type = IBMVFC_SCSI_FCP_TYPE;
|
||||
prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR);
|
||||
prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC);
|
||||
prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED);
|
||||
|
||||
if (cls3_error)
|
||||
prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_RETRY);
|
||||
|
||||
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
|
||||
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
|
||||
|
@ -54,6 +54,7 @@
|
||||
#define IBMVFC_DEV_LOSS_TMO (5 * 60)
|
||||
#define IBMVFC_DEFAULT_LOG_LEVEL 2
|
||||
#define IBMVFC_MAX_CDB_LEN 16
|
||||
#define IBMVFC_CLS3_ERROR 0
|
||||
|
||||
/*
|
||||
* Ensure we have resources for ERP and initialization:
|
||||
|
@ -1606,8 +1606,6 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
|
||||
|
||||
if (!(vscsi->flags & RESPONSE_Q_DOWN)) {
|
||||
list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) {
|
||||
pr_debug("send_messages cmd %p\n", cmd);
|
||||
|
||||
iue = cmd->iue;
|
||||
|
||||
crq->valid = VALID_CMD_RESP_EL;
|
||||
@ -1934,6 +1932,8 @@ static int ibmvscsis_drop_nexus(struct ibmvscsis_tport *tport)
|
||||
/*
|
||||
* Release the SCSI I_T Nexus to the emulated ibmvscsis Target Port
|
||||
*/
|
||||
target_wait_for_sess_cmds(se_sess);
|
||||
transport_deregister_session_configfs(se_sess);
|
||||
transport_deregister_session(se_sess);
|
||||
tport->ibmv_nexus = NULL;
|
||||
kfree(nexus);
|
||||
@ -1978,7 +1978,7 @@ static long ibmvscsis_srp_login(struct scsi_info *vscsi,
|
||||
reason = SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED;
|
||||
else if (fmt->buffers & (~SUPPORTED_FORMATS))
|
||||
reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT;
|
||||
else if ((fmt->buffers | SUPPORTED_FORMATS) == 0)
|
||||
else if ((fmt->buffers & SUPPORTED_FORMATS) == 0)
|
||||
reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT;
|
||||
|
||||
if (vscsi->state == SRP_PROCESSING)
|
||||
@ -2554,10 +2554,6 @@ static void ibmvscsis_parse_cmd(struct scsi_info *vscsi,
|
||||
|
||||
srp->lun.scsi_lun[0] &= 0x3f;
|
||||
|
||||
pr_debug("calling submit_cmd, se_cmd %p, lun 0x%llx, cdb 0x%x, attr:%d\n",
|
||||
&cmd->se_cmd, scsilun_to_int(&srp->lun), (int)srp->cdb[0],
|
||||
attr);
|
||||
|
||||
rc = target_submit_cmd(&cmd->se_cmd, nexus->se_sess, srp->cdb,
|
||||
cmd->sense_buf, scsilun_to_int(&srp->lun),
|
||||
data_len, attr, dir, 0);
|
||||
@ -3142,8 +3138,6 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg,
|
||||
long tx_len;
|
||||
long rc = 0;
|
||||
|
||||
pr_debug("rdma: dir %d, bytes 0x%x\n", dir, bytes);
|
||||
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
@ -3192,12 +3186,6 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg,
|
||||
vscsi->dds.window[LOCAL].liobn,
|
||||
server_ioba);
|
||||
} else {
|
||||
/* write to client */
|
||||
struct srp_cmd *srp = (struct srp_cmd *)iue->sbuf->buf;
|
||||
|
||||
if (!READ_CMD(srp->cdb))
|
||||
print_hex_dump_bytes(" data:", DUMP_PREFIX_NONE,
|
||||
sg_virt(sgp), buf_len);
|
||||
/* The h_copy_rdma will cause phyp, running in another
|
||||
* partition, to read memory, so we need to make sure
|
||||
* the data has been written out, hence these syncs.
|
||||
@ -3322,12 +3310,9 @@ cmd_work:
|
||||
rc = ibmvscsis_trans_event(vscsi, crq);
|
||||
} else if (vscsi->flags & TRANS_EVENT) {
|
||||
/*
|
||||
* if a tranport event has occurred leave
|
||||
* if a transport event has occurred leave
|
||||
* everything but transport events on the queue
|
||||
*/
|
||||
pr_debug("handle_crq, ignoring\n");
|
||||
|
||||
/*
|
||||
*
|
||||
* need to decrement the queue index so we can
|
||||
* look at the elment again
|
||||
*/
|
||||
@ -3461,6 +3446,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
|
||||
vscsi->map_ioba = dma_map_single(&vdev->dev, vscsi->map_buf, PAGE_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(&vdev->dev, vscsi->map_ioba)) {
|
||||
rc = -ENOMEM;
|
||||
dev_err(&vscsi->dev, "probe: error mapping command buffer\n");
|
||||
goto free_buf;
|
||||
}
|
||||
@ -3693,12 +3679,9 @@ static void ibmvscsis_release_cmd(struct se_cmd *se_cmd)
|
||||
se_cmd);
|
||||
struct scsi_info *vscsi = cmd->adapter;
|
||||
|
||||
pr_debug("release_cmd %p, flags %d\n", se_cmd, cmd->flags);
|
||||
|
||||
spin_lock_bh(&vscsi->intr_lock);
|
||||
/* Remove from active_q */
|
||||
list_del(&cmd->list);
|
||||
list_add_tail(&cmd->list, &vscsi->waiting_rsp);
|
||||
list_move_tail(&cmd->list, &vscsi->waiting_rsp);
|
||||
ibmvscsis_send_messages(vscsi);
|
||||
spin_unlock_bh(&vscsi->intr_lock);
|
||||
}
|
||||
@ -3715,9 +3698,6 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
|
||||
struct iu_entry *iue = cmd->iue;
|
||||
int rc;
|
||||
|
||||
pr_debug("write_pending, se_cmd %p, length 0x%x\n",
|
||||
se_cmd, se_cmd->data_length);
|
||||
|
||||
rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma,
|
||||
1, 1);
|
||||
if (rc) {
|
||||
@ -3756,9 +3736,6 @@ static int ibmvscsis_queue_data_in(struct se_cmd *se_cmd)
|
||||
uint len = 0;
|
||||
int rc;
|
||||
|
||||
pr_debug("queue_data_in, se_cmd %p, length 0x%x\n",
|
||||
se_cmd, se_cmd->data_length);
|
||||
|
||||
rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 1,
|
||||
1);
|
||||
if (rc) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,412 +0,0 @@
|
||||
/*
|
||||
* in2000.h - Linux device driver definitions for the
|
||||
* Always IN2000 ISA SCSI card.
|
||||
*
|
||||
* IMPORTANT: This file is for version 1.33 - 26/Aug/1998
|
||||
*
|
||||
* Copyright (c) 1996 John Shifflett, GeoLog Consulting
|
||||
* john@geolog.com
|
||||
* jshiffle@netcom.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IN2000_H
|
||||
#define IN2000_H
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define PROC_INTERFACE /* add code for /proc/scsi/in2000/xxx interface */
|
||||
#ifdef PROC_INTERFACE
|
||||
#define PROC_STATISTICS /* add code for keeping various real time stats */
|
||||
#endif
|
||||
|
||||
#define SYNC_DEBUG /* extra info on sync negotiation printed */
|
||||
#define DEBUGGING_ON /* enable command-line debugging bitmask */
|
||||
#define DEBUG_DEFAULTS 0 /* default bitmask - change from command-line */
|
||||
|
||||
#ifdef __i386__
|
||||
#define FAST_READ_IO /* No problems with these on my machine */
|
||||
#define FAST_WRITE_IO
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGGING_ON
|
||||
#define DB(f,a) if (hostdata->args & (f)) a;
|
||||
#define CHECK_NULL(p,s) /* if (!(p)) {printk("\n"); while (1) printk("NP:%s\r",(s));} */
|
||||
#else
|
||||
#define DB(f,a)
|
||||
#define CHECK_NULL(p,s)
|
||||
#endif
|
||||
|
||||
#define uchar unsigned char
|
||||
|
||||
#define read1_io(a) (inb(hostdata->io_base+(a)))
|
||||
#define read2_io(a) (inw(hostdata->io_base+(a)))
|
||||
#define write1_io(b,a) (outb((b),hostdata->io_base+(a)))
|
||||
#define write2_io(w,a) (outw((w),hostdata->io_base+(a)))
|
||||
|
||||
#ifdef __i386__
|
||||
/* These inline assembly defines are derived from a patch
|
||||
* sent to me by Bill Earnest. He's done a lot of very
|
||||
* valuable thinking, testing, and coding during his effort
|
||||
* to squeeze more speed out of this driver. I really think
|
||||
* that we are doing IO at close to the maximum now with
|
||||
* the fifo. (And yes, insw uses 'edi' while outsw uses
|
||||
* 'esi'. Thanks Bill!)
|
||||
*/
|
||||
|
||||
#define FAST_READ2_IO() \
|
||||
({ \
|
||||
int __dummy_1,__dummy_2; \
|
||||
__asm__ __volatile__ ("\n \
|
||||
cld \n \
|
||||
orl %%ecx, %%ecx \n \
|
||||
jz 1f \n \
|
||||
rep \n \
|
||||
insw (%%dx),%%es:(%%edi) \n \
|
||||
1: " \
|
||||
: "=D" (sp) ,"=c" (__dummy_1) ,"=d" (__dummy_2) /* output */ \
|
||||
: "2" (f), "0" (sp), "1" (i) /* input */ \
|
||||
); /* trashed */ \
|
||||
})
|
||||
|
||||
#define FAST_WRITE2_IO() \
|
||||
({ \
|
||||
int __dummy_1,__dummy_2; \
|
||||
__asm__ __volatile__ ("\n \
|
||||
cld \n \
|
||||
orl %%ecx, %%ecx \n \
|
||||
jz 1f \n \
|
||||
rep \n \
|
||||
outsw %%ds:(%%esi),(%%dx) \n \
|
||||
1: " \
|
||||
: "=S" (sp) ,"=c" (__dummy_1) ,"=d" (__dummy_2)/* output */ \
|
||||
: "2" (f), "0" (sp), "1" (i) /* input */ \
|
||||
); /* trashed */ \
|
||||
})
|
||||
#endif
|
||||
|
||||
/* IN2000 io_port offsets */
|
||||
#define IO_WD_ASR 0x00 /* R - 3393 auxstat reg */
|
||||
#define ASR_INT 0x80
|
||||
#define ASR_LCI 0x40
|
||||
#define ASR_BSY 0x20
|
||||
#define ASR_CIP 0x10
|
||||
#define ASR_PE 0x02
|
||||
#define ASR_DBR 0x01
|
||||
#define IO_WD_ADDR 0x00 /* W - 3393 address reg */
|
||||
#define IO_WD_DATA 0x01 /* R/W - rest of 3393 regs */
|
||||
#define IO_FIFO 0x02 /* R/W - in2000 dual-port fifo (16 bits) */
|
||||
#define IN2000_FIFO_SIZE 2048 /* fifo capacity in bytes */
|
||||
#define IO_CARD_RESET 0x03 /* W - in2000 start master reset */
|
||||
#define IO_FIFO_COUNT 0x04 /* R - in2000 fifo counter */
|
||||
#define IO_FIFO_WRITE 0x05 /* W - clear fifo counter, start write */
|
||||
#define IO_FIFO_READ 0x07 /* W - start fifo read */
|
||||
#define IO_LED_OFF 0x08 /* W - turn off in2000 activity LED */
|
||||
#define IO_SWITCHES 0x08 /* R - read in2000 dip switch */
|
||||
#define SW_ADDR0 0x01 /* bit 0 = bit 0 of index to io addr */
|
||||
#define SW_ADDR1 0x02 /* bit 1 = bit 1 of index io addr */
|
||||
#define SW_DISINT 0x04 /* bit 2 true if ints disabled */
|
||||
#define SW_INT0 0x08 /* bit 3 = bit 0 of index to interrupt */
|
||||
#define SW_INT1 0x10 /* bit 4 = bit 1 of index to interrupt */
|
||||
#define SW_INT_SHIFT 3 /* shift right this amount to right justify int bits */
|
||||
#define SW_SYNC_DOS5 0x20 /* bit 5 used by Always BIOS */
|
||||
#define SW_FLOPPY 0x40 /* bit 6 true if floppy enabled */
|
||||
#define SW_BIT7 0x80 /* bit 7 hardwired true (ground) */
|
||||
#define IO_LED_ON 0x09 /* W - turn on in2000 activity LED */
|
||||
#define IO_HARDWARE 0x0a /* R - read in2000 hardware rev, stop reset */
|
||||
#define IO_INTR_MASK 0x0c /* W - in2000 interrupt mask reg */
|
||||
#define IMASK_WD 0x01 /* WD33c93 interrupt mask */
|
||||
#define IMASK_FIFO 0x02 /* FIFO interrupt mask */
|
||||
|
||||
/* wd register names */
|
||||
#define WD_OWN_ID 0x00
|
||||
#define WD_CONTROL 0x01
|
||||
#define WD_TIMEOUT_PERIOD 0x02
|
||||
#define WD_CDB_1 0x03
|
||||
#define WD_CDB_2 0x04
|
||||
#define WD_CDB_3 0x05
|
||||
#define WD_CDB_4 0x06
|
||||
#define WD_CDB_5 0x07
|
||||
#define WD_CDB_6 0x08
|
||||
#define WD_CDB_7 0x09
|
||||
#define WD_CDB_8 0x0a
|
||||
#define WD_CDB_9 0x0b
|
||||
#define WD_CDB_10 0x0c
|
||||
#define WD_CDB_11 0x0d
|
||||
#define WD_CDB_12 0x0e
|
||||
#define WD_TARGET_LUN 0x0f
|
||||
#define WD_COMMAND_PHASE 0x10
|
||||
#define WD_SYNCHRONOUS_TRANSFER 0x11
|
||||
#define WD_TRANSFER_COUNT_MSB 0x12
|
||||
#define WD_TRANSFER_COUNT 0x13
|
||||
#define WD_TRANSFER_COUNT_LSB 0x14
|
||||
#define WD_DESTINATION_ID 0x15
|
||||
#define WD_SOURCE_ID 0x16
|
||||
#define WD_SCSI_STATUS 0x17
|
||||
#define WD_COMMAND 0x18
|
||||
#define WD_DATA 0x19
|
||||
#define WD_QUEUE_TAG 0x1a
|
||||
#define WD_AUXILIARY_STATUS 0x1f
|
||||
|
||||
/* WD commands */
|
||||
#define WD_CMD_RESET 0x00
|
||||
#define WD_CMD_ABORT 0x01
|
||||
#define WD_CMD_ASSERT_ATN 0x02
|
||||
#define WD_CMD_NEGATE_ACK 0x03
|
||||
#define WD_CMD_DISCONNECT 0x04
|
||||
#define WD_CMD_RESELECT 0x05
|
||||
#define WD_CMD_SEL_ATN 0x06
|
||||
#define WD_CMD_SEL 0x07
|
||||
#define WD_CMD_SEL_ATN_XFER 0x08
|
||||
#define WD_CMD_SEL_XFER 0x09
|
||||
#define WD_CMD_RESEL_RECEIVE 0x0a
|
||||
#define WD_CMD_RESEL_SEND 0x0b
|
||||
#define WD_CMD_WAIT_SEL_RECEIVE 0x0c
|
||||
#define WD_CMD_TRANS_ADDR 0x18
|
||||
#define WD_CMD_TRANS_INFO 0x20
|
||||
#define WD_CMD_TRANSFER_PAD 0x21
|
||||
#define WD_CMD_SBT_MODE 0x80
|
||||
|
||||
/* SCSI Bus Phases */
|
||||
#define PHS_DATA_OUT 0x00
|
||||
#define PHS_DATA_IN 0x01
|
||||
#define PHS_COMMAND 0x02
|
||||
#define PHS_STATUS 0x03
|
||||
#define PHS_MESS_OUT 0x06
|
||||
#define PHS_MESS_IN 0x07
|
||||
|
||||
/* Command Status Register definitions */
|
||||
|
||||
/* reset state interrupts */
|
||||
#define CSR_RESET 0x00
|
||||
#define CSR_RESET_AF 0x01
|
||||
|
||||
/* successful completion interrupts */
|
||||
#define CSR_RESELECT 0x10
|
||||
#define CSR_SELECT 0x11
|
||||
#define CSR_SEL_XFER_DONE 0x16
|
||||
#define CSR_XFER_DONE 0x18
|
||||
|
||||
/* paused or aborted interrupts */
|
||||
#define CSR_MSGIN 0x20
|
||||
#define CSR_SDP 0x21
|
||||
#define CSR_SEL_ABORT 0x22
|
||||
#define CSR_RESEL_ABORT 0x25
|
||||
#define CSR_RESEL_ABORT_AM 0x27
|
||||
#define CSR_ABORT 0x28
|
||||
|
||||
/* terminated interrupts */
|
||||
#define CSR_INVALID 0x40
|
||||
#define CSR_UNEXP_DISC 0x41
|
||||
#define CSR_TIMEOUT 0x42
|
||||
#define CSR_PARITY 0x43
|
||||
#define CSR_PARITY_ATN 0x44
|
||||
#define CSR_BAD_STATUS 0x45
|
||||
#define CSR_UNEXP 0x48
|
||||
|
||||
/* service required interrupts */
|
||||
#define CSR_RESEL 0x80
|
||||
#define CSR_RESEL_AM 0x81
|
||||
#define CSR_DISC 0x85
|
||||
#define CSR_SRV_REQ 0x88
|
||||
|
||||
/* Own ID/CDB Size register */
|
||||
#define OWNID_EAF 0x08
|
||||
#define OWNID_EHP 0x10
|
||||
#define OWNID_RAF 0x20
|
||||
#define OWNID_FS_8 0x00
|
||||
#define OWNID_FS_12 0x40
|
||||
#define OWNID_FS_16 0x80
|
||||
|
||||
/* Control register */
|
||||
#define CTRL_HSP 0x01
|
||||
#define CTRL_HA 0x02
|
||||
#define CTRL_IDI 0x04
|
||||
#define CTRL_EDI 0x08
|
||||
#define CTRL_HHP 0x10
|
||||
#define CTRL_POLLED 0x00
|
||||
#define CTRL_BURST 0x20
|
||||
#define CTRL_BUS 0x40
|
||||
#define CTRL_DMA 0x80
|
||||
|
||||
/* Timeout Period register */
|
||||
#define TIMEOUT_PERIOD_VALUE 20 /* results in 200 ms. */
|
||||
|
||||
/* Synchronous Transfer Register */
|
||||
#define STR_FSS 0x80
|
||||
|
||||
/* Destination ID register */
|
||||
#define DSTID_DPD 0x40
|
||||
#define DATA_OUT_DIR 0
|
||||
#define DATA_IN_DIR 1
|
||||
#define DSTID_SCC 0x80
|
||||
|
||||
/* Source ID register */
|
||||
#define SRCID_MASK 0x07
|
||||
#define SRCID_SIV 0x08
|
||||
#define SRCID_DSP 0x20
|
||||
#define SRCID_ES 0x40
|
||||
#define SRCID_ER 0x80
|
||||
|
||||
|
||||
|
||||
#define ILLEGAL_STATUS_BYTE 0xff
|
||||
|
||||
|
||||
#define DEFAULT_SX_PER 500 /* (ns) fairly safe */
|
||||
#define DEFAULT_SX_OFF 0 /* aka async */
|
||||
|
||||
#define OPTIMUM_SX_PER 252 /* (ns) best we can do (mult-of-4) */
|
||||
#define OPTIMUM_SX_OFF 12 /* size of in2000 fifo */
|
||||
|
||||
struct sx_period {
|
||||
unsigned int period_ns;
|
||||
uchar reg_value;
|
||||
};
|
||||
|
||||
|
||||
struct IN2000_hostdata {
|
||||
struct Scsi_Host *next;
|
||||
uchar chip; /* what kind of wd33c93 chip? */
|
||||
uchar microcode; /* microcode rev if 'B' */
|
||||
unsigned short io_base; /* IO port base */
|
||||
unsigned int dip_switch; /* dip switch settings */
|
||||
unsigned int hrev; /* hardware revision of card */
|
||||
volatile uchar busy[8]; /* index = target, bit = lun */
|
||||
volatile Scsi_Cmnd *input_Q; /* commands waiting to be started */
|
||||
volatile Scsi_Cmnd *selecting; /* trying to select this command */
|
||||
volatile Scsi_Cmnd *connected; /* currently connected command */
|
||||
volatile Scsi_Cmnd *disconnected_Q;/* commands waiting for reconnect */
|
||||
uchar state; /* what we are currently doing */
|
||||
uchar fifo; /* what the FIFO is up to */
|
||||
uchar level2; /* extent to which Level-2 commands are used */
|
||||
uchar disconnect; /* disconnect/reselect policy */
|
||||
unsigned int args; /* set from command-line argument */
|
||||
uchar incoming_msg[8]; /* filled during message_in phase */
|
||||
int incoming_ptr; /* mainly used with EXTENDED messages */
|
||||
uchar outgoing_msg[8]; /* send this during next message_out */
|
||||
int outgoing_len; /* length of outgoing message */
|
||||
unsigned int default_sx_per; /* default transfer period for SCSI bus */
|
||||
uchar sync_xfer[8]; /* sync_xfer reg settings per target */
|
||||
uchar sync_stat[8]; /* status of sync negotiation per target */
|
||||
uchar sync_off; /* bit mask: don't use sync with these targets */
|
||||
#ifdef PROC_INTERFACE
|
||||
uchar proc; /* bit mask: what's in proc output */
|
||||
#ifdef PROC_STATISTICS
|
||||
unsigned long cmd_cnt[8]; /* # of commands issued per target */
|
||||
unsigned long int_cnt; /* # of interrupts serviced */
|
||||
unsigned long disc_allowed_cnt[8]; /* # of disconnects allowed per target */
|
||||
unsigned long disc_done_cnt[8]; /* # of disconnects done per target*/
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* defines for hostdata->chip */
|
||||
|
||||
#define C_WD33C93 0
|
||||
#define C_WD33C93A 1
|
||||
#define C_WD33C93B 2
|
||||
#define C_UNKNOWN_CHIP 100
|
||||
|
||||
/* defines for hostdata->state */
|
||||
|
||||
#define S_UNCONNECTED 0
|
||||
#define S_SELECTING 1
|
||||
#define S_RUNNING_LEVEL2 2
|
||||
#define S_CONNECTED 3
|
||||
#define S_PRE_TMP_DISC 4
|
||||
#define S_PRE_CMP_DISC 5
|
||||
|
||||
/* defines for hostdata->fifo */
|
||||
|
||||
#define FI_FIFO_UNUSED 0
|
||||
#define FI_FIFO_READING 1
|
||||
#define FI_FIFO_WRITING 2
|
||||
|
||||
/* defines for hostdata->level2 */
|
||||
/* NOTE: only the first 3 are trustworthy at this point -
|
||||
* having trouble when more than 1 device is reading/writing
|
||||
* at the same time...
|
||||
*/
|
||||
|
||||
#define L2_NONE 0 /* no combination commands - we get lots of ints */
|
||||
#define L2_SELECT 1 /* start with SEL_ATN_XFER, but never resume it */
|
||||
#define L2_BASIC 2 /* resume after STATUS ints & RDP messages */
|
||||
#define L2_DATA 3 /* resume after DATA_IN/OUT ints */
|
||||
#define L2_MOST 4 /* resume after anything except a RESELECT int */
|
||||
#define L2_RESELECT 5 /* resume after everything, including RESELECT ints */
|
||||
#define L2_ALL 6 /* always resume */
|
||||
|
||||
/* defines for hostdata->disconnect */
|
||||
|
||||
#define DIS_NEVER 0
|
||||
#define DIS_ADAPTIVE 1
|
||||
#define DIS_ALWAYS 2
|
||||
|
||||
/* defines for hostdata->args */
|
||||
|
||||
#define DB_TEST 1<<0
|
||||
#define DB_FIFO 1<<1
|
||||
#define DB_QUEUE_COMMAND 1<<2
|
||||
#define DB_EXECUTE 1<<3
|
||||
#define DB_INTR 1<<4
|
||||
#define DB_TRANSFER 1<<5
|
||||
#define DB_MASK 0x3f
|
||||
|
||||
#define A_NO_SCSI_RESET 1<<15
|
||||
|
||||
|
||||
/* defines for hostdata->sync_xfer[] */
|
||||
|
||||
#define SS_UNSET 0
|
||||
#define SS_FIRST 1
|
||||
#define SS_WAITING 2
|
||||
#define SS_SET 3
|
||||
|
||||
/* defines for hostdata->proc */
|
||||
|
||||
#define PR_VERSION 1<<0
|
||||
#define PR_INFO 1<<1
|
||||
#define PR_STATISTICS 1<<2
|
||||
#define PR_CONNECTED 1<<3
|
||||
#define PR_INPUTQ 1<<4
|
||||
#define PR_DISCQ 1<<5
|
||||
#define PR_TEST 1<<6
|
||||
#define PR_STOP 1<<7
|
||||
|
||||
|
||||
# include <linux/init.h>
|
||||
# include <linux/spinlock.h>
|
||||
# define in2000__INITFUNC(function) __initfunc(function)
|
||||
# define in2000__INIT __init
|
||||
# define in2000__INITDATA __initdata
|
||||
# define CLISPIN_LOCK(host,flags) spin_lock_irqsave(host->host_lock, flags)
|
||||
# define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(host->host_lock, \
|
||||
flags)
|
||||
|
||||
static int in2000_detect(struct scsi_host_template *) in2000__INIT;
|
||||
static int in2000_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
static int in2000_abort(Scsi_Cmnd *);
|
||||
static void in2000_setup(char *, int *) in2000__INIT;
|
||||
static int in2000_biosparam(struct scsi_device *, struct block_device *,
|
||||
sector_t, int *);
|
||||
static int in2000_bus_reset(Scsi_Cmnd *);
|
||||
|
||||
|
||||
#define IN2000_CAN_Q 16
|
||||
#define IN2000_SG SG_ALL
|
||||
#define IN2000_CPL 2
|
||||
#define IN2000_HOST_ID 7
|
||||
|
||||
#endif /* IN2000_H */
|
@ -493,15 +493,15 @@ struct ipr_error_table_t ipr_error_table[] = {
|
||||
"9072: Link not operational transition"},
|
||||
{0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL,
|
||||
"9032: Array exposed but still protected"},
|
||||
{0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1,
|
||||
{0x066B8300, 0, IPR_DEBUG_LOG_LEVEL,
|
||||
"70DD: Device forced failed by disrupt device command"},
|
||||
{0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL,
|
||||
"4061: Multipath redundancy level got better"},
|
||||
{0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
|
||||
"4060: Multipath redundancy level got worse"},
|
||||
{0x06808100, 0, IPR_DEFAULT_LOG_LEVEL,
|
||||
{0x06808100, 0, IPR_DEBUG_LOG_LEVEL,
|
||||
"9083: Device raw mode enabled"},
|
||||
{0x06808200, 0, IPR_DEFAULT_LOG_LEVEL,
|
||||
{0x06808200, 0, IPR_DEBUG_LOG_LEVEL,
|
||||
"9084: Device raw mode disabled"},
|
||||
{0x07270000, 0, 0,
|
||||
"Failure due to other device"},
|
||||
@ -1473,7 +1473,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
|
||||
struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
|
||||
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
|
||||
|
||||
list_del(&hostrcb->queue);
|
||||
list_del_init(&hostrcb->queue);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
|
||||
if (ioasc) {
|
||||
@ -2552,6 +2552,23 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
|
||||
}
|
||||
}
|
||||
|
||||
static struct ipr_hostrcb *ipr_get_free_hostrcb(struct ipr_ioa_cfg *ioa)
|
||||
{
|
||||
struct ipr_hostrcb *hostrcb;
|
||||
|
||||
hostrcb = list_first_entry_or_null(&ioa->hostrcb_free_q,
|
||||
struct ipr_hostrcb, queue);
|
||||
|
||||
if (unlikely(!hostrcb)) {
|
||||
dev_info(&ioa->pdev->dev, "Reclaiming async error buffers.");
|
||||
hostrcb = list_first_entry_or_null(&ioa->hostrcb_report_q,
|
||||
struct ipr_hostrcb, queue);
|
||||
}
|
||||
|
||||
list_del_init(&hostrcb->queue);
|
||||
return hostrcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_process_error - Op done function for an adapter error log.
|
||||
* @ipr_cmd: ipr command struct
|
||||
@ -2569,13 +2586,14 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
|
||||
struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
|
||||
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
|
||||
u32 fd_ioasc;
|
||||
char *envp[] = { "ASYNC_ERR_LOG=1", NULL };
|
||||
|
||||
if (ioa_cfg->sis64)
|
||||
fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc);
|
||||
else
|
||||
fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc);
|
||||
|
||||
list_del(&hostrcb->queue);
|
||||
list_del_init(&hostrcb->queue);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
|
||||
if (!ioasc) {
|
||||
@ -2588,6 +2606,10 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
|
||||
"Host RCB failed with IOASC: 0x%08X\n", ioasc);
|
||||
}
|
||||
|
||||
list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_report_q);
|
||||
hostrcb = ipr_get_free_hostrcb(ioa_cfg);
|
||||
kobject_uevent_env(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE, envp);
|
||||
|
||||
ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb);
|
||||
}
|
||||
|
||||
@ -4095,6 +4117,64 @@ static struct device_attribute ipr_ioa_fw_type_attr = {
|
||||
.show = ipr_show_fw_type
|
||||
};
|
||||
|
||||
static ssize_t ipr_read_async_err_log(struct file *filep, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *cdev = container_of(kobj, struct device, kobj);
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
|
||||
struct ipr_hostrcb *hostrcb;
|
||||
unsigned long lock_flags = 0;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
hostrcb = list_first_entry_or_null(&ioa_cfg->hostrcb_report_q,
|
||||
struct ipr_hostrcb, queue);
|
||||
if (!hostrcb) {
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
return 0;
|
||||
}
|
||||
ret = memory_read_from_buffer(buf, count, &off, &hostrcb->hcam,
|
||||
sizeof(hostrcb->hcam));
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ipr_next_async_err_log(struct file *filep, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct device *cdev = container_of(kobj, struct device, kobj);
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
|
||||
struct ipr_hostrcb *hostrcb;
|
||||
unsigned long lock_flags = 0;
|
||||
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
hostrcb = list_first_entry_or_null(&ioa_cfg->hostrcb_report_q,
|
||||
struct ipr_hostrcb, queue);
|
||||
if (!hostrcb) {
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Reclaim hostrcb before exit */
|
||||
list_move_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct bin_attribute ipr_ioa_async_err_log = {
|
||||
.attr = {
|
||||
.name = "async_err_log",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = 0,
|
||||
.read = ipr_read_async_err_log,
|
||||
.write = ipr_next_async_err_log
|
||||
};
|
||||
|
||||
static struct device_attribute *ipr_ioa_attrs[] = {
|
||||
&ipr_fw_version_attr,
|
||||
&ipr_log_level_attr,
|
||||
@ -7026,8 +7106,7 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
struct ipr_resource_entry *res;
|
||||
struct ipr_hostrcb *hostrcb, *temp;
|
||||
int i = 0, j;
|
||||
int j;
|
||||
|
||||
ENTER;
|
||||
ioa_cfg->in_reset_reload = 0;
|
||||
@ -7048,12 +7127,16 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
|
||||
}
|
||||
schedule_work(&ioa_cfg->work_q);
|
||||
|
||||
list_for_each_entry_safe(hostrcb, temp, &ioa_cfg->hostrcb_free_q, queue) {
|
||||
list_del(&hostrcb->queue);
|
||||
if (i++ < IPR_NUM_LOG_HCAMS)
|
||||
ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb);
|
||||
for (j = 0; j < IPR_NUM_HCAMS; j++) {
|
||||
list_del_init(&ioa_cfg->hostrcb[j]->queue);
|
||||
if (j < IPR_NUM_LOG_HCAMS)
|
||||
ipr_send_hcam(ioa_cfg,
|
||||
IPR_HCAM_CDB_OP_CODE_LOG_DATA,
|
||||
ioa_cfg->hostrcb[j]);
|
||||
else
|
||||
ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb);
|
||||
ipr_send_hcam(ioa_cfg,
|
||||
IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE,
|
||||
ioa_cfg->hostrcb[j]);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
ENTER;
|
||||
ipr_cmd->job_step = ipr_ioafp_std_inquiry;
|
||||
dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n");
|
||||
if (ioa_cfg->identify_hrrq_index == 0)
|
||||
dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n");
|
||||
|
||||
if (ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num) {
|
||||
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)
|
||||
|
||||
hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next,
|
||||
struct ipr_hostrcb, queue);
|
||||
list_del(&hostrcb->queue);
|
||||
list_del_init(&hostrcb->queue);
|
||||
memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam));
|
||||
|
||||
rc = ipr_get_ldump_data_section(ioa_cfg,
|
||||
@ -9332,7 +9416,7 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
|
||||
dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size,
|
||||
ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
|
||||
|
||||
for (i = 0; i < IPR_NUM_HCAMS; i++) {
|
||||
for (i = 0; i < IPR_MAX_HCAMS; i++) {
|
||||
dma_free_coherent(&ioa_cfg->pdev->dev,
|
||||
sizeof(struct ipr_hostrcb),
|
||||
ioa_cfg->hostrcb[i],
|
||||
@ -9572,7 +9656,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
|
||||
if (!ioa_cfg->u.cfg_table)
|
||||
goto out_free_host_rrq;
|
||||
|
||||
for (i = 0; i < IPR_NUM_HCAMS; i++) {
|
||||
for (i = 0; i < IPR_MAX_HCAMS; i++) {
|
||||
ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct ipr_hostrcb),
|
||||
&ioa_cfg->hostrcb_dma[i],
|
||||
@ -9714,6 +9798,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
|
||||
|
||||
INIT_LIST_HEAD(&ioa_cfg->hostrcb_free_q);
|
||||
INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q);
|
||||
INIT_LIST_HEAD(&ioa_cfg->hostrcb_report_q);
|
||||
INIT_LIST_HEAD(&ioa_cfg->free_res_q);
|
||||
INIT_LIST_HEAD(&ioa_cfg->used_res_q);
|
||||
INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
|
||||
@ -10352,6 +10437,8 @@ static void ipr_remove(struct pci_dev *pdev)
|
||||
&ipr_trace_attr);
|
||||
ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_dump_attr);
|
||||
sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_ioa_async_err_log);
|
||||
scsi_remove_host(ioa_cfg->host);
|
||||
|
||||
__ipr_remove(pdev);
|
||||
@ -10400,10 +10487,25 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = sysfs_create_bin_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_ioa_async_err_log);
|
||||
|
||||
if (rc) {
|
||||
ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_dump_attr);
|
||||
ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_trace_attr);
|
||||
scsi_remove_host(ioa_cfg->host);
|
||||
__ipr_remove(pdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_dump_attr);
|
||||
|
||||
if (rc) {
|
||||
sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_ioa_async_err_log);
|
||||
ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
|
||||
&ipr_trace_attr);
|
||||
scsi_remove_host(ioa_cfg->host);
|
||||
|
@ -154,7 +154,9 @@
|
||||
#define IPR_DEFAULT_MAX_ERROR_DUMP 984
|
||||
#define IPR_NUM_LOG_HCAMS 2
|
||||
#define IPR_NUM_CFG_CHG_HCAMS 2
|
||||
#define IPR_NUM_HCAM_QUEUE 12
|
||||
#define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS)
|
||||
#define IPR_MAX_HCAMS (IPR_NUM_HCAMS + IPR_NUM_HCAM_QUEUE)
|
||||
|
||||
#define IPR_MAX_SIS64_TARGETS_PER_BUS 1024
|
||||
#define IPR_MAX_SIS64_LUNS_PER_TARGET 0xffffffff
|
||||
@ -1504,6 +1506,7 @@ struct ipr_ioa_cfg {
|
||||
u8 log_level;
|
||||
#define IPR_MAX_LOG_LEVEL 4
|
||||
#define IPR_DEFAULT_LOG_LEVEL 2
|
||||
#define IPR_DEBUG_LOG_LEVEL 3
|
||||
|
||||
#define IPR_NUM_TRACE_INDEX_BITS 8
|
||||
#define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS)
|
||||
@ -1532,10 +1535,11 @@ struct ipr_ioa_cfg {
|
||||
|
||||
char ipr_hcam_label[8];
|
||||
#define IPR_HCAM_LABEL "hcams"
|
||||
struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS];
|
||||
dma_addr_t hostrcb_dma[IPR_NUM_HCAMS];
|
||||
struct ipr_hostrcb *hostrcb[IPR_MAX_HCAMS];
|
||||
dma_addr_t hostrcb_dma[IPR_MAX_HCAMS];
|
||||
struct list_head hostrcb_free_q;
|
||||
struct list_head hostrcb_pending_q;
|
||||
struct list_head hostrcb_report_q;
|
||||
|
||||
struct ipr_hrr_queue hrrq[IPR_MAX_HRRQ_NUM];
|
||||
u32 hrrq_num;
|
||||
|
@ -1837,7 +1837,6 @@ static void fc_exch_reset(struct fc_exch *ep)
|
||||
int rc = 1;
|
||||
|
||||
spin_lock_bh(&ep->ex_lock);
|
||||
fc_exch_abort_locked(ep, 0);
|
||||
ep->state |= FC_EX_RST_CLEANUP;
|
||||
fc_exch_timer_cancel(ep);
|
||||
if (ep->esb_stat & ESB_ST_REC_QUAL)
|
||||
|
@ -457,6 +457,9 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
|
||||
*/
|
||||
static int fc_rport_logoff(struct fc_rport_priv *rdata)
|
||||
{
|
||||
struct fc_lport *lport = rdata->local_port;
|
||||
u32 port_id = rdata->ids.port_id;
|
||||
|
||||
mutex_lock(&rdata->rp_mutex);
|
||||
|
||||
FC_RPORT_DBG(rdata, "Remove port\n");
|
||||
@ -466,6 +469,15 @@ static int fc_rport_logoff(struct fc_rport_priv *rdata)
|
||||
FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n");
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* FC-LS states:
|
||||
* To explicitly Logout, the initiating Nx_Port shall terminate
|
||||
* other open Sequences that it initiated with the destination
|
||||
* Nx_Port prior to performing Logout.
|
||||
*/
|
||||
lport->tt.exch_mgr_reset(lport, 0, port_id);
|
||||
lport->tt.exch_mgr_reset(lport, port_id, 0);
|
||||
|
||||
fc_rport_enter_logo(rdata);
|
||||
|
||||
/*
|
||||
@ -547,16 +559,24 @@ static void fc_rport_timeout(struct work_struct *work)
|
||||
*/
|
||||
static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
|
||||
{
|
||||
struct fc_lport *lport = rdata->local_port;
|
||||
|
||||
FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
|
||||
IS_ERR(fp) ? -PTR_ERR(fp) : 0,
|
||||
fc_rport_state(rdata), rdata->retries);
|
||||
|
||||
switch (rdata->rp_state) {
|
||||
case RPORT_ST_FLOGI:
|
||||
case RPORT_ST_PLOGI:
|
||||
rdata->flags &= ~FC_RP_STARTED;
|
||||
fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
|
||||
break;
|
||||
case RPORT_ST_PLOGI:
|
||||
if (lport->point_to_multipoint) {
|
||||
rdata->flags &= ~FC_RP_STARTED;
|
||||
fc_rport_enter_delete(rdata, RPORT_EV_FAILED);
|
||||
} else
|
||||
fc_rport_enter_logo(rdata);
|
||||
break;
|
||||
case RPORT_ST_RTV:
|
||||
fc_rport_enter_ready(rdata);
|
||||
break;
|
||||
@ -1877,7 +1897,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
|
||||
spp->spp_type_ext = rspp->spp_type_ext;
|
||||
spp->spp_flags = FC_SPP_RESP_ACK;
|
||||
|
||||
fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
|
||||
fc_rport_enter_prli(rdata);
|
||||
|
||||
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
|
||||
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)
|
||||
FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
|
||||
fc_rport_state(rdata));
|
||||
|
||||
fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
|
||||
fc_rport_enter_delete(rdata, RPORT_EV_STOP);
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
|
||||
} else
|
||||
|
@ -1535,7 +1535,7 @@ lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
|
||||
}
|
||||
|
||||
/* Routines for all individual HBA attributes */
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
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)
|
||||
ad->AttrType = cpu_to_be16(RHBA_NODENAME);
|
||||
return size;
|
||||
}
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1573,7 +1573,7 @@ lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
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)
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1615,7 +1615,7 @@ lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1637,7 +1637,7 @@ lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1669,7 +1669,7 @@ lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1690,7 +1690,7 @@ lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1715,7 +1715,7 @@ lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1736,7 +1736,7 @@ lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1759,7 +1759,7 @@ lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1775,7 +1775,7 @@ lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1794,7 +1794,7 @@ lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1811,7 +1811,7 @@ lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1828,7 +1828,7 @@ lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1846,7 +1846,7 @@ lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1867,7 +1867,7 @@ lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1884,7 +1884,7 @@ lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1906,7 +1906,7 @@ lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport,
|
||||
}
|
||||
|
||||
/* Routines for all individual PORT attributes */
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1925,7 +1925,7 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -1975,7 +1975,7 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2039,7 +2039,7 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2059,7 +2059,7 @@ lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2081,7 +2081,7 @@ lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2102,7 +2102,7 @@ lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2120,7 +2120,7 @@ lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2138,7 +2138,7 @@ lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2156,7 +2156,7 @@ lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2175,7 +2175,7 @@ lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_class(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2190,7 +2190,7 @@ lpfc_fdmi_port_attr_class(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2208,7 +2208,7 @@ lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2227,7 +2227,7 @@ lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2243,7 +2243,7 @@ lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2259,7 +2259,7 @@ lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2274,7 +2274,7 @@ lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2295,7 +2295,7 @@ lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2316,7 +2316,7 @@ lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2337,7 +2337,7 @@ lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2358,7 +2358,7 @@ lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2378,7 +2378,7 @@ lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
@ -2393,7 +2393,7 @@ lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport,
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport,
|
||||
struct lpfc_fdmi_attr_def *ad)
|
||||
{
|
||||
|
@ -4617,7 +4617,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
|
||||
return sentplogi;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc,
|
||||
uint32_t word0)
|
||||
{
|
||||
@ -4629,7 +4629,7 @@ lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc,
|
||||
return sizeof(struct fc_rdp_link_service_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc,
|
||||
uint8_t *page_a0, uint8_t *page_a2)
|
||||
{
|
||||
@ -4694,7 +4694,7 @@ lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc,
|
||||
return sizeof(struct fc_rdp_sfp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc,
|
||||
READ_LNK_VAR *stat)
|
||||
{
|
||||
@ -4723,7 +4723,7 @@ lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc,
|
||||
return sizeof(struct fc_rdp_link_error_status_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat,
|
||||
struct lpfc_vport *vport)
|
||||
{
|
||||
@ -4748,7 +4748,7 @@ lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat,
|
||||
return sizeof(struct fc_rdp_bbc_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2)
|
||||
{
|
||||
@ -4776,7 +4776,7 @@ lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba,
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
@ -4805,7 +4805,7 @@ lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba,
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
@ -4834,7 +4834,7 @@ lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba,
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
@ -4864,7 +4864,7 @@ lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba,
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
@ -4893,7 +4893,7 @@ lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba,
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc,
|
||||
uint8_t *page_a0, struct lpfc_vport *vport)
|
||||
{
|
||||
@ -4907,7 +4907,7 @@ lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc,
|
||||
return sizeof(struct fc_rdp_opd_sfp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat)
|
||||
{
|
||||
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)
|
||||
return sizeof(struct fc_fec_rdp_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
||||
{
|
||||
uint16_t rdp_cap = 0;
|
||||
@ -4986,7 +4986,7 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
||||
return sizeof(struct fc_rdp_port_speed_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc,
|
||||
struct lpfc_hba *phba)
|
||||
{
|
||||
@ -5003,7 +5003,7 @@ lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc,
|
||||
return sizeof(struct fc_rdp_port_name_desc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc,
|
||||
struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
@ -5027,7 +5027,7 @@ lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc,
|
||||
return sizeof(struct fc_rdp_port_name_desc);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
|
||||
int status)
|
||||
{
|
||||
@ -5165,7 +5165,7 @@ free_rdp_context:
|
||||
kfree(rdp_context);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context)
|
||||
{
|
||||
LPFC_MBOXQ_t *mbox = NULL;
|
||||
@ -7995,7 +7995,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
lpfc_start_fdmi(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
@ -2260,7 +2260,7 @@ lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
lpfc_mbx_cmpl_rdp_link_stat(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
||||
{
|
||||
MAILBOX_t *mb;
|
||||
@ -2281,7 +2281,7 @@ mbx_failed:
|
||||
rdp_context->cmpl(phba, rdp_context, rc);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
|
||||
{
|
||||
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) mbox->context1;
|
||||
|
@ -5689,7 +5689,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
|
||||
uint32_t feature)
|
||||
{
|
||||
@ -8968,7 +8968,7 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
|
||||
* Since ABORTS must go on the same WQ of the command they are
|
||||
* aborting, we use command's fcp_wqidx.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
lpfc_sli_calc_ring(struct lpfc_hba *phba, uint32_t ring_number,
|
||||
struct lpfc_iocbq *piocb)
|
||||
{
|
||||
|
@ -189,25 +189,12 @@ u32
|
||||
megasas_build_and_issue_cmd(struct megasas_instance *instance,
|
||||
struct scsi_cmnd *scmd);
|
||||
static void megasas_complete_cmd_dpc(unsigned long instance_addr);
|
||||
void
|
||||
megasas_release_fusion(struct megasas_instance *instance);
|
||||
int
|
||||
megasas_ioc_init_fusion(struct megasas_instance *instance);
|
||||
void
|
||||
megasas_free_cmds_fusion(struct megasas_instance *instance);
|
||||
u8
|
||||
megasas_get_map_info(struct megasas_instance *instance);
|
||||
int
|
||||
megasas_sync_map_info(struct megasas_instance *instance);
|
||||
int
|
||||
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
|
||||
int seconds);
|
||||
void megasas_reset_reply_desc(struct megasas_instance *instance);
|
||||
void megasas_fusion_ocr_wq(struct work_struct *work);
|
||||
static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance,
|
||||
int initial);
|
||||
int megasas_check_mpio_paths(struct megasas_instance *instance,
|
||||
struct scsi_cmnd *scmd);
|
||||
|
||||
int
|
||||
megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
|
||||
@ -5036,7 +5023,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
||||
|
||||
/* Find first memory bar */
|
||||
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
|
||||
instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
|
||||
instance->bar = find_first_bit(&bar_list, BITS_PER_LONG);
|
||||
if (pci_request_selected_regions(instance->pdev, 1<<instance->bar,
|
||||
"megasas: LSI")) {
|
||||
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,
|
||||
&instance->consumer_h);
|
||||
|
||||
if (!instance->producer || !instance->consumer) {
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate"
|
||||
dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate "
|
||||
"memory for producer, consumer\n");
|
||||
goto fail_alloc_dma_buf;
|
||||
}
|
||||
@ -6711,14 +6698,9 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
|
||||
unsigned long flags;
|
||||
u32 wait_time = MEGASAS_RESET_WAIT_TIME;
|
||||
|
||||
ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
|
||||
if (!ioc)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) {
|
||||
error = -EFAULT;
|
||||
goto out_kfree_ioc;
|
||||
}
|
||||
ioc = memdup_user(user_ioc, sizeof(*ioc));
|
||||
if (IS_ERR(ioc))
|
||||
return PTR_ERR(ioc);
|
||||
|
||||
instance = megasas_lookup_instance(ioc->host_no);
|
||||
if (!instance) {
|
||||
|
@ -991,5 +991,14 @@ union desc_value {
|
||||
} u;
|
||||
};
|
||||
|
||||
void megasas_free_cmds_fusion(struct megasas_instance *instance);
|
||||
int megasas_ioc_init_fusion(struct megasas_instance *instance);
|
||||
u8 megasas_get_map_info(struct megasas_instance *instance);
|
||||
int megasas_sync_map_info(struct megasas_instance *instance);
|
||||
void megasas_release_fusion(struct megasas_instance *instance);
|
||||
void megasas_reset_reply_desc(struct megasas_instance *instance);
|
||||
int megasas_check_mpio_paths(struct megasas_instance *instance,
|
||||
struct scsi_cmnd *scmd);
|
||||
void megasas_fusion_ocr_wq(struct work_struct *work);
|
||||
|
||||
#endif /* _MEGARAID_SAS_FUSION_H_ */
|
||||
|
@ -98,7 +98,7 @@ MODULE_PARM_DESC(mpt3sas_fwfault_debug,
|
||||
" enable detection of firmware fault and halt firmware - (default=0)");
|
||||
|
||||
static int
|
||||
_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag);
|
||||
_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
/**
|
||||
* _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
|
||||
@ -218,8 +218,7 @@ _base_fault_reset_work(struct work_struct *work)
|
||||
ioc->non_operational_loop = 0;
|
||||
|
||||
if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) {
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name,
|
||||
__func__, (rc == 0) ? "success" : "failed");
|
||||
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
@ -2040,7 +2039,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
|
||||
* mpt3sas_base_unmap_resources - free controller resources
|
||||
* @ioc: per adapter object
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
struct pci_dev *pdev = ioc->pdev;
|
||||
@ -2145,7 +2144,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
|
||||
|
||||
_base_mask_interrupts(ioc);
|
||||
|
||||
r = _base_get_ioc_facts(ioc, CAN_SLEEP);
|
||||
r = _base_get_ioc_facts(ioc);
|
||||
if (r)
|
||||
goto out_fail;
|
||||
|
||||
@ -3183,12 +3182,11 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
||||
/**
|
||||
* _base_allocate_memory_pools - allocate start of day memory pools
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 success, anything else error
|
||||
*/
|
||||
static int
|
||||
_base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
struct mpt3sas_facts *facts;
|
||||
u16 max_sge_elements;
|
||||
@ -3658,29 +3656,25 @@ mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked)
|
||||
* _base_wait_on_iocstate - waiting on a particular ioc state
|
||||
* @ioc_state: controller state { READY, OPERATIONAL, or RESET }
|
||||
* @timeout: timeout in second
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
|
||||
int sleep_flag)
|
||||
_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout)
|
||||
{
|
||||
u32 count, cntdn;
|
||||
u32 current_state;
|
||||
|
||||
count = 0;
|
||||
cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
|
||||
cntdn = 1000 * timeout;
|
||||
do {
|
||||
current_state = mpt3sas_base_get_iocstate(ioc, 1);
|
||||
if (current_state == ioc_state)
|
||||
return 0;
|
||||
if (count && current_state == MPI2_IOC_STATE_FAULT)
|
||||
break;
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
usleep_range(1000, 1500);
|
||||
else
|
||||
udelay(500);
|
||||
|
||||
usleep_range(1000, 1500);
|
||||
count++;
|
||||
} while (--cntdn);
|
||||
|
||||
@ -3692,24 +3686,22 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
|
||||
* a write to the doorbell)
|
||||
* @ioc: per adapter object
|
||||
* @timeout: timeout in second
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*
|
||||
* Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
|
||||
*/
|
||||
static int
|
||||
_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag);
|
||||
_base_diag_reset(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
static int
|
||||
_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
int sleep_flag)
|
||||
_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout)
|
||||
{
|
||||
u32 cntdn, count;
|
||||
u32 int_status;
|
||||
|
||||
count = 0;
|
||||
cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
|
||||
cntdn = 1000 * timeout;
|
||||
do {
|
||||
int_status = readl(&ioc->chip->HostInterruptStatus);
|
||||
if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
|
||||
@ -3718,10 +3710,8 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
ioc->name, __func__, count, timeout));
|
||||
return 0;
|
||||
}
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
usleep_range(1000, 1500);
|
||||
else
|
||||
udelay(500);
|
||||
|
||||
usleep_range(1000, 1500);
|
||||
count++;
|
||||
} while (--cntdn);
|
||||
|
||||
@ -3731,11 +3721,38 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
_base_spin_on_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout)
|
||||
{
|
||||
u32 cntdn, count;
|
||||
u32 int_status;
|
||||
|
||||
count = 0;
|
||||
cntdn = 2000 * timeout;
|
||||
do {
|
||||
int_status = readl(&ioc->chip->HostInterruptStatus);
|
||||
if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
|
||||
dhsprintk(ioc, pr_info(MPT3SAS_FMT
|
||||
"%s: successful count(%d), timeout(%d)\n",
|
||||
ioc->name, __func__, count, timeout));
|
||||
return 0;
|
||||
}
|
||||
|
||||
udelay(500);
|
||||
count++;
|
||||
} while (--cntdn);
|
||||
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%s: failed due to timeout count(%d), int_status(%x)!\n",
|
||||
ioc->name, __func__, count, int_status);
|
||||
return -EFAULT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
|
||||
* @ioc: per adapter object
|
||||
* @timeout: timeout in second
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*
|
||||
@ -3743,15 +3760,14 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
* doorbell.
|
||||
*/
|
||||
static int
|
||||
_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
int sleep_flag)
|
||||
_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout)
|
||||
{
|
||||
u32 cntdn, count;
|
||||
u32 int_status;
|
||||
u32 doorbell;
|
||||
|
||||
count = 0;
|
||||
cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
|
||||
cntdn = 1000 * timeout;
|
||||
do {
|
||||
int_status = readl(&ioc->chip->HostInterruptStatus);
|
||||
if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
|
||||
@ -3769,10 +3785,7 @@ _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
} else if (int_status == 0xFFFFFFFF)
|
||||
goto out;
|
||||
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
usleep_range(1000, 1500);
|
||||
else
|
||||
udelay(500);
|
||||
usleep_range(1000, 1500);
|
||||
count++;
|
||||
} while (--cntdn);
|
||||
|
||||
@ -3787,20 +3800,18 @@ _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
* _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
|
||||
* @ioc: per adapter object
|
||||
* @timeout: timeout in second
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
int sleep_flag)
|
||||
_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout)
|
||||
{
|
||||
u32 cntdn, count;
|
||||
u32 doorbell_reg;
|
||||
|
||||
count = 0;
|
||||
cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
|
||||
cntdn = 1000 * timeout;
|
||||
do {
|
||||
doorbell_reg = readl(&ioc->chip->Doorbell);
|
||||
if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
|
||||
@ -3809,10 +3820,8 @@ _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
ioc->name, __func__, count, timeout));
|
||||
return 0;
|
||||
}
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
usleep_range(1000, 1500);
|
||||
else
|
||||
udelay(500);
|
||||
|
||||
usleep_range(1000, 1500);
|
||||
count++;
|
||||
} while (--cntdn);
|
||||
|
||||
@ -3827,13 +3836,11 @@ _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
* @ioc: per adapter object
|
||||
* @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
|
||||
* @timeout: timeout in second
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout,
|
||||
int sleep_flag)
|
||||
_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout)
|
||||
{
|
||||
u32 ioc_state;
|
||||
int r = 0;
|
||||
@ -3852,12 +3859,11 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout,
|
||||
|
||||
writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
|
||||
&ioc->chip->Doorbell);
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 15))) {
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
|
||||
timeout, sleep_flag);
|
||||
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout);
|
||||
if (ioc_state) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%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,
|
||||
* @reply_bytes: reply length
|
||||
* @reply: pointer to reply payload
|
||||
* @timeout: timeout in second
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
|
||||
u32 *request, int reply_bytes, u16 *reply, int timeout)
|
||||
{
|
||||
MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
|
||||
int i;
|
||||
u8 failed;
|
||||
u16 dummy;
|
||||
__le32 *mfp;
|
||||
|
||||
/* make sure doorbell is not in use */
|
||||
@ -3911,7 +3915,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
|
||||
&ioc->chip->Doorbell);
|
||||
|
||||
if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
|
||||
if ((_base_spin_on_doorbell_int(ioc, 5))) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"doorbell handshake int failed (line=%d)\n",
|
||||
ioc->name, __LINE__);
|
||||
@ -3919,7 +3923,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
}
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 5))) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"doorbell handshake ack failed (line=%d)\n",
|
||||
ioc->name, __LINE__);
|
||||
@ -3929,7 +3933,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
/* send message 32-bits at a time */
|
||||
for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
|
||||
writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
|
||||
if ((_base_wait_for_doorbell_ack(ioc, 5)))
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
@ -3941,7 +3945,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
}
|
||||
|
||||
/* now wait for the reply */
|
||||
if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
|
||||
if ((_base_wait_for_doorbell_int(ioc, timeout))) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"doorbell handshake int failed (line=%d)\n",
|
||||
ioc->name, __LINE__);
|
||||
@ -3952,7 +3956,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK);
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
|
||||
if ((_base_wait_for_doorbell_int(ioc, 5))) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"doorbell handshake int failed (line=%d)\n",
|
||||
ioc->name, __LINE__);
|
||||
@ -3963,22 +3967,22 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
|
||||
for (i = 2; i < default_reply->MsgLength * 2; i++) {
|
||||
if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
|
||||
if ((_base_wait_for_doorbell_int(ioc, 5))) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"doorbell handshake int failed (line=%d)\n",
|
||||
ioc->name, __LINE__);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (i >= reply_bytes/2) /* overflow case */
|
||||
dummy = readl(&ioc->chip->Doorbell);
|
||||
readl(&ioc->chip->Doorbell);
|
||||
else
|
||||
reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
|
||||
& MPI2_DOORBELL_DATA_MASK);
|
||||
writel(0, &ioc->chip->HostInterruptStatus);
|
||||
}
|
||||
|
||||
_base_wait_for_doorbell_int(ioc, 5, sleep_flag);
|
||||
if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
|
||||
_base_wait_for_doorbell_int(ioc, 5);
|
||||
if (_base_wait_for_doorbell_not_used(ioc, 5) != 0) {
|
||||
dhsprintk(ioc, pr_info(MPT3SAS_FMT
|
||||
"doorbell is in use (line=%d)\n", ioc->name, __LINE__));
|
||||
}
|
||||
@ -4015,7 +4019,6 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
{
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
bool issue_reset = false;
|
||||
int rc;
|
||||
void *request;
|
||||
@ -4068,7 +4071,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
ioc->ioc_link_reset_in_progress = 1;
|
||||
init_completion(&ioc->base_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
|
||||
wait_for_completion_timeout(&ioc->base_cmds.done,
|
||||
msecs_to_jiffies(10000));
|
||||
if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
|
||||
mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
|
||||
@ -4093,8 +4096,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
ioc->base_cmds.status = MPT3_CMD_NOT_USED;
|
||||
rc = -EFAULT;
|
||||
out:
|
||||
@ -4119,7 +4121,6 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
|
||||
{
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
bool issue_reset = false;
|
||||
int rc;
|
||||
void *request;
|
||||
@ -4170,7 +4171,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
|
||||
memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
|
||||
init_completion(&ioc->base_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
|
||||
wait_for_completion_timeout(&ioc->base_cmds.done,
|
||||
msecs_to_jiffies(10000));
|
||||
if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
@ -4191,8 +4192,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
ioc->base_cmds.status = MPT3_CMD_NOT_USED;
|
||||
rc = -EFAULT;
|
||||
out:
|
||||
@ -4203,12 +4203,11 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
|
||||
/**
|
||||
* _base_get_port_facts - obtain port facts reply and save in ioc
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag)
|
||||
_base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port)
|
||||
{
|
||||
Mpi2PortFactsRequest_t mpi_request;
|
||||
Mpi2PortFactsReply_t mpi_reply;
|
||||
@ -4224,7 +4223,7 @@ _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag)
|
||||
mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
|
||||
mpi_request.PortNumber = port;
|
||||
r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
|
||||
(u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
|
||||
(u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5);
|
||||
|
||||
if (r != 0) {
|
||||
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)
|
||||
* _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL
|
||||
* @ioc: per adapter object
|
||||
* @timeout:
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
int sleep_flag)
|
||||
_base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout)
|
||||
{
|
||||
u32 ioc_state;
|
||||
int rc;
|
||||
@ -4287,8 +4284,7 @@ _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout,
|
||||
goto issue_diag_reset;
|
||||
}
|
||||
|
||||
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
|
||||
timeout, sleep_flag);
|
||||
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout);
|
||||
if (ioc_state) {
|
||||
dfailprintk(ioc, printk(MPT3SAS_FMT
|
||||
"%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,
|
||||
}
|
||||
|
||||
issue_diag_reset:
|
||||
rc = _base_diag_reset(ioc, sleep_flag);
|
||||
rc = _base_diag_reset(ioc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_get_ioc_facts - obtain ioc facts reply and save in ioc
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2IOCFactsRequest_t mpi_request;
|
||||
Mpi2IOCFactsReply_t mpi_reply;
|
||||
@ -4319,7 +4314,7 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
|
||||
__func__));
|
||||
|
||||
r = _base_wait_for_iocstate(ioc, 10, sleep_flag);
|
||||
r = _base_wait_for_iocstate(ioc, 10);
|
||||
if (r) {
|
||||
dfailprintk(ioc, printk(MPT3SAS_FMT
|
||||
"%s: failed getting to correct state\n",
|
||||
@ -4331,7 +4326,7 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
memset(&mpi_request, 0, mpi_request_sz);
|
||||
mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
|
||||
r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
|
||||
(u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
|
||||
(u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5);
|
||||
|
||||
if (r != 0) {
|
||||
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)
|
||||
/**
|
||||
* _base_send_ioc_init - send ioc_init to firmware
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2IOCInitRequest_t mpi_request;
|
||||
Mpi2IOCInitReply_t mpi_reply;
|
||||
@ -4479,8 +4473,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
|
||||
r = _base_handshake_req_reply_wait(ioc,
|
||||
sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
|
||||
sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
|
||||
sleep_flag);
|
||||
sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10);
|
||||
|
||||
if (r != 0) {
|
||||
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,
|
||||
/**
|
||||
* _base_send_port_enable - send port_enable(discovery stuff) to firmware
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_send_port_enable(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2PortEnableRequest_t *mpi_request;
|
||||
Mpi2PortEnableReply_t *mpi_reply;
|
||||
unsigned long timeleft;
|
||||
int r = 0;
|
||||
u16 smid;
|
||||
u16 ioc_status;
|
||||
@ -4592,8 +4583,7 @@ _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
|
||||
init_completion(&ioc->port_enable_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
|
||||
300*HZ);
|
||||
wait_for_completion_timeout(&ioc->port_enable_cmds.done, 300*HZ);
|
||||
if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
ioc->name, __func__);
|
||||
@ -4737,15 +4727,13 @@ _base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event)
|
||||
/**
|
||||
* _base_event_notification - send event notification
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_event_notification(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2EventNotificationRequest_t *mpi_request;
|
||||
unsigned long timeleft;
|
||||
u16 smid;
|
||||
int r = 0;
|
||||
int i;
|
||||
@ -4777,7 +4765,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
cpu_to_le32(ioc->event_masks[i]);
|
||||
init_completion(&ioc->base_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
|
||||
wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
|
||||
if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
ioc->name, __func__);
|
||||
@ -4827,19 +4815,18 @@ mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type)
|
||||
return;
|
||||
|
||||
mutex_lock(&ioc->base_cmds.mutex);
|
||||
_base_event_notification(ioc, CAN_SLEEP);
|
||||
_base_event_notification(ioc);
|
||||
mutex_unlock(&ioc->base_cmds.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_diag_reset - the "big hammer" start of day reset
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_diag_reset(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
u32 host_diagnostic;
|
||||
u32 ioc_state;
|
||||
@ -4867,10 +4854,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
|
||||
|
||||
/* wait 100 msec */
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
msleep(100);
|
||||
else
|
||||
mdelay(100);
|
||||
msleep(100);
|
||||
|
||||
if (count++ > 20)
|
||||
goto out;
|
||||
@ -4890,10 +4874,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
&ioc->chip->HostDiagnostic);
|
||||
|
||||
/*This delay allows the chip PCIe hardware time to finish reset tasks*/
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
|
||||
else
|
||||
mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
|
||||
msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
|
||||
|
||||
/* Approximately 300 second max wait */
|
||||
for (count = 0; count < (300000000 /
|
||||
@ -4906,13 +4887,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
|
||||
break;
|
||||
|
||||
/* Wait to pass the second read delay window */
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
|
||||
/ 1000);
|
||||
else
|
||||
mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
|
||||
/ 1000);
|
||||
msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC / 1000);
|
||||
}
|
||||
|
||||
if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
|
||||
@ -4941,8 +4916,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
|
||||
drsprintk(ioc, pr_info(MPT3SAS_FMT
|
||||
"Wait for FW to go to the READY state\n", ioc->name));
|
||||
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
|
||||
sleep_flag);
|
||||
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20);
|
||||
if (ioc_state) {
|
||||
pr_err(MPT3SAS_FMT
|
||||
"%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)
|
||||
/**
|
||||
* _base_make_ioc_ready - put controller in READY state
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
* @type: FORCE_BIG_HAMMER or SOFT_RESET
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
enum reset_type type)
|
||||
_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type)
|
||||
{
|
||||
u32 ioc_state;
|
||||
int rc;
|
||||
@ -4995,10 +4967,7 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
ioc->name, __func__, ioc_state);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
ssleep(1);
|
||||
else
|
||||
mdelay(1000);
|
||||
ssleep(1);
|
||||
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
}
|
||||
}
|
||||
@ -5024,24 +4993,23 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
|
||||
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
|
||||
if (!(_base_send_ioc_reset(ioc,
|
||||
MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
|
||||
MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
issue_diag_reset:
|
||||
rc = _base_diag_reset(ioc, CAN_SLEEP);
|
||||
rc = _base_diag_reset(ioc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_make_ioc_operational - put controller in OPERATIONAL state
|
||||
* @ioc: per adapter object
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
static int
|
||||
_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
int r, i, index;
|
||||
unsigned long flags;
|
||||
@ -5160,7 +5128,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
}
|
||||
skip_init_reply_post_free_queue:
|
||||
|
||||
r = _base_send_ioc_init(ioc, sleep_flag);
|
||||
r = _base_send_ioc_init(ioc);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -5186,13 +5154,11 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
skip_init_reply_post_host_index:
|
||||
|
||||
_base_unmask_interrupts(ioc);
|
||||
r = _base_event_notification(ioc, sleep_flag);
|
||||
r = _base_event_notification(ioc);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (sleep_flag == CAN_SLEEP)
|
||||
_base_static_config_pages(ioc);
|
||||
|
||||
_base_static_config_pages(ioc);
|
||||
|
||||
if (ioc->is_driver_loading) {
|
||||
|
||||
@ -5211,7 +5177,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
return r; /* scan_start and scan_finished support */
|
||||
}
|
||||
|
||||
r = _base_send_port_enable(ioc, sleep_flag);
|
||||
r = _base_send_port_enable(ioc);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -5235,7 +5201,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
|
||||
if (ioc->chip_phys && ioc->chip) {
|
||||
_base_mask_interrupts(ioc);
|
||||
ioc->shost_recovery = 1;
|
||||
_base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
|
||||
_base_make_ioc_ready(ioc, SOFT_RESET);
|
||||
ioc->shost_recovery = 0;
|
||||
}
|
||||
|
||||
@ -5292,7 +5258,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
||||
goto out_free_resources;
|
||||
|
||||
pci_set_drvdata(ioc->pdev, ioc->shost);
|
||||
r = _base_get_ioc_facts(ioc, CAN_SLEEP);
|
||||
r = _base_get_ioc_facts(ioc);
|
||||
if (r)
|
||||
goto out_free_resources;
|
||||
|
||||
@ -5326,7 +5292,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
||||
ioc->build_sg_mpi = &_base_build_sg;
|
||||
ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge;
|
||||
|
||||
r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
|
||||
r = _base_make_ioc_ready(ioc, SOFT_RESET);
|
||||
if (r)
|
||||
goto out_free_resources;
|
||||
|
||||
@ -5338,12 +5304,12 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
||||
}
|
||||
|
||||
for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
|
||||
r = _base_get_port_facts(ioc, i, CAN_SLEEP);
|
||||
r = _base_get_port_facts(ioc, i);
|
||||
if (r)
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
|
||||
r = _base_allocate_memory_pools(ioc);
|
||||
if (r)
|
||||
goto out_free_resources;
|
||||
|
||||
@ -5429,7 +5395,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
||||
if (ioc->hba_mpi_version_belonged == MPI26_VERSION)
|
||||
_base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
|
||||
|
||||
r = _base_make_ioc_operational(ioc, CAN_SLEEP);
|
||||
r = _base_make_ioc_operational(ioc);
|
||||
if (r)
|
||||
goto out_free_resources;
|
||||
|
||||
@ -5565,21 +5531,18 @@ _base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
|
||||
/**
|
||||
* _wait_for_commands_to_complete - reset controller
|
||||
* @ioc: Pointer to MPT_ADAPTER structure
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
*
|
||||
* This function waiting(3s) for all pending commands to complete
|
||||
* prior to putting controller in reset.
|
||||
*/
|
||||
static void
|
||||
_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
|
||||
_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
u32 ioc_state;
|
||||
unsigned long flags;
|
||||
u16 i;
|
||||
|
||||
ioc->pending_io_count = 0;
|
||||
if (sleep_flag != CAN_SLEEP)
|
||||
return;
|
||||
|
||||
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
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)
|
||||
/**
|
||||
* mpt3sas_base_hard_reset_handler - reset controller
|
||||
* @ioc: Pointer to MPT_ADAPTER structure
|
||||
* @sleep_flag: CAN_SLEEP or NO_SLEEP
|
||||
* @type: FORCE_BIG_HAMMER or SOFT_RESET
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
|
||||
enum reset_type type)
|
||||
{
|
||||
int r;
|
||||
@ -5629,13 +5591,6 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
if (mpt3sas_fwfault_debug)
|
||||
mpt3sas_halt_firmware(ioc);
|
||||
|
||||
/* TODO - What we really should be doing is pulling
|
||||
* out all the code associated with NO_SLEEP; its never used.
|
||||
* That is legacy code from mpt fusion driver, ported over.
|
||||
* I will leave this BUG_ON here for now till its been resolved.
|
||||
*/
|
||||
BUG_ON(sleep_flag == NO_SLEEP);
|
||||
|
||||
/* wait for an active reset in progress to complete */
|
||||
if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
|
||||
do {
|
||||
@ -5660,9 +5615,9 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
is_fault = 1;
|
||||
}
|
||||
_base_reset_handler(ioc, MPT3_IOC_PRE_RESET);
|
||||
_wait_for_commands_to_complete(ioc, sleep_flag);
|
||||
_wait_for_commands_to_complete(ioc);
|
||||
_base_mask_interrupts(ioc);
|
||||
r = _base_make_ioc_ready(ioc, sleep_flag, type);
|
||||
r = _base_make_ioc_ready(ioc, type);
|
||||
if (r)
|
||||
goto out;
|
||||
_base_reset_handler(ioc, MPT3_IOC_AFTER_RESET);
|
||||
@ -5675,7 +5630,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
r = _base_get_ioc_facts(ioc, CAN_SLEEP);
|
||||
r = _base_get_ioc_facts(ioc);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
@ -5684,7 +5639,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
"Please reboot the system and ensure that the correct"
|
||||
" firmware version is running\n", ioc->name);
|
||||
|
||||
r = _base_make_ioc_operational(ioc, sleep_flag);
|
||||
r = _base_make_ioc_operational(ioc);
|
||||
if (!r)
|
||||
_base_reset_handler(ioc, MPT3_IOC_DONE_RESET);
|
||||
|
||||
|
@ -119,10 +119,6 @@
|
||||
|
||||
#define MPT_MAX_CALLBACKS 32
|
||||
|
||||
|
||||
#define CAN_SLEEP 1
|
||||
#define NO_SLEEP 0
|
||||
|
||||
#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
|
||||
/* reserved for issuing internally framed scsi io cmds */
|
||||
#define INTERNAL_SCSIIO_CMDS_COUNT 3
|
||||
@ -478,7 +474,7 @@ struct _sas_device {
|
||||
u8 pfa_led_on;
|
||||
u8 pend_sas_rphy_add;
|
||||
u8 enclosure_level;
|
||||
u8 connector_name[4];
|
||||
u8 connector_name[5];
|
||||
struct kref refcount;
|
||||
};
|
||||
|
||||
@ -794,16 +790,6 @@ struct reply_post_struct {
|
||||
dma_addr_t reply_post_free_dma;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mutex_type - task management mutex type
|
||||
* @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
|
||||
* @TM_MUTEX_ON: mutex is required
|
||||
*/
|
||||
enum mutex_type {
|
||||
TM_MUTEX_OFF = 0,
|
||||
TM_MUTEX_ON = 1,
|
||||
};
|
||||
|
||||
typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
|
||||
/**
|
||||
* struct MPT3SAS_ADAPTER - per adapter struct
|
||||
@ -1229,7 +1215,7 @@ int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc);
|
||||
void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc);
|
||||
int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc);
|
||||
void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc);
|
||||
int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
|
||||
int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
|
||||
enum reset_type type);
|
||||
|
||||
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);
|
||||
|
||||
int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
||||
uint channel, uint id, uint lun, u8 type, u16 smid_task,
|
||||
ulong timeout, enum mutex_type m_type);
|
||||
ulong timeout);
|
||||
int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
||||
uint channel, uint id, uint lun, u8 type, u16 smid_task,
|
||||
ulong timeout);
|
||||
|
||||
void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
|
||||
void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
|
||||
void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
|
||||
|
@ -285,7 +285,6 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
||||
{
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
Mpi2ConfigRequest_t *config_request;
|
||||
int r;
|
||||
u8 retry_count, issue_host_reset = 0;
|
||||
@ -386,8 +385,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
||||
_config_display_some_debug(ioc, smid, "config_request", NULL);
|
||||
init_completion(&ioc->config_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
|
||||
timeout*HZ);
|
||||
wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
|
||||
if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
ioc->name, __func__);
|
||||
@ -491,8 +489,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
||||
mutex_unlock(&ioc->config_cmds.mutex);
|
||||
|
||||
if (issue_host_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -518,7 +518,7 @@ mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
|
||||
*
|
||||
* Called when application request fasyn callback handler.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
_ctl_fasync(int fd, struct file *filep, int mode)
|
||||
{
|
||||
return fasync_helper(fd, filep, mode, &async_queue);
|
||||
@ -530,7 +530,7 @@ _ctl_fasync(int fd, struct file *filep, int mode)
|
||||
* @wait -
|
||||
*
|
||||
*/
|
||||
unsigned int
|
||||
static unsigned int
|
||||
_ctl_poll(struct file *filep, poll_table *wait)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc;
|
||||
@ -641,9 +641,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
MPI2RequestHeader_t *mpi_request = NULL, *request;
|
||||
MPI2DefaultReply_t *mpi_reply;
|
||||
u32 ioc_state;
|
||||
u16 ioc_status;
|
||||
u16 smid;
|
||||
unsigned long timeout, timeleft;
|
||||
unsigned long timeout;
|
||||
u8 issue_reset;
|
||||
u32 sz;
|
||||
void *psge;
|
||||
@ -914,8 +913,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
timeout = MPT3_IOCTL_DEFAULT_TIMEOUT;
|
||||
else
|
||||
timeout = karg.timeout;
|
||||
timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
timeout*HZ);
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done, timeout*HZ);
|
||||
if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
|
||||
Mpi2SCSITaskManagementRequest_t *tm_request =
|
||||
(Mpi2SCSITaskManagementRequest_t *)mpi_request;
|
||||
@ -938,7 +936,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
}
|
||||
|
||||
mpi_reply = ioc->ctl_cmds.reply;
|
||||
ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
|
||||
if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
|
||||
(ioc->logging_level & MPT_DEBUG_TM)) {
|
||||
@ -1001,13 +998,11 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
ioc->name,
|
||||
le16_to_cpu(mpi_request->FunctionDependent1));
|
||||
mpt3sas_halt_firmware(ioc);
|
||||
mpt3sas_scsih_issue_tm(ioc,
|
||||
mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
|
||||
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30,
|
||||
TM_MUTEX_ON);
|
||||
0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30);
|
||||
} else
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -1220,8 +1215,7 @@ _ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
|
||||
__func__));
|
||||
|
||||
retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
pr_info(MPT3SAS_FMT "host reset: %s\n",
|
||||
ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
|
||||
return 0;
|
||||
@ -1381,7 +1375,6 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2DiagBufferPostRequest_t *mpi_request;
|
||||
Mpi2DiagBufferPostReply_t *mpi_reply;
|
||||
u8 buffer_type;
|
||||
unsigned long timeleft;
|
||||
u16 smid;
|
||||
u16 ioc_status;
|
||||
u32 ioc_state;
|
||||
@ -1499,7 +1492,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
@ -1538,8 +1531,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
|
||||
out:
|
||||
|
||||
@ -1800,7 +1792,6 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
|
||||
u16 ioc_status;
|
||||
u32 ioc_state;
|
||||
int rc;
|
||||
unsigned long timeleft;
|
||||
|
||||
dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
|
||||
__func__));
|
||||
@ -1848,7 +1839,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
@ -1974,8 +1965,7 @@ _ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset);
|
||||
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1995,7 +1985,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
Mpi2DiagBufferPostReply_t *mpi_reply;
|
||||
int rc, i;
|
||||
u8 buffer_type;
|
||||
unsigned long timeleft, request_size, copy_size;
|
||||
unsigned long request_size, copy_size;
|
||||
u16 smid;
|
||||
u16 ioc_status;
|
||||
u8 issue_reset = 0;
|
||||
@ -2116,7 +2106,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
@ -2155,8 +2145,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
|
||||
out:
|
||||
|
||||
@ -2352,7 +2341,7 @@ out_unlock_pciaccess:
|
||||
* @cmd - ioctl opcode
|
||||
* @arg -
|
||||
*/
|
||||
long
|
||||
static long
|
||||
_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret;
|
||||
@ -2372,7 +2361,7 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
* @cmd - ioctl opcode
|
||||
* @arg -
|
||||
*/
|
||||
long
|
||||
static long
|
||||
_ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret;
|
||||
@ -2392,7 +2381,7 @@ _ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
*
|
||||
* This routine handles 32 bit applications in 64bit os.
|
||||
*/
|
||||
long
|
||||
static long
|
||||
_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
|
||||
{
|
||||
long ret;
|
||||
@ -2410,7 +2399,7 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
|
||||
*
|
||||
* This routine handles 32 bit applications in 64bit os.
|
||||
*/
|
||||
long
|
||||
static long
|
||||
_ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
|
||||
{
|
||||
long ret;
|
||||
|
@ -1195,7 +1195,7 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
|
||||
*
|
||||
* Returns queue depth.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
{
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
@ -1244,7 +1244,7 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
* Returns 0 if ok. Any other return is assumed to be an error and
|
||||
* the device is ignored.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_target_alloc(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
|
||||
@ -1311,7 +1311,7 @@ scsih_target_alloc(struct scsi_target *starget)
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_target_destroy(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
|
||||
@ -1320,7 +1320,6 @@ scsih_target_destroy(struct scsi_target *starget)
|
||||
struct _sas_device *sas_device;
|
||||
struct _raid_device *raid_device;
|
||||
unsigned long flags;
|
||||
struct sas_rphy *rphy;
|
||||
|
||||
sas_target_priv_data = starget->hostdata;
|
||||
if (!sas_target_priv_data)
|
||||
@ -1339,7 +1338,6 @@ scsih_target_destroy(struct scsi_target *starget)
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ioc->sas_device_lock, flags);
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
|
||||
if (sas_device && (sas_device->starget == starget) &&
|
||||
(sas_device->id == starget->id) &&
|
||||
@ -1369,7 +1367,7 @@ scsih_target_destroy(struct scsi_target *starget)
|
||||
* Returns 0 if ok. Any other return is assumed to be an error and
|
||||
* the device is ignored.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
@ -1434,7 +1432,7 @@ scsih_slave_alloc(struct scsi_device *sdev)
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_slave_destroy(struct scsi_device *sdev)
|
||||
{
|
||||
struct MPT3SAS_TARGET *sas_target_priv_data;
|
||||
@ -1527,7 +1525,7 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
|
||||
* scsih_is_raid - return boolean indicating device is raid volume
|
||||
* @dev the device struct object
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_is_raid(struct device *dev)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(dev);
|
||||
@ -1542,7 +1540,7 @@ scsih_is_raid(struct device *dev)
|
||||
* scsih_get_resync - get raid volume resync percent complete
|
||||
* @dev the device struct object
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_get_resync(struct device *dev)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(dev);
|
||||
@ -1603,7 +1601,7 @@ scsih_get_resync(struct device *dev)
|
||||
* scsih_get_state - get raid volume level
|
||||
* @dev the device struct object
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_get_state(struct device *dev)
|
||||
{
|
||||
struct scsi_device *sdev = to_scsi_device(dev);
|
||||
@ -1805,7 +1803,7 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
|
||||
* Returns 0 if ok. Any other return is assumed to be an error and
|
||||
* the device is ignored.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
@ -2021,7 +2019,7 @@ scsih_slave_configure(struct scsi_device *sdev)
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
|
||||
sector_t capacity, int params[])
|
||||
{
|
||||
@ -2201,7 +2199,6 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
|
||||
* @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
|
||||
* @smid_task: smid assigned to the task
|
||||
* @timeout: timeout in seconds
|
||||
* @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
|
||||
* Context: user
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
int
|
||||
mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
|
||||
uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
|
||||
enum mutex_type m_type)
|
||||
uint id, uint lun, u8 type, u16 smid_task, ulong timeout)
|
||||
{
|
||||
Mpi2SCSITaskManagementRequest_t *mpi_request;
|
||||
Mpi2SCSITaskManagementReply_t *mpi_reply;
|
||||
u16 smid = 0;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
struct scsiio_tracker *scsi_lookup = NULL;
|
||||
int rc;
|
||||
u16 msix_task = 0;
|
||||
|
||||
if (m_type == TM_MUTEX_ON)
|
||||
mutex_lock(&ioc->tm_cmds.mutex);
|
||||
lockdep_assert_held(&ioc->tm_cmds.mutex);
|
||||
|
||||
if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) {
|
||||
pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n",
|
||||
__func__, ioc->name);
|
||||
rc = FAILED;
|
||||
goto err_out;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (ioc->shost_recovery || ioc->remove_host ||
|
||||
ioc->pci_error_recovery) {
|
||||
pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
|
||||
__func__, ioc->name);
|
||||
rc = FAILED;
|
||||
goto err_out;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
|
||||
if (ioc_state & MPI2_DOORBELL_USED) {
|
||||
dhsprintk(ioc, pr_info(MPT3SAS_FMT
|
||||
"unexpected doorbell active!\n", ioc->name));
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
rc = (!rc) ? SUCCESS : FAILED;
|
||||
goto err_out;
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
return (!rc) ? SUCCESS : FAILED;
|
||||
}
|
||||
|
||||
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
|
||||
mpt3sas_base_fault_info(ioc, ioc_state &
|
||||
MPI2_DOORBELL_DATA_MASK);
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
rc = (!rc) ? SUCCESS : FAILED;
|
||||
goto err_out;
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
return (!rc) ? SUCCESS : FAILED;
|
||||
}
|
||||
|
||||
smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
|
||||
if (!smid) {
|
||||
pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
|
||||
ioc->name, __func__);
|
||||
rc = FAILED;
|
||||
goto err_out;
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
|
||||
@ -2292,19 +2280,17 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
|
||||
else
|
||||
msix_task = 0;
|
||||
mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task);
|
||||
timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
|
||||
wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
|
||||
if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
ioc->name, __func__);
|
||||
_debug_dump_mf(mpi_request,
|
||||
sizeof(Mpi2SCSITaskManagementRequest_t)/4);
|
||||
if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) {
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc,
|
||||
FORCE_BIG_HAMMER);
|
||||
rc = (!rc) ? SUCCESS : FAILED;
|
||||
ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
|
||||
mpt3sas_scsih_clear_tm_flag(ioc, handle);
|
||||
goto err_out;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2356,17 +2342,23 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mpt3sas_scsih_clear_tm_flag(ioc, handle);
|
||||
ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
|
||||
if (m_type == TM_MUTEX_ON)
|
||||
mutex_unlock(&ioc->tm_cmds.mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
err_out:
|
||||
if (m_type == TM_MUTEX_ON)
|
||||
mutex_unlock(&ioc->tm_cmds.mutex);
|
||||
return rc;
|
||||
int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
||||
uint channel, uint id, uint lun, u8 type, u16 smid_task, ulong timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ioc->tm_cmds.mutex);
|
||||
ret = mpt3sas_scsih_issue_tm(ioc, handle, channel, id, lun, type,
|
||||
smid_task, timeout);
|
||||
mutex_unlock(&ioc->tm_cmds.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2439,7 +2431,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_abort(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
|
||||
@ -2482,9 +2474,9 @@ scsih_abort(struct scsi_cmnd *scmd)
|
||||
mpt3sas_halt_firmware(ioc);
|
||||
|
||||
handle = sas_device_priv_data->sas_target->handle;
|
||||
r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
|
||||
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
|
||||
scmd->device->id, scmd->device->lun,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON);
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30);
|
||||
|
||||
out:
|
||||
sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
|
||||
@ -2498,7 +2490,7 @@ scsih_abort(struct scsi_cmnd *scmd)
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_dev_reset(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
|
||||
@ -2541,9 +2533,9 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
|
||||
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
|
||||
scmd->device->id, scmd->device->lun,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON);
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30);
|
||||
|
||||
out:
|
||||
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
|
||||
@ -2561,7 +2553,7 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_target_reset(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
|
||||
@ -2603,9 +2595,9 @@ scsih_target_reset(struct scsi_cmnd *scmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
|
||||
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
|
||||
scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
|
||||
30, TM_MUTEX_ON);
|
||||
30);
|
||||
|
||||
out:
|
||||
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
|
||||
@ -2624,7 +2616,7 @@ scsih_target_reset(struct scsi_cmnd *scmd)
|
||||
*
|
||||
* Returns SUCCESS if command aborted else FAILED
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_host_reset(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
|
||||
@ -2641,8 +2633,7 @@ scsih_host_reset(struct scsi_cmnd *scmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
r = (retval < 0) ? FAILED : SUCCESS;
|
||||
out:
|
||||
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,
|
||||
*
|
||||
* Context - processed in interrupt context.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
|
||||
u32 event_context)
|
||||
{
|
||||
@ -3494,7 +3485,7 @@ _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
|
||||
*
|
||||
* Context - processed in interrupt context.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
_scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc,
|
||||
u16 smid, u16 handle)
|
||||
{
|
||||
@ -4032,7 +4023,7 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
|
||||
* SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
|
||||
* SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
|
||||
{
|
||||
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)
|
||||
le16_to_cpu(mpi_reply->DevHandle));
|
||||
mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
|
||||
|
||||
if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
|
||||
if ((ioc->logging_level & MPT_DEBUG_REPLY) &&
|
||||
((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
|
||||
(scmd->sense_buffer[2] == MEDIUM_ERROR) ||
|
||||
(scmd->sense_buffer[2] == HARDWARE_ERROR)))
|
||||
@ -5380,8 +5371,9 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
|
||||
MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
|
||||
sas_device->enclosure_level =
|
||||
le16_to_cpu(sas_device_pg0.EnclosureLevel);
|
||||
memcpy(&sas_device->connector_name[0],
|
||||
&sas_device_pg0.ConnectorName[0], 4);
|
||||
memcpy(sas_device->connector_name,
|
||||
sas_device_pg0.ConnectorName, 4);
|
||||
sas_device->connector_name[4] = '\0';
|
||||
} else {
|
||||
sas_device->enclosure_level = 0;
|
||||
sas_device->connector_name[0] = '\0';
|
||||
@ -5508,8 +5500,9 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
|
||||
if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
|
||||
sas_device->enclosure_level =
|
||||
le16_to_cpu(sas_device_pg0.EnclosureLevel);
|
||||
memcpy(&sas_device->connector_name[0],
|
||||
&sas_device_pg0.ConnectorName[0], 4);
|
||||
memcpy(sas_device->connector_name,
|
||||
sas_device_pg0.ConnectorName, 4);
|
||||
sas_device->connector_name[4] = '\0';
|
||||
} else {
|
||||
sas_device->enclosure_level = 0;
|
||||
sas_device->connector_name[0] = '\0';
|
||||
@ -6087,8 +6080,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
|
||||
r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30,
|
||||
TM_MUTEX_OFF);
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
|
||||
if (r == FAILED) {
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"mpt3sas_scsih_issue_tm: FAILED when sending "
|
||||
@ -6128,8 +6120,8 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
|
||||
goto out_no_lock;
|
||||
|
||||
r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
|
||||
sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
|
||||
TM_MUTEX_OFF);
|
||||
sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid,
|
||||
30);
|
||||
if (r == FAILED) {
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
|
||||
@ -6297,8 +6289,7 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
|
||||
mutex_unlock(&ioc->scsih_cmds.mutex);
|
||||
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -6311,11 +6302,10 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
|
||||
static void
|
||||
_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
|
||||
{
|
||||
int rc;
|
||||
sdev->no_uld_attach = no_uld_attach ? 1 : 0;
|
||||
sdev_printk(KERN_INFO, sdev, "%s raid component\n",
|
||||
sdev->no_uld_attach ? "hidding" : "exposing");
|
||||
rc = scsi_device_reprobe(sdev);
|
||||
WARN_ON(scsi_device_reprobe(sdev));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -8137,7 +8127,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
|
||||
* Routine called when unloading the driver.
|
||||
* Return nothing.
|
||||
*/
|
||||
void scsih_remove(struct pci_dev *pdev)
|
||||
static void scsih_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
||||
@ -8210,7 +8200,7 @@ void scsih_remove(struct pci_dev *pdev)
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
@ -8451,7 +8441,7 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
|
||||
* of scanning the entire bus. In our implemention, we will kick off
|
||||
* firmware discovery.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_scan_start(struct Scsi_Host *shost)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
||||
@ -8478,7 +8468,7 @@ scsih_scan_start(struct Scsi_Host *shost)
|
||||
* scsi_host and the elapsed time of the scan in jiffies. In our implemention,
|
||||
* we wait for firmware discovery to complete, then return 1.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
||||
@ -8608,7 +8598,7 @@ static struct raid_function_template mpt3sas_raid_functions = {
|
||||
* MPI25_VERSION for SAS 3.0 HBA devices, and
|
||||
* MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices
|
||||
*/
|
||||
u16
|
||||
static u16
|
||||
_scsih_determine_hba_mpi_version(struct pci_dev *pdev)
|
||||
{
|
||||
|
||||
@ -8660,7 +8650,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
|
||||
*
|
||||
* Returns 0 success, anything else error.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc;
|
||||
@ -8869,7 +8859,7 @@ out_add_shost_fail:
|
||||
*
|
||||
* Returns 0 success, anything else error.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
@ -8896,7 +8886,7 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
*
|
||||
* Returns 0 success, anything else error.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
@ -8916,7 +8906,7 @@ scsih_resume(struct pci_dev *pdev)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
|
||||
mpt3sas_base_hard_reset_handler(ioc, SOFT_RESET);
|
||||
scsi_unblock_requests(shost);
|
||||
mpt3sas_base_start_watchdog(ioc);
|
||||
return 0;
|
||||
@ -8933,7 +8923,7 @@ scsih_resume(struct pci_dev *pdev)
|
||||
* Return value:
|
||||
* PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
|
||||
*/
|
||||
pci_ers_result_t
|
||||
static pci_ers_result_t
|
||||
scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
|
||||
{
|
||||
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)
|
||||
* code after the PCI slot has been reset, just before we
|
||||
* should resume normal operations.
|
||||
*/
|
||||
pci_ers_result_t
|
||||
static pci_ers_result_t
|
||||
scsih_pci_slot_reset(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
@ -8987,8 +8977,7 @@ scsih_pci_slot_reset(struct pci_dev *pdev)
|
||||
if (rc)
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
|
||||
pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
|
||||
(rc == 0) ? "success" : "failed");
|
||||
@ -9007,7 +8996,7 @@ scsih_pci_slot_reset(struct pci_dev *pdev)
|
||||
* OK to resume normal operation. Use completion to allow
|
||||
* halted scsi ops to resume.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
@ -9024,7 +9013,7 @@ scsih_pci_resume(struct pci_dev *pdev)
|
||||
* scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
|
||||
* @pdev: pointer to PCI device
|
||||
*/
|
||||
pci_ers_result_t
|
||||
static pci_ers_result_t
|
||||
scsih_pci_mmio_enabled(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
@ -9152,7 +9141,7 @@ static struct pci_driver mpt3sas_driver = {
|
||||
*
|
||||
* Returns 0 success, anything else error.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
scsih_init(void)
|
||||
{
|
||||
mpt2_ids = 0;
|
||||
@ -9202,7 +9191,7 @@ scsih_init(void)
|
||||
*
|
||||
* Returns 0 success, anything else error.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scsih_exit(void)
|
||||
{
|
||||
|
||||
|
@ -300,7 +300,6 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
|
||||
int rc;
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
void *psge;
|
||||
u8 issue_reset = 0;
|
||||
void *data_out = NULL;
|
||||
@ -394,8 +393,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
|
||||
ioc->name, (unsigned long long)sas_address));
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
|
||||
10*HZ);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
@ -446,8 +444,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
out:
|
||||
ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
|
||||
if (data_out)
|
||||
@ -1107,7 +1104,6 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
|
||||
int rc;
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
void *psge;
|
||||
u8 issue_reset = 0;
|
||||
void *data_out = NULL;
|
||||
@ -1203,8 +1199,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
|
||||
phy->number));
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
|
||||
10*HZ);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
@ -1253,8 +1248,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
out:
|
||||
ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
|
||||
if (data_out)
|
||||
@ -1421,7 +1415,6 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
int rc;
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
void *psge;
|
||||
u8 issue_reset = 0;
|
||||
void *data_out = NULL;
|
||||
@ -1522,8 +1515,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
phy->number, phy_operation));
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
|
||||
10*HZ);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
@ -1564,8 +1556,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset)
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
out:
|
||||
ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
|
||||
if (data_out)
|
||||
@ -1899,7 +1890,6 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
|
||||
int rc;
|
||||
u16 smid;
|
||||
u32 ioc_state;
|
||||
unsigned long timeleft;
|
||||
void *psge;
|
||||
u8 issue_reset = 0;
|
||||
dma_addr_t dma_addr_in = 0;
|
||||
@ -2043,8 +2033,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
|
||||
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
|
||||
10*HZ);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s : timeout\n",
|
||||
@ -2103,8 +2092,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset) {
|
||||
mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
|
||||
FORCE_BIG_HAMMER);
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
rc = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,8 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
|
||||
}
|
||||
}
|
||||
|
||||
void mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
|
||||
static void
|
||||
mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
|
||||
{
|
||||
void __iomem *regs = mvi->regs;
|
||||
u32 tmp;
|
||||
@ -563,7 +564,7 @@ static u8 mvs_64xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
|
||||
return MVS_ID_NOT_MAPPED;
|
||||
}
|
||||
|
||||
void mvs_64xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
|
||||
static void mvs_64xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
|
||||
{
|
||||
int i;
|
||||
struct scatterlist *sg;
|
||||
@ -633,7 +634,7 @@ static void mvs_64xx_phy_work_around(struct mvs_info *mvi, int i)
|
||||
mvs_write_port_vsr_data(mvi, i, tmp);
|
||||
}
|
||||
|
||||
void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
|
||||
static void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
|
||||
struct sas_phy_linkrates *rates)
|
||||
{
|
||||
u32 lrmin = 0, lrmax = 0;
|
||||
@ -668,20 +669,20 @@ static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi)
|
||||
}
|
||||
|
||||
|
||||
u32 mvs_64xx_spi_read_data(struct mvs_info *mvi)
|
||||
static u32 mvs_64xx_spi_read_data(struct mvs_info *mvi)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex;
|
||||
return ior32(SPI_DATA_REG_64XX);
|
||||
}
|
||||
|
||||
void mvs_64xx_spi_write_data(struct mvs_info *mvi, u32 data)
|
||||
static void mvs_64xx_spi_write_data(struct mvs_info *mvi, u32 data)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex;
|
||||
iow32(SPI_DATA_REG_64XX, data);
|
||||
}
|
||||
|
||||
|
||||
int mvs_64xx_spi_buildcmd(struct mvs_info *mvi,
|
||||
static int mvs_64xx_spi_buildcmd(struct mvs_info *mvi,
|
||||
u32 *dwCmd,
|
||||
u8 cmd,
|
||||
u8 read,
|
||||
@ -705,7 +706,7 @@ int mvs_64xx_spi_buildcmd(struct mvs_info *mvi,
|
||||
}
|
||||
|
||||
|
||||
int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
|
||||
static int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex;
|
||||
int retry;
|
||||
@ -720,7 +721,7 @@ int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
|
||||
static int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex;
|
||||
u32 i, dwTmp;
|
||||
@ -735,7 +736,7 @@ int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
|
||||
static void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
|
||||
int buf_len, int from, void *prd)
|
||||
{
|
||||
int i;
|
||||
|
@ -48,8 +48,8 @@ static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i)
|
||||
}
|
||||
}
|
||||
|
||||
void set_phy_tuning(struct mvs_info *mvi, int phy_id,
|
||||
struct phy_tuning phy_tuning)
|
||||
static void set_phy_tuning(struct mvs_info *mvi, int phy_id,
|
||||
struct phy_tuning phy_tuning)
|
||||
{
|
||||
u32 tmp, setting_0 = 0, setting_1 = 0;
|
||||
u8 i;
|
||||
@ -110,8 +110,8 @@ void set_phy_tuning(struct mvs_info *mvi, int phy_id,
|
||||
}
|
||||
}
|
||||
|
||||
void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id,
|
||||
struct ffe_control ffe)
|
||||
static void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id,
|
||||
struct ffe_control ffe)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
@ -177,7 +177,7 @@ void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id,
|
||||
}
|
||||
|
||||
/*Notice: this function must be called when phy is disabled*/
|
||||
void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
|
||||
static void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
|
||||
{
|
||||
union reg_phy_cfg phy_cfg, phy_cfg_tmp;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
|
||||
static void
|
||||
mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
|
||||
{
|
||||
void __iomem *regs = mvi->regs;
|
||||
u32 tmp;
|
||||
@ -906,8 +907,8 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
|
||||
|
||||
}
|
||||
|
||||
void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
|
||||
struct sas_phy_linkrates *rates)
|
||||
static void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
|
||||
struct sas_phy_linkrates *rates)
|
||||
{
|
||||
u32 lrmax = 0;
|
||||
u32 tmp;
|
||||
@ -936,25 +937,25 @@ static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi)
|
||||
}
|
||||
|
||||
|
||||
u32 mvs_94xx_spi_read_data(struct mvs_info *mvi)
|
||||
static u32 mvs_94xx_spi_read_data(struct mvs_info *mvi)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
return mr32(SPI_RD_DATA_REG_94XX);
|
||||
}
|
||||
|
||||
void mvs_94xx_spi_write_data(struct mvs_info *mvi, u32 data)
|
||||
static void mvs_94xx_spi_write_data(struct mvs_info *mvi, u32 data)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
mw32(SPI_RD_DATA_REG_94XX, data);
|
||||
}
|
||||
|
||||
|
||||
int mvs_94xx_spi_buildcmd(struct mvs_info *mvi,
|
||||
u32 *dwCmd,
|
||||
u8 cmd,
|
||||
u8 read,
|
||||
u8 length,
|
||||
u32 addr
|
||||
static int mvs_94xx_spi_buildcmd(struct mvs_info *mvi,
|
||||
u32 *dwCmd,
|
||||
u8 cmd,
|
||||
u8 read,
|
||||
u8 length,
|
||||
u32 addr
|
||||
)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
@ -974,7 +975,7 @@ int mvs_94xx_spi_buildcmd(struct mvs_info *mvi,
|
||||
}
|
||||
|
||||
|
||||
int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
|
||||
static int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
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)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
|
||||
static int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
|
||||
{
|
||||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
u32 i, dwTmp;
|
||||
@ -997,8 +998,8 @@ int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
|
||||
int buf_len, int from, void *prd)
|
||||
static void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
|
||||
int buf_len, int from, void *prd)
|
||||
{
|
||||
int i;
|
||||
struct mvs_prd *buf_prd = prd;
|
||||
|
@ -74,7 +74,7 @@ void mvs_tag_init(struct mvs_info *mvi)
|
||||
mvs_tag_clear(mvi, i);
|
||||
}
|
||||
|
||||
struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
|
||||
static struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
|
||||
{
|
||||
unsigned long i = 0, j = 0, hi = 0;
|
||||
struct sas_ha_struct *sha = dev->port->ha;
|
||||
@ -102,7 +102,7 @@ struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
|
||||
|
||||
}
|
||||
|
||||
int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
|
||||
static int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
|
||||
{
|
||||
unsigned long i = 0, j = 0, n = 0, num = 0;
|
||||
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)
|
||||
mvs_port_notify_deformed(sas_phy, 1);
|
||||
}
|
||||
|
||||
struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi)
|
||||
static struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi)
|
||||
{
|
||||
u32 dev;
|
||||
for (dev = 0; dev < MVS_MAX_DEVICES; dev++) {
|
||||
@ -1175,7 +1175,7 @@ struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mvs_free_dev(struct mvs_device *mvi_dev)
|
||||
static void mvs_free_dev(struct mvs_device *mvi_dev)
|
||||
{
|
||||
u32 id = mvi_dev->device_id;
|
||||
memset(mvi_dev, 0, sizeof(*mvi_dev));
|
||||
@ -1185,7 +1185,7 @@ void mvs_free_dev(struct mvs_device *mvi_dev)
|
||||
mvi_dev->taskfileset = MVS_ID_NOT_MAPPED;
|
||||
}
|
||||
|
||||
int mvs_dev_found_notify(struct domain_device *dev, int lock)
|
||||
static int mvs_dev_found_notify(struct domain_device *dev, int lock)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
int res = 0;
|
||||
@ -1241,7 +1241,7 @@ int mvs_dev_found(struct domain_device *dev)
|
||||
return mvs_dev_found_notify(dev, 1);
|
||||
}
|
||||
|
||||
void mvs_dev_gone_notify(struct domain_device *dev)
|
||||
static void mvs_dev_gone_notify(struct domain_device *dev)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
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,
|
||||
return stat;
|
||||
}
|
||||
|
||||
void mvs_set_sense(u8 *buffer, int len, int d_sense,
|
||||
static void mvs_set_sense(u8 *buffer, int len, int d_sense,
|
||||
int key, int asc, int ascq)
|
||||
{
|
||||
memset(buffer, 0, len);
|
||||
@ -1650,7 +1650,7 @@ void mvs_set_sense(u8 *buffer, int len, int d_sense,
|
||||
return;
|
||||
}
|
||||
|
||||
void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu,
|
||||
static void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu,
|
||||
u8 key, u8 asc, u8 asc_q)
|
||||
{
|
||||
iu->datapres = 2;
|
||||
|
@ -1,565 +0,0 @@
|
||||
/*
|
||||
* This driver adapted from Drew Eckhardt's Trantor T128 driver
|
||||
*
|
||||
* Copyright 1993, Drew Eckhardt
|
||||
* Visionary Computing
|
||||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 666-5836
|
||||
*
|
||||
* ( Based on T128 - DISTRIBUTION RELEASE 3. )
|
||||
*
|
||||
* Modified to work with the Pro Audio Spectrum/Studio 16
|
||||
* by John Weidman.
|
||||
*
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* Media Vision
|
||||
* (510) 770-8600
|
||||
* (800) 348-7116
|
||||
*/
|
||||
|
||||
/*
|
||||
* The card is detected and initialized in one of several ways :
|
||||
* 1. Autoprobe (default) - There are many different models of
|
||||
* the Pro Audio Spectrum/Studio 16, and I only have one of
|
||||
* them, so this may require a little tweaking. An interrupt
|
||||
* is triggered to autoprobe for the interrupt line. Note:
|
||||
* with the newer model boards, the interrupt is set via
|
||||
* software after reset using the default_irq for the
|
||||
* current board number.
|
||||
*
|
||||
* 2. With command line overrides - pas16=port,irq may be
|
||||
* used on the LILO command line to override the defaults.
|
||||
*
|
||||
* 3. With the PAS16_OVERRIDE compile time define. This is
|
||||
* specified as an array of address, irq tuples. Ie, for
|
||||
* one board at the default 0x388 address, IRQ10, I could say
|
||||
* -DPAS16_OVERRIDE={{0x388, 10}}
|
||||
* NOTE: Untested.
|
||||
*
|
||||
* 4. When included as a module, with arguments passed on the command line:
|
||||
* pas16_irq=xx the interrupt
|
||||
* pas16_addr=xx the port
|
||||
* e.g. "modprobe pas16 pas16_addr=0x388 pas16_irq=5"
|
||||
*
|
||||
* Note that if the override methods are used, place holders must
|
||||
* be specified for other boards in the system.
|
||||
*
|
||||
*
|
||||
* Configuration notes :
|
||||
* The current driver does not support interrupt sharing with the
|
||||
* sound portion of the card. If you use the same irq for the
|
||||
* scsi port and sound you will have problems. Either use
|
||||
* a different irq for the scsi port or don't use interrupts
|
||||
* for the scsi port.
|
||||
*
|
||||
* If you have problems with your card not being recognized, use
|
||||
* the LILO command line override. Try to get it recognized without
|
||||
* interrupts. Ie, for a board at the default 0x388 base port,
|
||||
* boot: linux pas16=0x388,0
|
||||
*
|
||||
* NO_IRQ (0) should be specified for no interrupt,
|
||||
* IRQ_AUTO (254) to autoprobe for an IRQ line if overridden
|
||||
* on the command line.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/dma.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "pas16.h"
|
||||
#include "NCR5380.h"
|
||||
|
||||
|
||||
static unsigned short pas16_addr;
|
||||
static int pas16_irq;
|
||||
|
||||
|
||||
static const int scsi_irq_translate[] =
|
||||
{ 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 };
|
||||
|
||||
/* The default_irqs array contains values used to set the irq into the
|
||||
* board via software (as must be done on newer model boards without
|
||||
* irq jumpers on the board). The first value in the array will be
|
||||
* assigned to logical board 0, the next to board 1, etc.
|
||||
*/
|
||||
static int default_irqs[] __initdata =
|
||||
{ PAS16_DEFAULT_BOARD_1_IRQ,
|
||||
PAS16_DEFAULT_BOARD_2_IRQ,
|
||||
PAS16_DEFAULT_BOARD_3_IRQ,
|
||||
PAS16_DEFAULT_BOARD_4_IRQ
|
||||
};
|
||||
|
||||
static struct override {
|
||||
unsigned short io_port;
|
||||
int irq;
|
||||
} overrides
|
||||
#ifdef PAS16_OVERRIDE
|
||||
[] __initdata = PAS16_OVERRIDE;
|
||||
#else
|
||||
[4] __initdata = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO},
|
||||
{0,IRQ_AUTO}};
|
||||
#endif
|
||||
|
||||
#define NO_OVERRIDES ARRAY_SIZE(overrides)
|
||||
|
||||
static struct base {
|
||||
unsigned short io_port;
|
||||
int noauto;
|
||||
} bases[] __initdata =
|
||||
{ {PAS16_DEFAULT_BASE_1, 0},
|
||||
{PAS16_DEFAULT_BASE_2, 0},
|
||||
{PAS16_DEFAULT_BASE_3, 0},
|
||||
{PAS16_DEFAULT_BASE_4, 0}
|
||||
};
|
||||
|
||||
#define NO_BASES ARRAY_SIZE(bases)
|
||||
|
||||
static const unsigned short pas16_offset[ 8 ] =
|
||||
{
|
||||
0x1c00, /* OUTPUT_DATA_REG */
|
||||
0x1c01, /* INITIATOR_COMMAND_REG */
|
||||
0x1c02, /* MODE_REG */
|
||||
0x1c03, /* TARGET_COMMAND_REG */
|
||||
0x3c00, /* STATUS_REG ro, SELECT_ENABLE_REG wo */
|
||||
0x3c01, /* BUS_AND_STATUS_REG ro, START_DMA_SEND_REG wo */
|
||||
0x3c02, /* INPUT_DATA_REGISTER ro, (N/A on PAS16 ?)
|
||||
* START_DMA_TARGET_RECEIVE_REG wo
|
||||
*/
|
||||
0x3c03, /* RESET_PARITY_INTERRUPT_REG ro,
|
||||
* START_DMA_INITIATOR_RECEIVE_REG wo
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Function : enable_board( int board_num, unsigned short port )
|
||||
*
|
||||
* Purpose : set address in new model board
|
||||
*
|
||||
* Inputs : board_num - logical board number 0-3, port - base address
|
||||
*
|
||||
*/
|
||||
|
||||
static void __init
|
||||
enable_board( int board_num, unsigned short port )
|
||||
{
|
||||
outb( 0xbc + board_num, MASTER_ADDRESS_PTR );
|
||||
outb( port >> 2, MASTER_ADDRESS_PTR );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Function : init_board( unsigned short port, int irq )
|
||||
*
|
||||
* Purpose : Set the board up to handle the SCSI interface
|
||||
*
|
||||
* Inputs : port - base address of the board,
|
||||
* irq - irq to assign to the SCSI port
|
||||
* force_irq - set it even if it conflicts with sound driver
|
||||
*
|
||||
*/
|
||||
|
||||
static void __init
|
||||
init_board( unsigned short io_port, int irq, int force_irq )
|
||||
{
|
||||
unsigned int tmp;
|
||||
unsigned int pas_irq_code;
|
||||
|
||||
/* Initialize the SCSI part of the board */
|
||||
|
||||
outb( 0x30, io_port + P_TIMEOUT_COUNTER_REG ); /* Timeout counter */
|
||||
outb( 0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET ); /* Reset TC */
|
||||
outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */
|
||||
|
||||
inb(io_port + pas16_offset[RESET_PARITY_INTERRUPT_REG]);
|
||||
|
||||
/* Set the SCSI interrupt pointer without mucking up the sound
|
||||
* interrupt pointer in the same byte.
|
||||
*/
|
||||
pas_irq_code = ( irq < 16 ) ? scsi_irq_translate[irq] : 0;
|
||||
tmp = inb( io_port + IO_CONFIG_3 );
|
||||
|
||||
if( (( tmp & 0x0f ) == pas_irq_code) && pas_irq_code > 0
|
||||
&& !force_irq )
|
||||
{
|
||||
printk( "pas16: WARNING: Can't use same irq as sound "
|
||||
"driver -- interrupts disabled\n" );
|
||||
/* Set up the drive parameters, disable 5380 interrupts */
|
||||
outb( 0x4d, io_port + SYS_CONFIG_4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = ( tmp & 0x0f ) | ( pas_irq_code << 4 );
|
||||
outb( tmp, io_port + IO_CONFIG_3 );
|
||||
|
||||
/* Set up the drive parameters and enable 5380 interrupts */
|
||||
outb( 0x6d, io_port + SYS_CONFIG_4 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function : pas16_hw_detect( unsigned short board_num )
|
||||
*
|
||||
* Purpose : determine if a pas16 board is present
|
||||
*
|
||||
* Inputs : board_num - logical board number ( 0 - 3 )
|
||||
*
|
||||
* Returns : 0 if board not found, 1 if found.
|
||||
*/
|
||||
|
||||
static int __init
|
||||
pas16_hw_detect( unsigned short board_num )
|
||||
{
|
||||
unsigned char board_rev, tmp;
|
||||
unsigned short io_port = bases[ board_num ].io_port;
|
||||
|
||||
/* See if we can find a PAS16 board at the address associated
|
||||
* with this logical board number.
|
||||
*/
|
||||
|
||||
/* First, attempt to take a newer model board out of reset and
|
||||
* give it a base address. This shouldn't affect older boards.
|
||||
*/
|
||||
enable_board( board_num, io_port );
|
||||
|
||||
/* Now see if it looks like a PAS16 board */
|
||||
board_rev = inb( io_port + PCB_CONFIG );
|
||||
|
||||
if( board_rev == 0xff )
|
||||
return 0;
|
||||
|
||||
tmp = board_rev ^ 0xe0;
|
||||
|
||||
outb( tmp, io_port + PCB_CONFIG );
|
||||
tmp = inb( io_port + PCB_CONFIG );
|
||||
outb( board_rev, io_port + PCB_CONFIG );
|
||||
|
||||
if( board_rev != tmp ) /* Not a PAS-16 */
|
||||
return 0;
|
||||
|
||||
if( ( inb( io_port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 )
|
||||
return 0; /* return if no SCSI interface found */
|
||||
|
||||
/* Mediavision has some new model boards that return ID bits
|
||||
* that indicate a SCSI interface, but they're not (LMS). We'll
|
||||
* put in an additional test to try to weed them out.
|
||||
*/
|
||||
|
||||
outb(0x01, io_port + WAIT_STATE); /* 1 Wait state */
|
||||
outb(0x20, io_port + pas16_offset[MODE_REG]); /* Is it really SCSI? */
|
||||
if (inb(io_port + pas16_offset[MODE_REG]) != 0x20) /* Write to a reg. */
|
||||
return 0; /* and try to read */
|
||||
outb(0x00, io_port + pas16_offset[MODE_REG]); /* it back. */
|
||||
if (inb(io_port + pas16_offset[MODE_REG]) != 0x00)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef MODULE
|
||||
/*
|
||||
* Function : pas16_setup(char *str, int *ints)
|
||||
*
|
||||
* Purpose : LILO command line initialization of the overrides array,
|
||||
*
|
||||
* Inputs : str - unused, ints - array of integer parameters with ints[0]
|
||||
* equal to the number of ints.
|
||||
*
|
||||
*/
|
||||
|
||||
static int __init pas16_setup(char *str)
|
||||
{
|
||||
static int commandline_current;
|
||||
int i;
|
||||
int ints[10];
|
||||
|
||||
get_options(str, ARRAY_SIZE(ints), ints);
|
||||
if (ints[0] != 2)
|
||||
printk("pas16_setup : usage pas16=io_port,irq\n");
|
||||
else
|
||||
if (commandline_current < NO_OVERRIDES) {
|
||||
overrides[commandline_current].io_port = (unsigned short) ints[1];
|
||||
overrides[commandline_current].irq = ints[2];
|
||||
for (i = 0; i < NO_BASES; ++i)
|
||||
if (bases[i].io_port == (unsigned short) ints[1]) {
|
||||
bases[i].noauto = 1;
|
||||
break;
|
||||
}
|
||||
++commandline_current;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("pas16=", pas16_setup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function : int pas16_detect(struct scsi_host_template * tpnt)
|
||||
*
|
||||
* Purpose : detects and initializes PAS16 controllers
|
||||
* that were autoprobed, overridden on the LILO command line,
|
||||
* or specified at compile time.
|
||||
*
|
||||
* Inputs : tpnt - template for this SCSI adapter.
|
||||
*
|
||||
* Returns : 1 if a host adapter was found, 0 if not.
|
||||
*
|
||||
*/
|
||||
|
||||
static int __init pas16_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
static int current_override;
|
||||
static unsigned short current_base;
|
||||
struct Scsi_Host *instance;
|
||||
unsigned short io_port;
|
||||
int count;
|
||||
|
||||
if (pas16_addr != 0) {
|
||||
overrides[0].io_port = pas16_addr;
|
||||
/*
|
||||
* This is how we avoid seeing more than
|
||||
* one host adapter at the same I/O port.
|
||||
* Cribbed shamelessly from pas16_setup().
|
||||
*/
|
||||
for (count = 0; count < NO_BASES; ++count)
|
||||
if (bases[count].io_port == pas16_addr) {
|
||||
bases[count].noauto = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pas16_irq != 0)
|
||||
overrides[0].irq = pas16_irq;
|
||||
|
||||
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
|
||||
io_port = 0;
|
||||
|
||||
if (overrides[current_override].io_port)
|
||||
{
|
||||
io_port = overrides[current_override].io_port;
|
||||
enable_board( current_override, io_port );
|
||||
init_board( io_port, overrides[current_override].irq, 1 );
|
||||
}
|
||||
else
|
||||
for (; !io_port && (current_base < NO_BASES); ++current_base) {
|
||||
dprintk(NDEBUG_INIT, "pas16: probing io_port 0x%04x\n",
|
||||
(unsigned int)bases[current_base].io_port);
|
||||
if ( !bases[current_base].noauto &&
|
||||
pas16_hw_detect( current_base ) ){
|
||||
io_port = bases[current_base].io_port;
|
||||
init_board( io_port, default_irqs[ current_base ], 0 );
|
||||
dprintk(NDEBUG_INIT, "pas16: detected board\n");
|
||||
}
|
||||
}
|
||||
|
||||
dprintk(NDEBUG_INIT, "pas16: io_port = 0x%04x\n",
|
||||
(unsigned int)io_port);
|
||||
|
||||
if (!io_port)
|
||||
break;
|
||||
|
||||
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if(instance == NULL)
|
||||
goto out;
|
||||
|
||||
instance->io_port = io_port;
|
||||
|
||||
if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP))
|
||||
goto out_unregister;
|
||||
|
||||
NCR5380_maybe_reset_bus(instance);
|
||||
|
||||
if (overrides[current_override].irq != IRQ_AUTO)
|
||||
instance->irq = overrides[current_override].irq;
|
||||
else
|
||||
instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
|
||||
|
||||
/* Compatibility with documented NCR5380 kernel parameters */
|
||||
if (instance->irq == 255)
|
||||
instance->irq = NO_IRQ;
|
||||
|
||||
if (instance->irq != NO_IRQ)
|
||||
if (request_irq(instance->irq, pas16_intr, 0,
|
||||
"pas16", instance)) {
|
||||
printk("scsi%d : IRQ%d not free, interrupts disabled\n",
|
||||
instance->host_no, instance->irq);
|
||||
instance->irq = NO_IRQ;
|
||||
}
|
||||
|
||||
if (instance->irq == NO_IRQ) {
|
||||
printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
|
||||
printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
|
||||
/* Disable 5380 interrupts, leave drive params the same */
|
||||
outb( 0x4d, io_port + SYS_CONFIG_4 );
|
||||
outb( (inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3 );
|
||||
}
|
||||
|
||||
dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n",
|
||||
instance->host_no, instance->irq);
|
||||
|
||||
++current_override;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
|
||||
out_unregister:
|
||||
scsi_unregister(instance);
|
||||
out:
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function : int pas16_biosparam(Disk *disk, struct block_device *dev, int *ip)
|
||||
*
|
||||
* Purpose : Generates a BIOS / DOS compatible H-C-S mapping for
|
||||
* the specified device / size.
|
||||
*
|
||||
* Inputs : size = size of device in sectors (512 bytes), dev = block device
|
||||
* major / minor, ip[] = {heads, sectors, cylinders}
|
||||
*
|
||||
* Returns : always 0 (success), initializes ip
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX Most SCSI boards use this mapping, I could be incorrect. Some one
|
||||
* using hard disks on a trantor should verify that this mapping corresponds
|
||||
* to that used by the BIOS / ASPI driver by running the linux fdisk program
|
||||
* and matching the H_C_S coordinates to what DOS uses.
|
||||
*/
|
||||
|
||||
static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
|
||||
sector_t capacity, int *ip)
|
||||
{
|
||||
int size = capacity;
|
||||
ip[0] = 64;
|
||||
ip[1] = 32;
|
||||
ip[2] = size >> 11; /* I think I have it as /(32*64) */
|
||||
if( ip[2] > 1024 ) { /* yes, >, not >= */
|
||||
ip[0]=255;
|
||||
ip[1]=63;
|
||||
ip[2]=size/(63*255);
|
||||
if( ip[2] > 1023 ) /* yes >1023... */
|
||||
ip[2] = 1023;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function : int pas16_pread (struct Scsi_Host *instance,
|
||||
* unsigned char *dst, int len)
|
||||
*
|
||||
* Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to
|
||||
* dst
|
||||
*
|
||||
* Inputs : dst = destination, len = length in bytes
|
||||
*
|
||||
* Returns : 0 on success, non zero on a failure such as a watchdog
|
||||
* timeout.
|
||||
*/
|
||||
|
||||
static inline int pas16_pread(struct Scsi_Host *instance,
|
||||
unsigned char *dst, int len)
|
||||
{
|
||||
register unsigned char *d = dst;
|
||||
register unsigned short reg = (unsigned short) (instance->io_port +
|
||||
P_DATA_REG_OFFSET);
|
||||
register int i = len;
|
||||
int ii = 0;
|
||||
|
||||
while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) )
|
||||
++ii;
|
||||
|
||||
insb( reg, d, i );
|
||||
|
||||
if ( inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) {
|
||||
outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET);
|
||||
printk("scsi%d : watchdog timer fired in NCR5380_pread()\n",
|
||||
instance->host_no);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function : int pas16_pwrite (struct Scsi_Host *instance,
|
||||
* unsigned char *src, int len)
|
||||
*
|
||||
* Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
|
||||
* src
|
||||
*
|
||||
* Inputs : src = source, len = length in bytes
|
||||
*
|
||||
* Returns : 0 on success, non zero on a failure such as a watchdog
|
||||
* timeout.
|
||||
*/
|
||||
|
||||
static inline int pas16_pwrite(struct Scsi_Host *instance,
|
||||
unsigned char *src, int len)
|
||||
{
|
||||
register unsigned char *s = src;
|
||||
register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET);
|
||||
register int i = len;
|
||||
int ii = 0;
|
||||
|
||||
while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) )
|
||||
++ii;
|
||||
|
||||
outsb( reg, s, i );
|
||||
|
||||
if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) {
|
||||
outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET);
|
||||
printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n",
|
||||
instance->host_no);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "NCR5380.c"
|
||||
|
||||
static int pas16_release(struct Scsi_Host *shost)
|
||||
{
|
||||
if (shost->irq != NO_IRQ)
|
||||
free_irq(shost->irq, shost);
|
||||
NCR5380_exit(shost);
|
||||
scsi_unregister(shost);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.name = "Pro Audio Spectrum-16 SCSI",
|
||||
.detect = pas16_detect,
|
||||
.release = pas16_release,
|
||||
.proc_name = "pas16",
|
||||
.info = pas16_info,
|
||||
.queuecommand = pas16_queue_command,
|
||||
.eh_abort_handler = pas16_abort,
|
||||
.eh_bus_reset_handler = pas16_bus_reset,
|
||||
.bios_param = pas16_biosparam,
|
||||
.can_queue = 32,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 2,
|
||||
.use_clustering = DISABLE_CLUSTERING,
|
||||
.cmd_size = NCR5380_CMD_SIZE,
|
||||
.max_sectors = 128,
|
||||
};
|
||||
#include "scsi_module.c"
|
||||
|
||||
#ifdef MODULE
|
||||
module_param(pas16_addr, ushort, 0);
|
||||
module_param(pas16_irq, int, 0);
|
||||
#endif
|
||||
MODULE_LICENSE("GPL");
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* This driver adapted from Drew Eckhardt's Trantor T128 driver
|
||||
*
|
||||
* Copyright 1993, Drew Eckhardt
|
||||
* Visionary Computing
|
||||
* (Unix and Linux consulting and custom programming)
|
||||
* drew@colorado.edu
|
||||
* +1 (303) 666-5836
|
||||
*
|
||||
* ( Based on T128 - DISTRIBUTION RELEASE 3. )
|
||||
*
|
||||
* Modified to work with the Pro Audio Spectrum/Studio 16
|
||||
* by John Weidman.
|
||||
*
|
||||
*
|
||||
* For more information, please consult
|
||||
*
|
||||
* Media Vision
|
||||
* (510) 770-8600
|
||||
* (800) 348-7116
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PAS16_H
|
||||
#define PAS16_H
|
||||
|
||||
#define PAS16_DEFAULT_BASE_1 0x388
|
||||
#define PAS16_DEFAULT_BASE_2 0x384
|
||||
#define PAS16_DEFAULT_BASE_3 0x38c
|
||||
#define PAS16_DEFAULT_BASE_4 0x288
|
||||
|
||||
#define PAS16_DEFAULT_BOARD_1_IRQ 10
|
||||
#define PAS16_DEFAULT_BOARD_2_IRQ 12
|
||||
#define PAS16_DEFAULT_BOARD_3_IRQ 14
|
||||
#define PAS16_DEFAULT_BOARD_4_IRQ 15
|
||||
|
||||
|
||||
/*
|
||||
* The Pro Audio Spectrum boards are I/O mapped. They use a Zilog 5380
|
||||
* SCSI controller, which is the equivalent of NCR's 5380. "Pseudo-DMA"
|
||||
* architecture is used, where a PAL drives the DMA signals on the 5380
|
||||
* allowing fast, blind transfers with proper handshaking.
|
||||
*/
|
||||
|
||||
|
||||
/* The Time-out Counter register is used to safe-guard against a stuck
|
||||
* bus (in the case of RDY driven handshake) or a stuck byte (if 16-Bit
|
||||
* DMA conversion is used). The counter uses a 28.224MHz clock
|
||||
* divided by 14 as its clock source. In the case of a stuck byte in
|
||||
* the holding register, an interrupt is generated (and mixed with the
|
||||
* one with the drive) using the CD-ROM interrupt pointer.
|
||||
*/
|
||||
|
||||
#define P_TIMEOUT_COUNTER_REG 0x4000
|
||||
#define P_TC_DISABLE 0x80 /* Set to 0 to enable timeout int. */
|
||||
/* Bits D6-D0 contain timeout count */
|
||||
|
||||
|
||||
#define P_TIMEOUT_STATUS_REG_OFFSET 0x4001
|
||||
#define P_TS_TIM 0x80 /* check timeout status */
|
||||
/* Bits D6-D4 N/U */
|
||||
#define P_TS_ARM_DRQ_INT 0x08 /* Arm DRQ Int. When set high,
|
||||
* the next rising edge will
|
||||
* cause a CD-ROM interrupt.
|
||||
* When set low, the interrupt
|
||||
* will be cleared. There is
|
||||
* no status available for
|
||||
* this interrupt.
|
||||
*/
|
||||
#define P_TS_ENABLE_TO_ERR_INTERRUPT /* Enable timeout error int. */
|
||||
#define P_TS_ENABLE_WAIT /* Enable Wait */
|
||||
|
||||
#define P_TS_CT 0x01 /* clear timeout. Note: writing
|
||||
* to this register clears the
|
||||
* timeout error int. or status
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The data register reads/writes to/from the 5380 in pseudo-DMA mode
|
||||
*/
|
||||
|
||||
#define P_DATA_REG_OFFSET 0x5c00 /* rw */
|
||||
|
||||
#define P_STATUS_REG_OFFSET 0x5c01 /* ro */
|
||||
#define P_ST_RDY 0x80 /* 5380 DDRQ Status */
|
||||
|
||||
#define P_IRQ_STATUS 0x5c03
|
||||
#define P_IS_IRQ 0x80 /* DIRQ status */
|
||||
|
||||
#define PCB_CONFIG 0x803
|
||||
#define MASTER_ADDRESS_PTR 0x9a01 /* Fixed position - no relo */
|
||||
#define SYS_CONFIG_4 0x8003
|
||||
#define WAIT_STATE 0xbc00
|
||||
#define OPERATION_MODE_1 0xec03
|
||||
#define IO_CONFIG_3 0xf002
|
||||
|
||||
#define NCR5380_implementation_fields /* none */
|
||||
|
||||
#define PAS16_io_port(reg) (instance->io_port + pas16_offset[(reg)])
|
||||
|
||||
#define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) )
|
||||
#define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) )
|
||||
|
||||
#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize)
|
||||
#define NCR5380_dma_recv_setup pas16_pread
|
||||
#define NCR5380_dma_send_setup pas16_pwrite
|
||||
#define NCR5380_dma_residual(instance) (0)
|
||||
|
||||
#define NCR5380_intr pas16_intr
|
||||
#define NCR5380_queue_command pas16_queue_command
|
||||
#define NCR5380_abort pas16_abort
|
||||
#define NCR5380_bus_reset pas16_bus_reset
|
||||
#define NCR5380_info pas16_info
|
||||
|
||||
/* 15 14 12 10 7 5 3
|
||||
1101 0100 1010 1000 */
|
||||
|
||||
#define PAS16_IRQS 0xd4a8
|
||||
|
||||
#endif /* PAS16_H */
|
@ -4492,8 +4492,8 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
|
||||
* @num: the inbound queue number
|
||||
* @phy_id: the phy id which we wanted to start up.
|
||||
*/
|
||||
int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
|
||||
u8 phy_id)
|
||||
static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
|
||||
u8 phy_id)
|
||||
{
|
||||
struct phy_stop_req payload;
|
||||
struct inbound_queue_table *circularQ;
|
||||
|
@ -527,7 +527,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
|
||||
* pm8001_alloc_dev - find a empty pm8001_device
|
||||
* @pm8001_ha: our hba card information
|
||||
*/
|
||||
struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
|
||||
static struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
|
||||
{
|
||||
u32 dev;
|
||||
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)
|
||||
* Return Value
|
||||
* None
|
||||
*/
|
||||
void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index)
|
||||
static void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index)
|
||||
{
|
||||
struct pmcraid_ioarcb *ioarcb = &(cmd->ioa_cb->ioarcb);
|
||||
dma_addr_t dma_addr = cmd->ioa_cb_bus_addr;
|
||||
@ -401,7 +401,7 @@ static struct pmcraid_cmd *pmcraid_get_free_cmd(
|
||||
* Return Value:
|
||||
* nothing
|
||||
*/
|
||||
void pmcraid_return_cmd(struct pmcraid_cmd *cmd)
|
||||
static void pmcraid_return_cmd(struct pmcraid_cmd *cmd)
|
||||
{
|
||||
struct pmcraid_instance *pinstance = cmd->drv_inst;
|
||||
unsigned long lock_flags;
|
||||
@ -1710,7 +1710,7 @@ static struct pmcraid_ioasc_error *pmcraid_get_error_info(u32 ioasc)
|
||||
* @ioasc: ioasc code
|
||||
* @cmd: pointer to command that resulted in 'ioasc'
|
||||
*/
|
||||
void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd)
|
||||
static void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd)
|
||||
{
|
||||
struct pmcraid_ioasc_error *error_info = pmcraid_get_error_info(ioasc);
|
||||
|
||||
@ -3137,7 +3137,7 @@ static int pmcraid_eh_host_reset_handler(struct scsi_cmnd *scmd)
|
||||
* returns pointer pmcraid_ioadl_desc, initialized to point to internal
|
||||
* or external IOADLs
|
||||
*/
|
||||
struct pmcraid_ioadl_desc *
|
||||
static struct pmcraid_ioadl_desc *
|
||||
pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount)
|
||||
{
|
||||
struct pmcraid_ioadl_desc *ioadl;
|
||||
|
@ -278,16 +278,6 @@
|
||||
struct req_que;
|
||||
struct qla_tgt_sess;
|
||||
|
||||
/*
|
||||
* (sd.h is not exported, hence local inclusion)
|
||||
* Data Integrity Field tuple.
|
||||
*/
|
||||
struct sd_dif_tuple {
|
||||
__be16 guard_tag; /* Checksum */
|
||||
__be16 app_tag; /* Opaque storage */
|
||||
__be32 ref_tag; /* Target LBA or indirect LBA */
|
||||
};
|
||||
|
||||
/*
|
||||
* SCSI Request Block
|
||||
*/
|
||||
|
@ -1828,7 +1828,7 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
|
||||
if (scsi_prot_sg_count(cmd)) {
|
||||
uint32_t i, j = 0, k = 0, num_ent;
|
||||
struct scatterlist *sg;
|
||||
struct sd_dif_tuple *spt;
|
||||
struct t10_pi_tuple *spt;
|
||||
|
||||
/* Patch the corresponding protection tags */
|
||||
scsi_for_each_prot_sg(cmd, sg,
|
||||
|
@ -899,12 +899,12 @@ qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha)
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||
|
||||
while (((qla2x00_reset_active(vha)) || ha->dpc_active ||
|
||||
ha->flags.mbox_busy) ||
|
||||
test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
|
||||
test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
break;
|
||||
while ((qla2x00_reset_active(vha) || ha->dpc_active ||
|
||||
ha->flags.mbox_busy) ||
|
||||
test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
|
||||
test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
break;
|
||||
msleep(1000);
|
||||
}
|
||||
}
|
||||
@ -4694,7 +4694,7 @@ retry_unlock:
|
||||
qla83xx_wait_logic();
|
||||
retry++;
|
||||
ql_dbg(ql_dbg_p3p, base_vha, 0xb064,
|
||||
"Failed to release IDC lock, retyring=%d\n", retry);
|
||||
"Failed to release IDC lock, retrying=%d\n", retry);
|
||||
goto retry_unlock;
|
||||
}
|
||||
} else if (retry < 10) {
|
||||
@ -4702,7 +4702,7 @@ retry_unlock:
|
||||
qla83xx_wait_logic();
|
||||
retry++;
|
||||
ql_dbg(ql_dbg_p3p, base_vha, 0xb065,
|
||||
"Failed to read drv-lockid, retyring=%d\n", retry);
|
||||
"Failed to read drv-lockid, retrying=%d\n", retry);
|
||||
goto retry_unlock;
|
||||
}
|
||||
|
||||
@ -4718,7 +4718,7 @@ retry_unlock2:
|
||||
qla83xx_wait_logic();
|
||||
retry++;
|
||||
ql_dbg(ql_dbg_p3p, base_vha, 0xb066,
|
||||
"Failed to release IDC lock, retyring=%d\n", retry);
|
||||
"Failed to release IDC lock, retrying=%d\n", retry);
|
||||
goto retry_unlock2;
|
||||
}
|
||||
}
|
||||
|
@ -1843,7 +1843,7 @@ static uint32_t ql4_84xx_poll_wait_for_ready(struct scsi_qla_host *ha,
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1,
|
||||
static uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1,
|
||||
uint32_t addr3, uint32_t mask, uint32_t addr,
|
||||
uint32_t *data_ptr)
|
||||
{
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/uuid.h>
|
||||
#include <linux/t10-pi.h>
|
||||
|
||||
#include <net/checksum.h>
|
||||
|
||||
@ -627,7 +628,7 @@ static LIST_HEAD(sdebug_host_list);
|
||||
static DEFINE_SPINLOCK(sdebug_host_list_lock);
|
||||
|
||||
static unsigned char *fake_storep; /* ramdisk storage */
|
||||
static struct sd_dif_tuple *dif_storep; /* protection info */
|
||||
static struct t10_pi_tuple *dif_storep; /* protection info */
|
||||
static void *map_storep; /* provisioning map */
|
||||
|
||||
static unsigned long map_size;
|
||||
@ -682,7 +683,7 @@ static void *fake_store(unsigned long long lba)
|
||||
return fake_storep + lba * sdebug_sector_size;
|
||||
}
|
||||
|
||||
static struct sd_dif_tuple *dif_store(sector_t sector)
|
||||
static struct t10_pi_tuple *dif_store(sector_t sector)
|
||||
{
|
||||
sector = sector_div(sector, sdebug_store_sectors);
|
||||
|
||||
@ -1349,7 +1350,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
||||
} else if (0x86 == cmd[2]) { /* extended inquiry */
|
||||
arr[1] = cmd[2]; /*sanity */
|
||||
arr[3] = 0x3c; /* number of following entries */
|
||||
if (sdebug_dif == SD_DIF_TYPE3_PROTECTION)
|
||||
if (sdebug_dif == T10_PI_TYPE3_PROTECTION)
|
||||
arr[4] = 0x4; /* SPT: GRD_CHK:1 */
|
||||
else if (have_dif_prot)
|
||||
arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
|
||||
@ -2430,7 +2431,7 @@ static __be16 dif_compute_csum(const void *buf, int len)
|
||||
return csum;
|
||||
}
|
||||
|
||||
static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
|
||||
static int dif_verify(struct t10_pi_tuple *sdt, const void *data,
|
||||
sector_t sector, u32 ei_lba)
|
||||
{
|
||||
__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,
|
||||
be16_to_cpu(csum));
|
||||
return 0x01;
|
||||
}
|
||||
if (sdebug_dif == SD_DIF_TYPE1_PROTECTION &&
|
||||
if (sdebug_dif == T10_PI_TYPE1_PROTECTION &&
|
||||
be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
|
||||
pr_err("REF check failed on sector %lu\n",
|
||||
(unsigned long)sector);
|
||||
return 0x03;
|
||||
}
|
||||
if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
|
||||
if (sdebug_dif == T10_PI_TYPE2_PROTECTION &&
|
||||
be32_to_cpu(sdt->ref_tag) != ei_lba) {
|
||||
pr_err("REF check failed on sector %lu\n",
|
||||
(unsigned long)sector);
|
||||
@ -2504,7 +2505,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
|
||||
unsigned int sectors, u32 ei_lba)
|
||||
{
|
||||
unsigned int i;
|
||||
struct sd_dif_tuple *sdt;
|
||||
struct t10_pi_tuple *sdt;
|
||||
sector_t sector;
|
||||
|
||||
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)
|
||||
break;
|
||||
}
|
||||
if (unlikely(have_dif_prot && check_prot)) {
|
||||
if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
|
||||
if (sdebug_dif == T10_PI_TYPE2_PROTECTION &&
|
||||
(cmd[1] & 0xe0)) {
|
||||
mk_sense_invalid_opcode(scp);
|
||||
return check_condition_result;
|
||||
}
|
||||
if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION ||
|
||||
sdebug_dif == SD_DIF_TYPE3_PROTECTION) &&
|
||||
if ((sdebug_dif == T10_PI_TYPE1_PROTECTION ||
|
||||
sdebug_dif == T10_PI_TYPE3_PROTECTION) &&
|
||||
(cmd[1] & 0xe0) == 0)
|
||||
sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
|
||||
"to DIF device\n");
|
||||
@ -2696,7 +2697,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
|
||||
unsigned int sectors, u32 ei_lba)
|
||||
{
|
||||
int ret;
|
||||
struct sd_dif_tuple *sdt;
|
||||
struct t10_pi_tuple *sdt;
|
||||
void *daddr;
|
||||
sector_t sector = start_sec;
|
||||
int ppage_offset;
|
||||
@ -2722,7 +2723,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
|
||||
}
|
||||
|
||||
for (ppage_offset = 0; ppage_offset < piter.length;
|
||||
ppage_offset += sizeof(struct sd_dif_tuple)) {
|
||||
ppage_offset += sizeof(struct t10_pi_tuple)) {
|
||||
/* If we're at the end of the current
|
||||
* data page advance to the next one
|
||||
*/
|
||||
@ -2893,13 +2894,13 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
||||
break;
|
||||
}
|
||||
if (unlikely(have_dif_prot && check_prot)) {
|
||||
if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
|
||||
if (sdebug_dif == T10_PI_TYPE2_PROTECTION &&
|
||||
(cmd[1] & 0xe0)) {
|
||||
mk_sense_invalid_opcode(scp);
|
||||
return check_condition_result;
|
||||
}
|
||||
if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION ||
|
||||
sdebug_dif == SD_DIF_TYPE3_PROTECTION) &&
|
||||
if ((sdebug_dif == T10_PI_TYPE1_PROTECTION ||
|
||||
sdebug_dif == T10_PI_TYPE3_PROTECTION) &&
|
||||
(cmd[1] & 0xe0) == 0)
|
||||
sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
|
||||
"to DIF device\n");
|
||||
@ -3135,13 +3136,13 @@ static int resp_comp_write(struct scsi_cmnd *scp,
|
||||
num = cmd[13]; /* 1 to a maximum of 255 logical blocks */
|
||||
if (0 == num)
|
||||
return 0; /* degenerate case, not an error */
|
||||
if (sdebug_dif == SD_DIF_TYPE2_PROTECTION &&
|
||||
if (sdebug_dif == T10_PI_TYPE2_PROTECTION &&
|
||||
(cmd[1] & 0xe0)) {
|
||||
mk_sense_invalid_opcode(scp);
|
||||
return check_condition_result;
|
||||
}
|
||||
if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION ||
|
||||
sdebug_dif == SD_DIF_TYPE3_PROTECTION) &&
|
||||
if ((sdebug_dif == T10_PI_TYPE1_PROTECTION ||
|
||||
sdebug_dif == T10_PI_TYPE3_PROTECTION) &&
|
||||
(cmd[1] & 0xe0) == 0)
|
||||
sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
|
||||
"to DIF device\n");
|
||||
@ -4939,12 +4940,11 @@ static int __init scsi_debug_init(void)
|
||||
}
|
||||
|
||||
switch (sdebug_dif) {
|
||||
|
||||
case SD_DIF_TYPE0_PROTECTION:
|
||||
case T10_PI_TYPE0_PROTECTION:
|
||||
break;
|
||||
case SD_DIF_TYPE1_PROTECTION:
|
||||
case SD_DIF_TYPE2_PROTECTION:
|
||||
case SD_DIF_TYPE3_PROTECTION:
|
||||
case T10_PI_TYPE1_PROTECTION:
|
||||
case T10_PI_TYPE2_PROTECTION:
|
||||
case T10_PI_TYPE3_PROTECTION:
|
||||
have_dif_prot = true;
|
||||
break;
|
||||
|
||||
@ -5026,7 +5026,7 @@ static int __init scsi_debug_init(void)
|
||||
if (sdebug_dix) {
|
||||
int dif_size;
|
||||
|
||||
dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
|
||||
dif_size = sdebug_store_sectors * sizeof(struct t10_pi_tuple);
|
||||
dif_storep = vmalloc(dif_size);
|
||||
|
||||
pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep);
|
||||
@ -5480,19 +5480,19 @@ static int sdebug_driver_probe(struct device * dev)
|
||||
|
||||
switch (sdebug_dif) {
|
||||
|
||||
case SD_DIF_TYPE1_PROTECTION:
|
||||
case T10_PI_TYPE1_PROTECTION:
|
||||
hprot = SHOST_DIF_TYPE1_PROTECTION;
|
||||
if (sdebug_dix)
|
||||
hprot |= SHOST_DIX_TYPE1_PROTECTION;
|
||||
break;
|
||||
|
||||
case SD_DIF_TYPE2_PROTECTION:
|
||||
case T10_PI_TYPE2_PROTECTION:
|
||||
hprot = SHOST_DIF_TYPE2_PROTECTION;
|
||||
if (sdebug_dix)
|
||||
hprot |= SHOST_DIX_TYPE2_PROTECTION;
|
||||
break;
|
||||
|
||||
case SD_DIF_TYPE3_PROTECTION:
|
||||
case T10_PI_TYPE3_PROTECTION:
|
||||
hprot = SHOST_DIF_TYPE3_PROTECTION;
|
||||
if (sdebug_dix)
|
||||
hprot |= SHOST_DIX_TYPE3_PROTECTION;
|
||||
|
@ -86,12 +86,14 @@ extern void scsi_device_unbusy(struct scsi_device *sdev);
|
||||
extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
|
||||
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
|
||||
extern void scsi_run_host_queues(struct Scsi_Host *shost);
|
||||
extern void scsi_requeue_run_queue(struct work_struct *work);
|
||||
extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);
|
||||
extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev);
|
||||
extern int scsi_mq_setup_tags(struct Scsi_Host *shost);
|
||||
extern void scsi_mq_destroy_tags(struct Scsi_Host *shost);
|
||||
extern int scsi_init_queue(void);
|
||||
extern void scsi_exit_queue(void);
|
||||
extern void scsi_evt_thread(struct work_struct *work);
|
||||
struct request_queue;
|
||||
struct request;
|
||||
extern struct kmem_cache *scsi_sdb_cache;
|
||||
|
@ -217,8 +217,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
|
||||
struct scsi_device *sdev;
|
||||
int display_failure_msg = 1, ret;
|
||||
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
|
||||
extern void scsi_evt_thread(struct work_struct *work);
|
||||
extern void scsi_requeue_run_queue(struct work_struct *work);
|
||||
|
||||
sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
|
||||
GFP_ATOMIC);
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pr.h>
|
||||
#include <linux/t10-pi.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
@ -314,7 +315,7 @@ protection_type_store(struct device *dev, struct device_attribute *attr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val >= 0 && val <= SD_DIF_TYPE3_PROTECTION)
|
||||
if (val >= 0 && val <= T10_PI_TYPE3_PROTECTION)
|
||||
sdkp->protection_type = val;
|
||||
|
||||
return count;
|
||||
@ -332,7 +333,7 @@ protection_mode_show(struct device *dev, struct device_attribute *attr,
|
||||
dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type);
|
||||
dix = scsi_host_dix_capable(sdp->host, sdkp->protection_type);
|
||||
|
||||
if (!dix && scsi_host_dix_capable(sdp->host, SD_DIF_TYPE0_PROTECTION)) {
|
||||
if (!dix && scsi_host_dix_capable(sdp->host, T10_PI_TYPE0_PROTECTION)) {
|
||||
dif = 0;
|
||||
dix = 1;
|
||||
}
|
||||
@ -608,7 +609,7 @@ static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd,
|
||||
scmd->prot_flags |= SCSI_PROT_GUARD_CHECK;
|
||||
}
|
||||
|
||||
if (dif != SD_DIF_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */
|
||||
if (dif != T10_PI_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */
|
||||
scmd->prot_flags |= SCSI_PROT_REF_INCREMENT;
|
||||
|
||||
if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false)
|
||||
@ -1031,7 +1032,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
|
||||
else
|
||||
protect = 0;
|
||||
|
||||
if (protect && sdkp->protection_type == SD_DIF_TYPE2_PROTECTION) {
|
||||
if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) {
|
||||
SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC);
|
||||
|
||||
if (unlikely(SCpnt->cmnd == NULL)) {
|
||||
@ -1997,7 +1998,7 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
|
||||
|
||||
type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
|
||||
|
||||
if (type > SD_DIF_TYPE3_PROTECTION)
|
||||
if (type > T10_PI_TYPE3_PROTECTION)
|
||||
ret = -ENODEV;
|
||||
else if (scsi_host_dif_capable(sdp->host, type))
|
||||
ret = 1;
|
||||
|
@ -156,27 +156,6 @@ static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t b
|
||||
return blocks * sdev->sector_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* A DIF-capable target device can be formatted with different
|
||||
* protection schemes. Currently 0 through 3 are defined:
|
||||
*
|
||||
* Type 0 is regular (unprotected) I/O
|
||||
*
|
||||
* Type 1 defines the contents of the guard and reference tags
|
||||
*
|
||||
* Type 2 defines the contents of the guard and reference tags and
|
||||
* uses 32-byte commands to seed the latter
|
||||
*
|
||||
* Type 3 defines the contents of the guard tag only
|
||||
*/
|
||||
|
||||
enum sd_dif_target_protection_types {
|
||||
SD_DIF_TYPE0_PROTECTION = 0x0,
|
||||
SD_DIF_TYPE1_PROTECTION = 0x1,
|
||||
SD_DIF_TYPE2_PROTECTION = 0x2,
|
||||
SD_DIF_TYPE3_PROTECTION = 0x3,
|
||||
};
|
||||
|
||||
/*
|
||||
* Look up the DIX operation based on whether the command is read or
|
||||
* write and whether dix and dif are enabled.
|
||||
@ -239,15 +218,6 @@ static inline unsigned int sd_prot_flag_mask(unsigned int prot_op)
|
||||
return flag_mask[prot_op];
|
||||
}
|
||||
|
||||
/*
|
||||
* Data Integrity Field tuple.
|
||||
*/
|
||||
struct sd_dif_tuple {
|
||||
__be16 guard_tag; /* Checksum */
|
||||
__be16 app_tag; /* Opaque storage */
|
||||
__be32 ref_tag; /* Target LBA or indirect LBA */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
||||
|
||||
extern void sd_dif_config_host(struct scsi_disk *);
|
||||
|
@ -60,14 +60,14 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
|
||||
|
||||
/* Enable DMA of protection information */
|
||||
if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) {
|
||||
if (type == SD_DIF_TYPE3_PROTECTION)
|
||||
if (type == T10_PI_TYPE3_PROTECTION)
|
||||
bi.profile = &t10_pi_type3_ip;
|
||||
else
|
||||
bi.profile = &t10_pi_type1_ip;
|
||||
|
||||
bi.flags |= BLK_INTEGRITY_IP_CHECKSUM;
|
||||
} else
|
||||
if (type == SD_DIF_TYPE3_PROTECTION)
|
||||
if (type == T10_PI_TYPE3_PROTECTION)
|
||||
bi.profile = &t10_pi_type3_crc;
|
||||
else
|
||||
bi.profile = &t10_pi_type1_crc;
|
||||
@ -82,7 +82,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
|
||||
if (!sdkp->ATO)
|
||||
goto out;
|
||||
|
||||
if (type == SD_DIF_TYPE3_PROTECTION)
|
||||
if (type == T10_PI_TYPE3_PROTECTION)
|
||||
bi.tag_size = sizeof(u16) + sizeof(u32);
|
||||
else
|
||||
bi.tag_size = sizeof(u16);
|
||||
@ -121,7 +121,7 @@ void sd_dif_prepare(struct scsi_cmnd *scmd)
|
||||
|
||||
sdkp = scsi_disk(scmd->request->rq_disk);
|
||||
|
||||
if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
|
||||
if (sdkp->protection_type == T10_PI_TYPE3_PROTECTION)
|
||||
return;
|
||||
|
||||
phys = scsi_prot_ref_tag(scmd);
|
||||
@ -172,7 +172,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
|
||||
|
||||
sdkp = scsi_disk(scmd->request->rq_disk);
|
||||
|
||||
if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0)
|
||||
if (sdkp->protection_type == T10_PI_TYPE3_PROTECTION || good_bytes == 0)
|
||||
return;
|
||||
|
||||
intervals = good_bytes / scsi_prot_interval(scmd);
|
||||
|
@ -79,18 +79,7 @@ static void sg_proc_cleanup(void);
|
||||
*/
|
||||
#define SG_MAX_CDB_SIZE 252
|
||||
|
||||
/*
|
||||
* Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
|
||||
* Then when using 32 bit integers x * m may overflow during the calculation.
|
||||
* Replacing muldiv(x) by muldiv(x)=((x % d) * m) / d + int(x / d) * m
|
||||
* calculates the same, but prevents the overflow when both m and d
|
||||
* are "small" numbers (like HZ and USER_HZ).
|
||||
* Of course an overflow is inavoidable if the result of muldiv doesn't fit
|
||||
* in 32 bits.
|
||||
*/
|
||||
#define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
|
||||
|
||||
#define SG_DEFAULT_TIMEOUT MULDIV(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
|
||||
#define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
|
||||
|
||||
int sg_big_buff = SG_DEF_RESERVED_SIZE;
|
||||
/* 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)
|
||||
return result;
|
||||
if (val < 0)
|
||||
return -EIO;
|
||||
if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
|
||||
val = MULDIV (INT_MAX, USER_HZ, HZ);
|
||||
if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
|
||||
val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
|
||||
INT_MAX);
|
||||
sfp->timeout_user = val;
|
||||
sfp->timeout = MULDIV (val, HZ, USER_HZ);
|
||||
sfp->timeout = mult_frac(val, HZ, USER_HZ);
|
||||
|
||||
return 0;
|
||||
case SG_GET_TIMEOUT: /* N.B. User receives timeout as return value */
|
||||
|
54
drivers/scsi/smartpqi/Kconfig
Normal file
54
drivers/scsi/smartpqi/Kconfig
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# Kernel configuration file for the SMARTPQI
|
||||
#
|
||||
# Copyright (c) 2016 Microsemi Corporation
|
||||
# Copyright (c) 2016 PMC-Sierra, Inc.
|
||||
# (mailto:esc.storagedev@microsemi.com)
|
||||
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# of the License.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# NO WARRANTY
|
||||
# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
||||
# solely responsible for determining the appropriateness of using and
|
||||
# distributing the Program and assumes all risks associated with its
|
||||
# exercise of rights under this Agreement, including but not limited to
|
||||
# the risks and costs of program errors, damage to or loss of data,
|
||||
# programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
# DISCLAIMER OF LIABILITY
|
||||
# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||
|
||||
config SCSI_SMARTPQI
|
||||
tristate "Microsemi PQI Driver"
|
||||
depends on PCI && SCSI && !S390
|
||||
select SCSI_SAS_ATTRS
|
||||
select RAID_ATTRS
|
||||
---help---
|
||||
This driver supports Microsemi PQI controllers.
|
||||
|
||||
<http://www.microsemi.com>
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called smartpqi.
|
||||
|
||||
Note: the aacraid driver will not manage a smartpqi
|
||||
controller. You need to enable smartpqi for smartpqi
|
||||
controllers. For more information, please see
|
||||
Documentation/scsi/smartpqi.txt
|
3
drivers/scsi/smartpqi/Makefile
Normal file
3
drivers/scsi/smartpqi/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
ccflags-y += -I.
|
||||
obj-m += smartpqi.o
|
||||
smartpqi-objs := smartpqi_init.o smartpqi_sis.o smartpqi_sas_transport.o
|
1136
drivers/scsi/smartpqi/smartpqi.h
Normal file
1136
drivers/scsi/smartpqi/smartpqi.h
Normal file
File diff suppressed because it is too large
Load Diff
6303
drivers/scsi/smartpqi/smartpqi_init.c
Normal file
6303
drivers/scsi/smartpqi/smartpqi_init.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user