Prior to this change, the addressing method wasn't getting set, and
so the LUN field could be set incorrectly in some instances.
This fix should allow for LUN numbers up to 16777215 (and return an error
for anything larger, which wouldn't fit into the flat addressing model).
Submitted by: scottl (in part)
This bug manifested itself after repeated device arrivals and
departures. The root of the problem was that the last entry in the
reply array wasn't initialized/allocated. So every time we got
around to that event, we had a bogus address.
There were a couple more problems with the code that are also fixed:
- The reply mechanism was being treated as sequential (indexed by
sc->replycurindex) even though the spec says that the driver
should use the ReplyFrameAddress field of the post queue
descriptor to figure out where the reply is. There is no
guarantee that the reply descriptors will be used in sequential
order.
- The second word of the reply post queue descriptor wasn't being
checked in mps_intr_locked() to make sure that it wasn't
0xffffffff. So the driver could potentially come across a
partially DMAed descriptor.
- The number of replies allocated was one less than the actual
size of the queue. Instead, it was the size of the number of
replies that can be used at one time. (Which is one less than
the size of the queue.)
mps.c: When initializing the entries in the reply free
queue, make sure we initialize the full number that
we tell the chip we have (sc->fqdepth), not the
number that can be used at any one time (sc->num_replies).
When allocating replies, make sure we allocate the
number of replies that we've told the chip exist,
not just the number that can be used simultaneously.
Use the ReplyFrameAddress field of the post queue
descriptor to figure out which reply is being
referenced. This is what the spec says to do, and
the spec doesn't guarantee that the replies will be
used in order.
Put a check in to verify that the reply address passed
back from the card is valid. (Panic if it isn't, we'll
panic when we try to deference the reply pointer in any
case.)
In mps_intr_locked(), verify that the second word of the
post queue descriptor is not 0xffffffff in addition to
verifying that the unused flag is not set, so we can
make sure we didn't get a partially DMAed descriptor.
Remove references to sc->replycurindex, it isn't needed
now.
mpsvar.h: Remove replycurindex from the softc, it isn't needed now.
Reviewed by: scottl
This includes support in the kernel, camcontrol(8), libcam and the mps(4)
driver for SMP passthrough.
The CAM SCSI probe code has been modified to fetch Inquiry VPD page 0x00
to determine supported pages, and will now fetch page 0x83 in addition to
page 0x80 if supported.
Add two new CAM CCBs, XPT_SMP_IO, and XPT_GDEV_ADVINFO. The SMP CCB is
intended for SMP requests and responses. The ADVINFO is currently used to
fetch cached VPD page 0x83 data from the transport layer, but is intended
to be extensible to fetch other types of device-specific data.
SMP-only devices are not currently represented in the CAM topology, and so
the current semantics are that the SIM will route SMP CCBs to either the
addressed device, if it contains an SMP target, or its parent, if it
contains an SMP target. (This is noted in cam_ccb.h, since it will change
later once we have the ability to have SMP-only devices in CAM's topology.)
smp_all.c,
smp_all.h: New helper routines for SMP. This includes
SMP request building routines, response parsing
routines, error decoding routines, and structure
definitions for a number of SMP commands.
libcam/Makefile: Add smp_all.c to libcam, so that SMP functionality
is available to userland applications.
camcontrol.8,
camcontrol.c: Add smp passthrough support to camcontrol. Several
new subcommands are now available:
'smpcmd' functions much like 'cmd', except that it
allows the user to send generic SMP commands.
'smprg' sends the SMP report general command, and
displays the decoded output. It will automatically
fetch extended output if it is available.
'smppc' sends the SMP phy control command, with any
number of potential options. Among other things,
this allows the user to reset a phy on a SAS
expander, or disable a phy on an expander.
'smpmaninfo' sends the SMP report manufacturer
information and displays the decoded output.
'smpphylist' displays a list of phys on an
expander, and the CAM devices attached to those
phys, if any.
cam.h,
cam.c: Add a status value for SMP errors
(CAM_SMP_STATUS_ERROR).
Add a missing description for CAM_SCSI_IT_NEXUS_LOST.
Add support for SMP commands to cam_error_string().
cam_ccb.h: Rename the CAM_DIR_RESV flag to CAM_DIR_BOTH. SMP
commands are by nature bi-directional, and we may
need to support bi-directional SCSI commands later.
Add the XPT_SMP_IO CCB. Since SMP commands are
bi-directional, there are pointers for both the
request and response.
Add a fill routine for SMP CCBs.
Add the XPT_GDEV_ADVINFO CCB. This is currently
used to fetch cached page 0x83 data from the
transport later, but is extensible to fetch many
other types of data.
cam_periph.c: Add support in cam_periph_mapmem() for XPT_SMP_IO
and XPT_GDEV_ADVINFO CCBs.
cam_xpt.c: Add support for executing XPT_SMP_IO CCBs.
cam_xpt_internal.h: Add fields for VPD pages 0x00 and 0x83 in struct
cam_ed.
scsi_all.c: Add scsi_get_sas_addr(), a function that parses
VPD page 0x83 data and pulls out a SAS address.
scsi_all.h: Add VPD page 0x00 and 0x83 structures, and a
prototype for scsi_get_sas_addr().
scsi_pass.c: Add support for mapping buffers in XPT_SMP_IO and
XPT_GDEV_ADVINFO CCBs.
scsi_xpt.c: In the SCSI probe code, first ask the device for
VPD page 0x00. If any VPD pages are supported,
that page is required to be implemented. Based on
the response, we may probe for the serial number
(page 0x80) or device id (page 0x83).
Add support for the XPT_GDEV_ADVINFO CCB.
sys/conf/files: Add smp_all.c.
mps.c: Add support for passing in a uio in mps_map_command(),
so we can map a S/G list at once.
Add support for SMP passthrough commands in
mps_data_cb(). SMP is a special case, because the
first buffer in the S/G list is outbound and the
second buffer is inbound.
Add support for warning the user if the busdma code
comes back with more buffers than will work for the
command. This will, for example, help the user
determine why an SMP command failed if busdma comes
back with three buffers.
mps_pci.c: Add sys/uio.h.
mps_sas.c: Add the SAS address and the parent handle to the
list of fields we pull from device page 0 and cache
in struct mpssas_target. These are needed for SMP
passthrough.
Add support for the XPT_SMP_IO CCB. For now, this
CCB is routed to the addressed device if it supports
SMP, or to its parent if it does not and the parent
does. This is necessary because CAM does not
currently support SMP-only nodes in the topology.
Make SMP passthrough support conditional on
__FreeBSD_version >= 900026. This will make it
easier to MFC this change to the driver without
MFCing the CAM changes as well.
mps_user.c: Un-staticize mpi_init_sge() so we can use it for
the SMP passthrough code.
mpsvar.h: Add a uio and iovecs into struct mps_command for
SMP passthrough commands.
Add a cm_max_segs field to struct mps_command so
that we can warn the user if busdma comes back with
too many segments.
Clear the cm_reply when a command gets freed. If
it is not cleared, reply frames will eventually get
freed into the pool multiple times and corrupt the
pool. (This fix is from scottl.)
Add a prototype for mpi_init_sge().
sys/param.h: Bump __FreeBSD_version to 900026 for the for the
inclusion of the XPT_GDEV_ADVINFO and XPT_SMP_IO
CAM CCBs.
- fix the leak of command struct on error
- simplify the cleanup logic
- EINPROGRESS is not a fatal error
- buggy comment and error message
Reviewed by: ken
controller, but make it optional.
After a problem report from Andrew Boyer, it looks like the LSI
chip may have issues (the watchdog timer fired) if too many aborts
are sent down to the chip at the same time. We know that task
management commands are serialized, and although the manual doesn't
say it, it may be a good idea to just send one at a time.
But, since I'm not certain that this is necessary, add a tunable
and sysctl variable (hw.mps.%d.allow_multiple_tm_cmds) to control
the driver's behavior.
mps.c: Add support for the sysctl and tunable, and add a
comment about the possible return values to
mps_map_command().
mps_sas.c: Run all task management commands through two new
routines, mpssas_issue_tm_request() and
mpssas_complete_tm_request().
This allows us to optionally serialize task
management commands. Also, change things so that
the response to a task management command always
comes back through the callback. (Before it could
come via the callback or the return value.)
mpsvar.h: Add softc variables for the list of active task
management commands, the number of active commands,
and whether we should allow multiple active task
management commands. Add an active command flag.
mps.4: Describe the new sysctl/loader tunable variable.
Sponsored by: Spectra Logic Corporation
When the driver is completely saturated with commands (1024 in the
case of the SAS2008 in my test system), I/O stops. If we tell CAM
that we have one less command slot than we have actually allocated,
everything works fine. We also need a few extra command slots to
allow for aborts and other task management commands to be sent down.
This needs more investigation to determine the root cause, but for
now this fixes things in my testing.
mps.c: Change a printf() to mps_printf().
mps_sas.c: Subtract 5 command slots when we tell CAM how many
commands we can handle.
Add some commented-out logic to print the contents
the CDBs for timed-out commands. This can help
in debugging devices that are timing out. This
will be uncommented once I bring some CAM changes in.
Reported by: Andrew Boyer <aboyer at averesystems dot com>
According to the MPT2 spec, task management commands are
serialized, and so no I/O should start while task management
commands are active.
So, to comply with that, freeze the SIM queue before we send any
task management commands (abort, target reset, etc.) down to the
IOC. We unfreeze the queue once the task management command
completes.
It isn't clear from the spec whether multiple simultaneous task
management commands are supported. Right now it is possible to
have multiple outstanding task management commands, especially in
the abort case. Multiple outstanding aborts do complete
successfully, so it may be supported.
We also don't yet have any recovery mechanism (e.g. reset the IOC)
if the task management command fails.
Bring in a driver for the LSI Logic MPT2 6Gb SAS controllers.
This driver supports basic I/O, and works with SAS and SATA drives and
expanders.
Basic error recovery works (i.e. timeouts and aborts) as well.
Integrated RAID isn't supported yet, and there are some known bugs.
So this isn't ready for production use, but is certainly ready for
testing and additional development. For the moment, new commits to this
driver should go into the FreeBSD Perforce repository first
(//depot/projects/mps/...) and then get merged into -current once
they've been vetted.
This has only been added to the amd64 GENERIC, since that is the only
architecture I have tested this driver with.
Submitted by: scottl
Discussed with: imp, gibbs, will
Sponsored by: Yahoo, Spectra Logic Corporation