提交 4dfddf50 编写于 作者: L Linus Torvalds

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
  ...
......@@ -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.
- 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.
- When a context is no longer needed, the user shall detach from
the context via the DK_CXLFLASH_DETACH ioctl.
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
- A close on fd2 will invalidate the tokens. This operation is not
required by the user.
- 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
......
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.
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.
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.
......@@ -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 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
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);
......
/**
* 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;
};
......
此差异已折叠。
/**
* 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 */
此差异已折叠。
/**
* 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);
......
此差异已折叠。
/**
* 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;
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 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;
};
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 */
......
此差异已折叠。
/**
* 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);
unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba);
int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type,
struct be_cmd_get_def_gateway_resp *gateway);
unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba);
int mgmt_set_gateway(struct beiscsi_hba *phba,
struct iscsi_iface_param_info *gateway_param);
unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba);
int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
unsigned int *s_handle);
unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba);
unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba);
unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async);
int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
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 @@ void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
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 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
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 @@ csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req)
/* 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 @@ static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp)
* 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 @@ static int cxlflash_probe(struct pci_dev *pdev,
* @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 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg)
* @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 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.
* 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.
*
* 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 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
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 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
* 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 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
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 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
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",
......
此差异已折叠。
/*
* 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];
......
......@@ -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;
......
此差异已折叠。
此差异已折叠。
......@@ -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
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部