2005-01-05 22:34:37 +00:00
|
|
|
/*-
|
1998-09-15 06:36:34 +00:00
|
|
|
* Implementation of SCSI Direct Access Peripheral driver for CAM.
|
|
|
|
*
|
|
|
|
* Copyright (c) 1997 Justin T. Gibbs.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions, and the following disclaimer,
|
|
|
|
* without modification, immediately at the beginning of the file.
|
|
|
|
* 2. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2003-06-10 18:14:05 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <sys/param.h>
|
2000-05-21 23:57:52 +00:00
|
|
|
|
|
|
|
#ifdef _KERNEL
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
2000-05-05 09:59:14 +00:00
|
|
|
#include <sys/bio.h>
|
2001-07-09 19:18:00 +00:00
|
|
|
#include <sys/sysctl.h>
|
2003-09-03 12:31:03 +00:00
|
|
|
#include <sys/taskqueue.h>
|
2007-04-15 08:49:19 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mutex.h>
|
1999-10-01 09:34:10 +00:00
|
|
|
#include <sys/conf.h>
|
2007-04-23 18:01:44 +00:00
|
|
|
#include <sys/devicestat.h>
|
1999-08-21 06:24:40 +00:00
|
|
|
#include <sys/eventhandler.h>
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <sys/malloc.h>
|
1999-08-09 10:35:05 +00:00
|
|
|
#include <sys/cons.h>
|
2013-04-26 16:17:04 +00:00
|
|
|
#include <sys/endian.h>
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
#include <geom/geom.h>
|
2003-04-01 15:06:26 +00:00
|
|
|
#include <geom/geom_disk.h>
|
2007-04-23 18:01:44 +00:00
|
|
|
#endif /* _KERNEL */
|
2003-04-01 15:06:26 +00:00
|
|
|
|
2000-05-21 23:57:52 +00:00
|
|
|
#ifndef _KERNEL
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#endif /* _KERNEL */
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
#include <cam/cam.h>
|
|
|
|
#include <cam/cam_ccb.h>
|
|
|
|
#include <cam/cam_periph.h>
|
|
|
|
#include <cam/cam_xpt_periph.h>
|
2007-04-15 08:49:19 +00:00
|
|
|
#include <cam/cam_sim.h>
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
#include <cam/scsi/scsi_message.h>
|
|
|
|
|
2000-05-21 23:57:52 +00:00
|
|
|
#ifndef _KERNEL
|
|
|
|
#include <cam/scsi/scsi_da.h>
|
|
|
|
#endif /* !_KERNEL */
|
|
|
|
|
|
|
|
#ifdef _KERNEL
|
1998-09-15 06:36:34 +00:00
|
|
|
typedef enum {
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_STATE_PROBE_RC,
|
|
|
|
DA_STATE_PROBE_RC16,
|
|
|
|
DA_STATE_PROBE_LBP,
|
|
|
|
DA_STATE_PROBE_BLK_LIMITS,
|
2013-04-26 16:31:03 +00:00
|
|
|
DA_STATE_PROBE_BDC,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_STATE_PROBE_ATA,
|
1998-09-15 06:36:34 +00:00
|
|
|
DA_STATE_NORMAL
|
|
|
|
} da_state;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
DA_FLAG_PACK_INVALID = 0x001,
|
|
|
|
DA_FLAG_NEW_PACK = 0x002,
|
|
|
|
DA_FLAG_PACK_LOCKED = 0x004,
|
|
|
|
DA_FLAG_PACK_REMOVABLE = 0x008,
|
|
|
|
DA_FLAG_NEED_OTAG = 0x020,
|
|
|
|
DA_FLAG_WENT_IDLE = 0x040,
|
|
|
|
DA_FLAG_RETRY_UA = 0x080,
|
2003-10-08 07:12:30 +00:00
|
|
|
DA_FLAG_OPEN = 0x100,
|
2011-12-23 19:12:02 +00:00
|
|
|
DA_FLAG_SCTX_INIT = 0x200,
|
2012-04-12 12:58:14 +00:00
|
|
|
DA_FLAG_CAN_RC16 = 0x400,
|
|
|
|
DA_FLAG_PROBED = 0x800
|
1998-09-15 06:36:34 +00:00
|
|
|
} da_flags;
|
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
typedef enum {
|
|
|
|
DA_Q_NONE = 0x00,
|
1998-12-02 17:35:28 +00:00
|
|
|
DA_Q_NO_SYNC_CACHE = 0x01,
|
2003-08-22 16:35:53 +00:00
|
|
|
DA_Q_NO_6_BYTE = 0x02,
|
2011-12-23 00:10:17 +00:00
|
|
|
DA_Q_NO_PREVENT = 0x04,
|
|
|
|
DA_Q_4K = 0x08
|
1998-10-08 05:46:38 +00:00
|
|
|
} da_quirks;
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
typedef enum {
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_CCB_PROBE_RC = 0x01,
|
|
|
|
DA_CCB_PROBE_RC16 = 0x02,
|
|
|
|
DA_CCB_PROBE_LBP = 0x03,
|
|
|
|
DA_CCB_PROBE_BLK_LIMITS = 0x04,
|
2013-04-26 16:31:03 +00:00
|
|
|
DA_CCB_PROBE_BDC = 0x05,
|
|
|
|
DA_CCB_PROBE_ATA = 0x06,
|
|
|
|
DA_CCB_BUFFER_IO = 0x07,
|
|
|
|
DA_CCB_WAITING = 0x08,
|
|
|
|
DA_CCB_DUMP = 0x0A,
|
|
|
|
DA_CCB_DELETE = 0x0B,
|
|
|
|
DA_CCB_TUR = 0x0C,
|
1998-09-15 06:36:34 +00:00
|
|
|
DA_CCB_TYPE_MASK = 0x0F,
|
|
|
|
DA_CCB_RETRY_UA = 0x10
|
|
|
|
} da_ccb_state;
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
/*
|
|
|
|
* Order here is important for method choice
|
|
|
|
*
|
|
|
|
* We prefer ATA_TRIM as tests run against a Sandforce 2281 SSD attached to
|
|
|
|
* LSI 2008 (mps) controller (FW: v12, Drv: v14) resulted 20% quicker deletes
|
|
|
|
* using ATA_TRIM than the corresponding UNMAP results for a real world mysql
|
|
|
|
* import taking 5mins.
|
|
|
|
*
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
typedef enum {
|
|
|
|
DA_DELETE_NONE,
|
|
|
|
DA_DELETE_DISABLE,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_DELETE_ATA_TRIM,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
DA_DELETE_UNMAP,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_DELETE_WS16,
|
|
|
|
DA_DELETE_WS10,
|
|
|
|
DA_DELETE_ZERO,
|
2013-05-02 15:03:30 +00:00
|
|
|
DA_DELETE_MIN = DA_DELETE_ATA_TRIM,
|
2013-04-26 16:17:04 +00:00
|
|
|
DA_DELETE_MAX = DA_DELETE_ZERO
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
} da_delete_methods;
|
|
|
|
|
|
|
|
static const char *da_delete_method_names[] =
|
2013-05-02 15:03:30 +00:00
|
|
|
{ "NONE", "DISABLE", "ATA_TRIM", "UNMAP", "WS16", "WS10", "ZERO" };
|
2013-04-26 16:17:04 +00:00
|
|
|
static const char *da_delete_method_desc[] =
|
2013-05-02 15:03:30 +00:00
|
|
|
{ "NONE", "DISABLED", "ATA TRIM", "UNMAP", "WRITE SAME(16) with UNMAP",
|
2013-04-26 16:17:04 +00:00
|
|
|
"WRITE SAME(10) with UNMAP", "ZERO" };
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/* Offsets into our private area for storing information */
|
|
|
|
#define ccb_state ppriv_field0
|
|
|
|
#define ccb_bp ppriv_ptr1
|
|
|
|
|
|
|
|
struct disk_params {
|
|
|
|
u_int8_t heads;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
u_int32_t cylinders;
|
1998-09-15 06:36:34 +00:00
|
|
|
u_int8_t secs_per_track;
|
|
|
|
u_int32_t secsize; /* Number of bytes/sector */
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
u_int64_t sectors; /* total number sectors */
|
2011-12-23 00:10:17 +00:00
|
|
|
u_int stripesize;
|
|
|
|
u_int stripeoffset;
|
1998-09-15 06:36:34 +00:00
|
|
|
};
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
#define UNMAP_RANGE_MAX 0xffffffff
|
|
|
|
#define UNMAP_HEAD_SIZE 8
|
|
|
|
#define UNMAP_RANGE_SIZE 16
|
|
|
|
#define UNMAP_MAX_RANGES 2048 /* Protocol Max is 4095 */
|
|
|
|
#define UNMAP_BUF_SIZE ((UNMAP_MAX_RANGES * UNMAP_RANGE_SIZE) + \
|
|
|
|
UNMAP_HEAD_SIZE)
|
|
|
|
|
|
|
|
#define WS10_MAX_BLKS 0xffff
|
|
|
|
#define WS16_MAX_BLKS 0xffffffff
|
|
|
|
#define ATA_TRIM_MAX_RANGES ((UNMAP_BUF_SIZE / \
|
|
|
|
(ATA_DSM_RANGE_SIZE * ATA_DSM_BLK_SIZE)) * ATA_DSM_BLK_SIZE)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
struct da_softc {
|
2000-04-15 05:54:02 +00:00
|
|
|
struct bio_queue_head bio_queue;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio_queue_head delete_queue;
|
|
|
|
struct bio_queue_head delete_run_queue;
|
2000-05-26 02:09:24 +00:00
|
|
|
SLIST_ENTRY(da_softc) links;
|
|
|
|
LIST_HEAD(, ccb_hdr) pending_ccbs;
|
1998-09-15 06:36:34 +00:00
|
|
|
da_state state;
|
|
|
|
da_flags flags;
|
1998-10-08 05:46:38 +00:00
|
|
|
da_quirks quirks;
|
2013-03-29 22:58:15 +00:00
|
|
|
int sort_io_queue;
|
1998-12-02 17:35:28 +00:00
|
|
|
int minimum_cmd_size;
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
int error_inject;
|
1998-09-15 06:36:34 +00:00
|
|
|
int ordered_tag_count;
|
2003-03-15 11:00:56 +00:00
|
|
|
int outstanding_cmds;
|
2013-04-26 16:17:04 +00:00
|
|
|
int trim_max_ranges;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
int delete_running;
|
2012-07-29 11:51:48 +00:00
|
|
|
int tur;
|
2013-04-26 16:17:04 +00:00
|
|
|
int delete_available; /* Delete methods possibly available */
|
|
|
|
uint32_t unmap_max_ranges;
|
|
|
|
uint32_t unmap_max_lba;
|
|
|
|
uint64_t ws_max_blks;
|
|
|
|
da_delete_methods delete_method;
|
1998-09-15 06:36:34 +00:00
|
|
|
struct disk_params params;
|
2004-02-18 21:36:53 +00:00
|
|
|
struct disk *disk;
|
1998-09-15 06:36:34 +00:00
|
|
|
union ccb saved_ccb;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
struct task sysctl_task;
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
struct sysctl_ctx_list sysctl_ctx;
|
|
|
|
struct sysctl_oid *sysctl_tree;
|
2007-04-15 08:49:19 +00:00
|
|
|
struct callout sendordered_c;
|
2010-06-07 17:41:34 +00:00
|
|
|
uint64_t wwpn;
|
2013-04-26 16:17:04 +00:00
|
|
|
uint8_t unmap_buf[UNMAP_BUF_SIZE];
|
2012-01-26 18:09:28 +00:00
|
|
|
struct scsi_read_capacity_data_long rcaplong;
|
2012-07-29 11:51:48 +00:00
|
|
|
struct callout mediapoll_c;
|
1998-09-15 06:36:34 +00:00
|
|
|
};
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
#define dadeleteflag(softc, delete_method, enable) \
|
|
|
|
if (enable) { \
|
|
|
|
softc->delete_available |= (1 << delete_method); \
|
|
|
|
} else { \
|
|
|
|
softc->delete_available &= ~(1 << delete_method); \
|
|
|
|
}
|
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
struct da_quirk_entry {
|
|
|
|
struct scsi_inquiry_pattern inq_pat;
|
|
|
|
da_quirks quirks;
|
|
|
|
};
|
|
|
|
|
2000-08-29 22:09:23 +00:00
|
|
|
static const char quantum[] = "QUANTUM";
|
|
|
|
static const char microp[] = "MICROP";
|
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
static struct da_quirk_entry da_quirk_table[] =
|
|
|
|
{
|
2003-08-25 18:14:43 +00:00
|
|
|
/* SPI, FC devices */
|
2001-11-17 14:46:22 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Fujitsu M2513A MO drives.
|
|
|
|
* Tested devices: M2513A2 firmware versions 1200 & 1300.
|
|
|
|
* (dip switch selects whether T_DIRECT or T_OPTICAL device)
|
|
|
|
* Reported by: W.Scholten <whs@xs4all.nl>
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* See above. */
|
|
|
|
{T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-10-08 05:46:38 +00:00
|
|
|
{
|
1998-10-12 17:16:47 +00:00
|
|
|
/*
|
|
|
|
* This particular Fujitsu drive doesn't like the
|
|
|
|
* synchronize cache command.
|
|
|
|
* Reported by: Tom Jackson <toj@gorilla.net>
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This drive doesn't like the synchronize cache command
|
|
|
|
* either. Reported by: Matthew Jacob <mjacob@feral.com>
|
|
|
|
* in NetBSD PR kern/6027, August 24, 1998.
|
1998-10-08 05:46:38 +00:00
|
|
|
*/
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, microp, "2217*", "*"},
|
1998-10-12 17:16:47 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
1998-10-13 23:34:54 +00:00
|
|
|
},
|
1999-01-05 20:43:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This drive doesn't like the synchronize cache command
|
|
|
|
* either. Reported by: Hellmuth Michaelis (hm@kts.org)
|
|
|
|
* (PR 8882).
|
|
|
|
*/
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, microp, "2112*", "*"},
|
1999-01-05 20:43:41 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-10-13 23:34:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
|
|
|
* Reported by: Blaz Zupan <blaz@gold.amis.net>
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
1998-12-02 17:35:28 +00:00
|
|
|
},
|
2000-08-29 22:09:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
2005-04-14 04:46:46 +00:00
|
|
|
* Reported by: Blaz Zupan <blaz@gold.amis.net>
|
2000-08-29 22:09:23 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "MAVERICK 540S", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-04-14 04:05:00 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
2005-04-14 04:46:46 +00:00
|
|
|
* Reported by: walter@pelissero.de
|
2005-04-14 04:05:00 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS540S", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-12-02 17:35:28 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Doesn't work correctly with 6 byte reads/writes.
|
|
|
|
* Returns illegal request, and points to byte 9 of the
|
|
|
|
* 6-byte CDB.
|
|
|
|
* Reported by: Adam McDougall <bsdx@spawnet.com>
|
|
|
|
*/
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 4*", "*"},
|
1998-12-02 17:35:28 +00:00
|
|
|
/*quirks*/ DA_Q_NO_6_BYTE
|
|
|
|
},
|
|
|
|
{
|
2003-08-22 16:35:53 +00:00
|
|
|
/* See above. */
|
2000-08-29 22:09:23 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 2*", "*"},
|
1998-12-02 17:35:28 +00:00
|
|
|
/*quirks*/ DA_Q_NO_6_BYTE
|
2000-03-15 22:44:03 +00:00
|
|
|
},
|
2005-04-14 04:12:45 +00:00
|
|
|
{
|
2005-04-14 04:46:46 +00:00
|
|
|
/*
|
|
|
|
* Doesn't like the synchronize cache command.
|
|
|
|
* Reported by: walter@pelissero.de
|
|
|
|
*/
|
2005-04-14 04:12:45 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CP3500*", "*"},
|
2006-11-26 17:15:54 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
2005-04-14 04:12:45 +00:00
|
|
|
},
|
2003-12-08 06:29:38 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* The CISS RAID controllers do not support SYNC_CACHE
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "COMPAQ", "RAID*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2003-08-25 18:14:43 +00:00
|
|
|
/* USB mass storage devices supported by umass(4) */
|
2003-08-22 05:43:30 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* EXATELECOM (Sigmatel) i-Bead 100/105 USB Flash MP3 Player
|
|
|
|
* PR: kern/51675
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "EXATEL", "i-BEAD10*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2003-08-22 05:58:23 +00:00
|
|
|
{
|
|
|
|
/*
|
2004-04-19 04:14:09 +00:00
|
|
|
* Power Quotient Int. (PQI) USB flash key
|
|
|
|
* PR: kern/53067
|
2003-08-22 05:58:23 +00:00
|
|
|
*/
|
2004-04-19 04:14:09 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "USB Flash Disk*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2006-11-26 17:15:54 +00:00
|
|
|
},
|
2003-08-22 16:35:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Creative Nomad MUVO mp3 player (USB)
|
|
|
|
* PR: kern/53094
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "NOMAD_MUVO", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
2004-04-19 04:14:09 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Jungsoft NEXDISK USB flash key
|
|
|
|
* PR: kern/54737
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "JUNGSOFT", "NEXDISK*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* FreeDik USB Mini Data Drive
|
|
|
|
* PR: kern/54786
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "FreeDik*", "Mini Data Drive",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Sigmatel USB Flash MP3 Player
|
|
|
|
* PR: kern/57046
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "SigmaTel", "MSCN", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
2004-05-02 19:24:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Neuros USB Digital Audio Computer
|
|
|
|
* PR: kern/63645
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "NEUROS", "dig. audio comp.",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2004-07-18 05:39:14 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SEAGRAND NP-900 MP3 Player
|
|
|
|
* PR: kern/64563
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "SEAGRAND", "NP-900*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
2004-08-08 09:08:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* iRiver iFP MP3 player (with UMS Firmware)
|
|
|
|
* PR: kern/54881, i386/63941, kern/66124
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "iRiver", "iFP*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
2004-08-12 23:17:09 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Frontier Labs NEX IA+ Digital Audio Player, rev 1.10/0.01
|
|
|
|
* PR: kern/70158
|
|
|
|
*/
|
2005-04-14 03:59:48 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "FL" , "Nex*", "*"},
|
2004-08-12 23:17:09 +00:00
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-04-14 04:31:48 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* ZICPlay USB MP3 Player with FM
|
|
|
|
* PR: kern/75057
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "ACTIONS*" , "USB DISK*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-05-05 18:48:41 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* TEAC USB floppy mechanisms
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "TEAC" , "FD-05*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-06-09 17:35:04 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kingston DataTraveler II+ USB Pen-Drive.
|
|
|
|
* Reported by: Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
|
|
|
*/
|
2005-12-19 03:43:48 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston" , "DataTraveler II+",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2005-06-09 17:35:04 +00:00
|
|
|
},
|
2012-10-15 12:33:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* USB DISK Pro PMAP
|
|
|
|
* Reported by: jhs
|
|
|
|
* PR: usb/96381
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, " ", "USB DISK Pro", "PMAP"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2005-12-19 03:27:28 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Motorola E398 Mobile Phone (TransFlash memory card).
|
|
|
|
* Reported by: Wojciech A. Koszek <dunstan@FreeBSD.czest.pl>
|
|
|
|
* PR: usb/89889
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Motorola" , "Motorola Phone",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-01-13 11:33:40 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Qware BeatZkey! Pro
|
|
|
|
* PR: usb/79164
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "GENERIC", "USB DISK DEVICE",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Time DPA20B 1GB MP3 Player
|
|
|
|
* PR: usb/81846
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB2.0*", "(FS) FLASH DISK*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
Add Product IDs :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
Add scsi_da.c quirks :
- Samsung USB key 128Mb [1]
- Kingston DataTraveler 2.0 [2]
- Creative MuVo Slim [3]
- United MP 5512 Portable MP3 Player [4]
- Sandisk Cruzer Micro 128MB [5], [9]
- PNY USB Flash keys [6], [7], [8]
Add umass.c quirks :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
PR: usb/90081 [1],
usb/89196 [2],
kern/86131 [3],
usb/80487 [4],
usb/75970 [5],
usb/75578 [6],
usb/72344 [7],
usb/65436 [8],
usb/70835 [9]
Submitted by: Henri-Pierre CHARLES <hpc@prism.uvsq.fr> [1],
Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua> [2],
Erich Rickheit KSC <rickheit-fbp@numachi.com> [3],
tnu@chania.di.uoa.gr [4],
Bram Abbekerk <bram@abbekerk.demon.nl> [5],
Thomas Pornin <pornin@bolet.org> [6],
parv <parv@pair.com> [7],
Peter D. Quilty <pdquilty@adelphia.net> [8],
Raymundo M. Vega <rvega@ms-smtp-03-eri0.socal.rr.com> [9]
Approved by: iedowse
MFC after: 3 days
2006-01-26 00:35:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung USB key 128Mb
|
|
|
|
* PR: usb/90081
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB-DISK", "FreeDik-FlashUsb",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Kingston DataTraveler 2.0 USB Flash memory.
|
|
|
|
* PR: usb/89196
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler 2.0",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Creative MUVO Slim mp3 player (USB)
|
|
|
|
* PR: usb/86131
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "MuVo Slim",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* United MP5512 Portable MP3 Player (2-in-1 USB DISK/MP3)
|
|
|
|
* PR: usb/80487
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "MUSIC DISK",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SanDisk Micro Cruzer 128MB
|
|
|
|
* PR: usb/75970
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "SanDisk" , "Micro Cruzer",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-03-13 22:26:33 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* TOSHIBA TransMemory USB sticks
|
2006-03-18 21:13:14 +00:00
|
|
|
* PR: kern/94660
|
2006-03-13 22:26:33 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "TOSHIBA", "TransMemory",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
Add Product IDs :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
Add scsi_da.c quirks :
- Samsung USB key 128Mb [1]
- Kingston DataTraveler 2.0 [2]
- Creative MuVo Slim [3]
- United MP 5512 Portable MP3 Player [4]
- Sandisk Cruzer Micro 128MB [5], [9]
- PNY USB Flash keys [6], [7], [8]
Add umass.c quirks :
- Sandisk Cruzer Micro 128MB [5]
- DANE-ELEC zMate 512MB USB flash drive [7]
- Attache 256MB USB 2.0 Flash Drive [8]
- Sandisk Cruzer Micro 256MB [9]
PR: usb/90081 [1],
usb/89196 [2],
kern/86131 [3],
usb/80487 [4],
usb/75970 [5],
usb/75578 [6],
usb/72344 [7],
usb/65436 [8],
usb/70835 [9]
Submitted by: Henri-Pierre CHARLES <hpc@prism.uvsq.fr> [1],
Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua> [2],
Erich Rickheit KSC <rickheit-fbp@numachi.com> [3],
tnu@chania.di.uoa.gr [4],
Bram Abbekerk <bram@abbekerk.demon.nl> [5],
Thomas Pornin <pornin@bolet.org> [6],
parv <parv@pair.com> [7],
Peter D. Quilty <pdquilty@adelphia.net> [8],
Raymundo M. Vega <rvega@ms-smtp-03-eri0.socal.rr.com> [9]
Approved by: iedowse
MFC after: 3 days
2006-01-26 00:35:54 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* PNY USB Flash keys
|
|
|
|
* PR: usb/75578, usb/72344, usb/65436
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "*" , "USB DISK*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-01-30 20:27:44 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Genesys 6-in-1 Card Reader
|
2006-03-18 18:28:13 +00:00
|
|
|
* PR: usb/94647
|
2006-01-30 20:27:44 +00:00
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "STORAGE DEVICE*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-10-07 19:04:23 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Rekam Digital CAMERA
|
|
|
|
* PR: usb/98713
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "CAMERA*", "4MP-9J6*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-10-07 18:28:55 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* iRiver H10 MP3 player
|
|
|
|
* PR: usb/102547
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "H10*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2006-11-26 17:15:54 +00:00
|
|
|
},
|
2007-06-28 06:12:55 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* iRiver U10 MP3 player
|
|
|
|
* PR: usb/92306
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "U10*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2006-11-26 17:13:24 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* X-Micro Flash Disk
|
|
|
|
* PR: usb/96901
|
|
|
|
*/
|
2006-11-26 17:18:31 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "X-Micro", "Flash Disk",
|
2006-11-26 17:13:24 +00:00
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-01-22 04:34:03 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* EasyMP3 EM732X USB 2.0 Flash MP3 Player
|
|
|
|
* PR: usb/96546
|
|
|
|
*/
|
2007-01-23 17:29:31 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "EM732X", "MP3 Player*",
|
2008-01-12 19:24:55 +00:00
|
|
|
"1.00"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2007-01-22 04:34:03 +00:00
|
|
|
},
|
2007-06-28 04:51:19 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Denver MP3 player
|
|
|
|
* PR: usb/107101
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "DENVER", "MP3 PLAYER",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 04:34:45 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Philips USB Key Audio KEY013
|
|
|
|
* PR: usb/68412
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "PHILIPS", "Key*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
|
|
|
|
},
|
2007-06-30 05:03:03 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* JNC MP3 Player
|
|
|
|
* PR: usb/94439
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "JNC*" , "MP3 Player*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 05:21:18 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* SAMSUNG MP0402H
|
|
|
|
* PR: usb/108427
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "MP0402H", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 05:24:25 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* I/O Magic USB flash - Giga Bank
|
|
|
|
* PR: usb/108810
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "GS-Magic", "stor*", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 14:41:30 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* JoyFly 128mb USB Flash Drive
|
|
|
|
* PR: 96133
|
|
|
|
*/
|
2007-07-01 17:42:07 +00:00
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "Flash Disk*",
|
2007-06-30 14:41:30 +00:00
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-06-30 14:44:09 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* ChipsBnk usb stick
|
|
|
|
* PR: 103702
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "ChipsBnk", "USB*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2008-12-23 09:11:05 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Storcase (Kingston) InfoStation IFS FC2/SATA-R 201A
|
|
|
|
* PR: 129858
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "IFS", "FC2/SATA-R*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2008-07-09 17:00:14 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Samsung YP-U3 mp3-player
|
|
|
|
* PR: 125398
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Samsung", "YP-U3",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2007-12-11 06:41:38 +00:00
|
|
|
{
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Netac", "OnlyDisk*",
|
|
|
|
"2000"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
2009-08-26 21:14:28 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Sony Cyber-Shot DSC cameras
|
|
|
|
* PR: usb/137035
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
|
2011-12-23 00:10:17 +00:00
|
|
|
},
|
2013-02-22 17:45:32 +00:00
|
|
|
{
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler G3",
|
|
|
|
"1.00"}, /*quirks*/ DA_Q_NO_PREVENT
|
|
|
|
},
|
2011-12-23 00:10:17 +00:00
|
|
|
/* ATA/SATA devices over SAS/USB/... */
|
|
|
|
{
|
|
|
|
/* Hitachi Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "Hitachi", "H??????????E3*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG HD155UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HD155UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG HD204UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Samsung Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HD204UI*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST????DL*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST????DL", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST???DM*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST???DM*", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST????DM*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Barracuda Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST????DM", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9500423AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST950042", "3AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9500424AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST950042", "4AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9640423AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST964042", "3AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9640424AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST964042", "4AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750420AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "0AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750422AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "2AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST9750423AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST975042", "3AS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Thin Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "ST???LT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Seagate Momentus Thin Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ST???LT*", "*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD????RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "??RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD????RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "??RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD??????RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "????RS*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD??????RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Caviar Green Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "????RX*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD???PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "?PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD?????PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Black Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PKT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD???PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "?PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "ATA", "WDC WD?????PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* WDC Scorpio Blue Advanced Format (4k) drives */
|
|
|
|
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PVT*", "*" },
|
|
|
|
/*quirks*/DA_Q_4K
|
|
|
|
},
|
2012-04-29 22:28:15 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Olympus FE-210 camera
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "FE210*",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* LG UP3S MP3 player
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "LG", "UP3S",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Laser MP3-2GA13 MP3 player
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "(HS) Flash Disk",
|
|
|
|
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
2012-10-16 17:49:14 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* LaCie external 250GB Hard drive des by Porsche
|
|
|
|
* Submitted by: Ben Stuyts <ben@altesco.nl>
|
|
|
|
* PR: 121474
|
|
|
|
*/
|
|
|
|
{T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "HM250JI", "*"},
|
|
|
|
/*quirks*/ DA_Q_NO_SYNC_CACHE
|
|
|
|
},
|
1998-10-08 05:46:38 +00:00
|
|
|
};
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
static disk_strategy_t dastrategy;
|
2003-02-21 19:00:48 +00:00
|
|
|
static dumper_t dadump;
|
1998-09-15 06:36:34 +00:00
|
|
|
static periph_init_t dainit;
|
|
|
|
static void daasync(void *callback_arg, u_int32_t code,
|
|
|
|
struct cam_path *path, void *arg);
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
static void dasysctlinit(void *context, int pending);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
|
2013-04-26 16:22:54 +00:00
|
|
|
static int dadeletemaxsysctl(SYSCTL_HANDLER_ARGS);
|
2013-04-26 15:31:52 +00:00
|
|
|
static void dadeletemethodset(struct da_softc *softc,
|
2013-01-10 11:57:46 +00:00
|
|
|
da_delete_methods delete_method);
|
2013-04-26 16:22:54 +00:00
|
|
|
static off_t dadeletemaxsize(struct da_softc *softc,
|
|
|
|
da_delete_methods delete_method);
|
2013-04-26 16:17:04 +00:00
|
|
|
static void dadeletemethodchoose(struct da_softc *softc,
|
|
|
|
da_delete_methods default_method);
|
2013-05-02 14:37:23 +00:00
|
|
|
static void daprobedone(struct cam_periph *periph, union ccb *ccb);
|
2013-04-26 16:17:04 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static periph_ctor_t daregister;
|
|
|
|
static periph_dtor_t dacleanup;
|
|
|
|
static periph_start_t dastart;
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
static periph_oninv_t daoninvalidate;
|
1998-09-15 06:36:34 +00:00
|
|
|
static void dadone(struct cam_periph *periph,
|
|
|
|
union ccb *done_ccb);
|
|
|
|
static int daerror(union ccb *ccb, u_int32_t cam_flags,
|
|
|
|
u_int32_t sense_flags);
|
|
|
|
static void daprevent(struct cam_periph *periph, int action);
|
2012-04-12 12:58:14 +00:00
|
|
|
static void dareprobe(struct cam_periph *periph);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
static void dasetgeom(struct cam_periph *periph, uint32_t block_len,
|
2012-01-26 18:09:28 +00:00
|
|
|
uint64_t maxsector,
|
|
|
|
struct scsi_read_capacity_data_long *rcaplong,
|
|
|
|
size_t rcap_size);
|
1998-09-15 06:36:34 +00:00
|
|
|
static timeout_t dasendorderedtag;
|
1999-08-21 06:24:40 +00:00
|
|
|
static void dashutdown(void *arg, int howto);
|
2012-07-29 11:51:48 +00:00
|
|
|
static timeout_t damediapoll;
|
|
|
|
|
|
|
|
#ifndef DA_DEFAULT_POLL_PERIOD
|
|
|
|
#define DA_DEFAULT_POLL_PERIOD 3
|
|
|
|
#endif
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
#ifndef DA_DEFAULT_TIMEOUT
|
|
|
|
#define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */
|
|
|
|
#endif
|
|
|
|
|
2001-07-09 19:18:00 +00:00
|
|
|
#ifndef DA_DEFAULT_RETRY
|
|
|
|
#define DA_DEFAULT_RETRY 4
|
|
|
|
#endif
|
|
|
|
|
2006-11-02 21:12:37 +00:00
|
|
|
#ifndef DA_DEFAULT_SEND_ORDERED
|
|
|
|
#define DA_DEFAULT_SEND_ORDERED 1
|
|
|
|
#endif
|
|
|
|
|
2013-03-29 22:58:15 +00:00
|
|
|
#define DA_SIO (softc->sort_io_queue >= 0 ? \
|
|
|
|
softc->sort_io_queue : cam_sort_io_queues)
|
2006-11-02 21:12:37 +00:00
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
static int da_poll_period = DA_DEFAULT_POLL_PERIOD;
|
2001-07-09 19:18:00 +00:00
|
|
|
static int da_retry_count = DA_DEFAULT_RETRY;
|
|
|
|
static int da_default_timeout = DA_DEFAULT_TIMEOUT;
|
2006-11-02 21:12:37 +00:00
|
|
|
static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
|
2001-07-09 19:18:00 +00:00
|
|
|
|
2011-11-07 15:43:11 +00:00
|
|
|
static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
|
2001-07-09 19:18:00 +00:00
|
|
|
"CAM Direct Access Disk driver");
|
2012-07-29 11:51:48 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, poll_period, CTLFLAG_RW,
|
|
|
|
&da_poll_period, 0, "Media polling period in seconds");
|
|
|
|
TUNABLE_INT("kern.cam.da.poll_period", &da_poll_period);
|
2001-07-09 19:18:00 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW,
|
|
|
|
&da_retry_count, 0, "Normal I/O retry count");
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count);
|
2001-07-09 19:18:00 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
|
|
|
|
&da_default_timeout, 0, "Normal I/O timeout (in seconds)");
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
|
2012-07-11 23:00:26 +00:00
|
|
|
SYSCTL_INT(_kern_cam_da, OID_AUTO, send_ordered, CTLFLAG_RW,
|
2006-11-02 21:12:37 +00:00
|
|
|
&da_send_ordered, 0, "Send Ordered Tags");
|
2012-07-11 23:00:26 +00:00
|
|
|
TUNABLE_INT("kern.cam.da.send_ordered", &da_send_ordered);
|
2001-07-09 19:18:00 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* DA_ORDEREDTAG_INTERVAL determines how often, relative
|
|
|
|
* to the default timeout, we check to see whether an ordered
|
|
|
|
* tagged transaction is appropriate to prevent simple tag
|
|
|
|
* starvation. Since we'd like to ensure that there is at least
|
|
|
|
* 1/2 of the timeout length left for a starved transaction to
|
|
|
|
* complete after we've sent an ordered tag, we must poll at least
|
|
|
|
* four times in every timeout period. This takes care of the worst
|
|
|
|
* case where a starved transaction starts during an interval that
|
|
|
|
* meets the requirement "don't send an ordered tag" test so it takes
|
|
|
|
* us two intervals to determine that a tag must be sent.
|
|
|
|
*/
|
|
|
|
#ifndef DA_ORDEREDTAG_INTERVAL
|
|
|
|
#define DA_ORDEREDTAG_INTERVAL 4
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct periph_driver dadriver =
|
|
|
|
{
|
|
|
|
dainit, "da",
|
|
|
|
TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
|
|
|
|
};
|
|
|
|
|
2001-02-07 07:05:59 +00:00
|
|
|
PERIPHDRIVER_DECLARE(da, dadriver);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2011-11-07 06:44:47 +00:00
|
|
|
static MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
|
2007-05-14 21:48:53 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static int
|
2003-02-25 22:06:21 +00:00
|
|
|
daopen(struct disk *dp)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
int error;
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = (struct cam_periph *)dp->d_drv1;
|
2007-04-15 08:49:19 +00:00
|
|
|
if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
return (ENXIO);
|
2007-04-15 08:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cam_periph_lock(periph);
|
|
|
|
if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
|
|
|
|
cam_periph_unlock(periph);
|
|
|
|
cam_periph_release(periph);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
|
|
|
|
("daopen\n"));
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2013-04-27 12:46:04 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2012-04-12 12:58:14 +00:00
|
|
|
dareprobe(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2012-04-12 12:58:14 +00:00
|
|
|
/* Wait for the disk size update. */
|
2013-04-04 19:07:37 +00:00
|
|
|
error = cam_periph_sleep(periph, &softc->disk->d_mediasize, PRIBIO,
|
2012-04-12 12:58:14 +00:00
|
|
|
"dareprobe", 0);
|
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "unable to retrieve capacity data");
|
1998-10-07 02:57:57 +00:00
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
if (periph->flags & CAM_PERIPH_INVALID)
|
2012-04-12 12:58:14 +00:00
|
|
|
error = ENXIO;
|
2008-08-29 04:39:46 +00:00
|
|
|
|
2012-04-12 12:58:14 +00:00
|
|
|
if (error == 0 && (softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
|
|
|
|
(softc->quirks & DA_Q_NO_PREVENT) == 0)
|
|
|
|
daprevent(periph, PR_PREVENT);
|
2008-08-29 04:39:46 +00:00
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
if (error == 0) {
|
|
|
|
softc->flags &= ~DA_FLAG_PACK_INVALID;
|
|
|
|
softc->flags |= DA_FLAG_OPEN;
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unhold(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
cam_periph_unlock(periph);
|
2008-08-29 04:39:46 +00:00
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
if (error != 0)
|
2008-08-29 04:39:46 +00:00
|
|
|
cam_periph_release(periph);
|
2012-04-12 12:58:14 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-02-25 22:06:21 +00:00
|
|
|
daclose(struct disk *dp)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = (struct cam_periph *)dp->d_drv1;
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_lock(periph);
|
2012-06-20 18:35:36 +00:00
|
|
|
if (cam_periph_hold(periph, PRIBIO) != 0) {
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unlock(periph);
|
|
|
|
cam_periph_release(periph);
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
return (0);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
|
|
|
|
("daclose\n"));
|
|
|
|
|
2011-06-14 16:05:00 +00:00
|
|
|
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
|
1998-10-08 05:46:38 +00:00
|
|
|
union ccb *ccb;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2009-10-23 08:27:55 +00:00
|
|
|
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
scsi_synchronize_cache(&ccb->csio,
|
|
|
|
/*retries*/1,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
/*begin_lba*/0,/* Cover the whole disk */
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
5 * 60 * 1000);
|
|
|
|
|
2012-06-05 10:08:22 +00:00
|
|
|
cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
|
|
|
|
/*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
|
2004-02-18 21:36:53 +00:00
|
|
|
softc->disk->d_devstat);
|
1998-10-08 05:46:38 +00:00
|
|
|
xpt_release_ccb(ccb);
|
|
|
|
|
|
|
|
}
|
1998-09-19 04:59:35 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
|
2003-08-22 16:35:53 +00:00
|
|
|
if ((softc->quirks & DA_Q_NO_PREVENT) == 0)
|
|
|
|
daprevent(periph, PR_ALLOW);
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* If we've got removeable media, mark the blocksize as
|
|
|
|
* unavailable, since it could change when new media is
|
|
|
|
* inserted.
|
|
|
|
*/
|
2004-02-18 21:36:53 +00:00
|
|
|
softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
softc->flags &= ~DA_FLAG_OPEN;
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unhold(periph);
|
2008-12-17 10:49:03 +00:00
|
|
|
cam_periph_unlock(periph);
|
2008-12-19 14:31:40 +00:00
|
|
|
cam_periph_release(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static void
|
|
|
|
daschedule(struct cam_periph *periph)
|
|
|
|
{
|
|
|
|
struct da_softc *softc = (struct da_softc *)periph->softc;
|
|
|
|
uint32_t prio;
|
|
|
|
|
2013-01-11 16:10:11 +00:00
|
|
|
if (softc->state != DA_STATE_NORMAL)
|
|
|
|
return;
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Check if cam_periph_getccb() was called. */
|
|
|
|
prio = periph->immediate_priority;
|
|
|
|
|
|
|
|
/* Check if we have more work to do. */
|
|
|
|
if (bioq_first(&softc->bio_queue) ||
|
2012-07-29 11:51:48 +00:00
|
|
|
(!softc->delete_running && bioq_first(&softc->delete_queue)) ||
|
|
|
|
softc->tur) {
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
prio = CAM_PRIORITY_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Schedule CCB if any of above is true. */
|
|
|
|
if (prio != CAM_PRIORITY_NONE)
|
|
|
|
xpt_schedule(periph, prio);
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Actually translate the requested transfer into one the physical driver
|
|
|
|
* can understand. The transfer is described by a buf and will include
|
|
|
|
* only one physical transfer.
|
|
|
|
*/
|
|
|
|
static void
|
2000-04-15 05:54:02 +00:00
|
|
|
dastrategy(struct bio *bp)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
|
1998-09-15 06:36:34 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2007-04-15 08:49:19 +00:00
|
|
|
|
|
|
|
cam_periph_lock(periph);
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* If the device has been made invalid, error out
|
|
|
|
*/
|
|
|
|
if ((softc->flags & DA_FLAG_PACK_INVALID)) {
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unlock(periph);
|
2001-05-08 08:30:48 +00:00
|
|
|
biofinish(bp, NULL, ENXIO);
|
|
|
|
return;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2012-06-05 09:45:42 +00:00
|
|
|
|
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastrategy(%p)\n", bp));
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Place it in the queue of disk activities for this disk
|
2007-06-16 18:20:29 +00:00
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
if (bp->bio_cmd == BIO_DELETE) {
|
|
|
|
if (bp->bio_bcount == 0)
|
|
|
|
biodone(bp);
|
2013-03-29 22:58:15 +00:00
|
|
|
else if (DA_SIO)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_disksort(&softc->delete_queue, bp);
|
2013-03-29 22:58:15 +00:00
|
|
|
else
|
|
|
|
bioq_insert_tail(&softc->delete_queue, bp);
|
|
|
|
} else if (DA_SIO) {
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_disksort(&softc->bio_queue, bp);
|
2013-03-29 22:58:15 +00:00
|
|
|
} else {
|
|
|
|
bioq_insert_tail(&softc->bio_queue, bp);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Schedule ourselves for performing the work.
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
daschedule(periph);
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_unlock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-02-21 19:00:48 +00:00
|
|
|
dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
1998-12-11 03:54:43 +00:00
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
1999-10-01 09:34:10 +00:00
|
|
|
u_int secsize;
|
1998-12-11 03:54:43 +00:00
|
|
|
struct ccb_scsiio csio;
|
2003-02-21 19:00:48 +00:00
|
|
|
struct disk *dp;
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
int error = 0;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2003-02-21 19:00:48 +00:00
|
|
|
dp = arg;
|
2003-02-25 22:06:21 +00:00
|
|
|
periph = dp->d_drv1;
|
1998-09-15 06:36:34 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_lock(periph);
|
2002-03-31 22:28:03 +00:00
|
|
|
secsize = softc->params.secsize;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2007-04-18 05:14:16 +00:00
|
|
|
if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
|
|
|
|
cam_periph_unlock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
return (ENXIO);
|
2007-04-18 05:14:16 +00:00
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2002-03-31 22:28:03 +00:00
|
|
|
if (length > 0) {
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
csio.ccb_h.ccb_state = DA_CCB_DUMP;
|
|
|
|
scsi_read_write(&csio,
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
/*retries*/0,
|
1998-09-15 06:36:34 +00:00
|
|
|
dadone,
|
|
|
|
MSG_ORDERED_Q_TAG,
|
2013-03-19 15:01:50 +00:00
|
|
|
/*read*/SCSI_RW_WRITE,
|
1998-09-15 06:36:34 +00:00
|
|
|
/*byte2*/0,
|
1998-12-02 17:35:28 +00:00
|
|
|
/*minimum_cmd_size*/ softc->minimum_cmd_size,
|
2002-03-31 22:28:03 +00:00
|
|
|
offset / secsize,
|
|
|
|
length / secsize,
|
|
|
|
/*data_ptr*/(u_int8_t *) virtual,
|
|
|
|
/*dxfer_len*/length,
|
1998-09-15 06:36:34 +00:00
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
2012-02-02 19:02:15 +00:00
|
|
|
da_default_timeout * 1000);
|
1998-09-15 06:36:34 +00:00
|
|
|
xpt_polled_action((union ccb *)&csio);
|
|
|
|
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
error = cam_periph_error((union ccb *)&csio,
|
|
|
|
0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
|
|
|
|
if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
|
|
|
|
/*reduction*/0, /*timeout*/0, /*getcount_only*/0);
|
|
|
|
if (error != 0)
|
1998-10-08 05:46:38 +00:00
|
|
|
printf("Aborting dump due to I/O error.\n");
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
cam_periph_unlock(periph);
|
|
|
|
return (error);
|
2007-04-15 08:49:19 +00:00
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
1998-10-08 05:46:38 +00:00
|
|
|
/*
|
|
|
|
* Sync the disk cache contents to the physical media.
|
|
|
|
*/
|
|
|
|
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
|
|
|
|
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
1998-10-08 05:46:38 +00:00
|
|
|
csio.ccb_h.ccb_state = DA_CCB_DUMP;
|
|
|
|
scsi_synchronize_cache(&csio,
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
/*retries*/0,
|
1998-10-08 05:46:38 +00:00
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
/*begin_lba*/0,/* Cover the whole disk */
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
5 * 60 * 1000);
|
|
|
|
xpt_polled_action((union ccb *)&csio);
|
|
|
|
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
error = cam_periph_error((union ccb *)&csio,
|
|
|
|
0, SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR, NULL);
|
|
|
|
if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
|
|
|
|
/*reduction*/0, /*timeout*/0, /*getcount_only*/0);
|
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "Synchronize cache failed\n");
|
1998-10-08 05:46:38 +00:00
|
|
|
}
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_unlock(periph);
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
return (error);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
static int
|
|
|
|
dagetattr(struct bio *bp)
|
|
|
|
{
|
2012-10-12 17:18:24 +00:00
|
|
|
int ret;
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
struct cam_periph *periph;
|
|
|
|
|
|
|
|
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
|
2012-10-12 17:18:24 +00:00
|
|
|
cam_periph_lock(periph);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute,
|
|
|
|
periph->path);
|
2012-10-12 17:18:24 +00:00
|
|
|
cam_periph_unlock(periph);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
if (ret == 0)
|
|
|
|
bp->bio_completed = bp->bio_length;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static void
|
|
|
|
dainit(void)
|
|
|
|
{
|
|
|
|
cam_status status;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Install a global async callback. This callback will
|
|
|
|
* receive async callbacks like "new device found".
|
|
|
|
*/
|
2007-05-16 16:54:23 +00:00
|
|
|
status = xpt_register_async(AC_FOUND_DEVICE, daasync, NULL, NULL);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (status != CAM_REQ_CMP) {
|
|
|
|
printf("da: Failed to attach master async callback "
|
|
|
|
"due to status 0x%x!\n", status);
|
2006-11-02 21:12:37 +00:00
|
|
|
} else if (da_send_ordered) {
|
1998-10-08 05:46:38 +00:00
|
|
|
|
1999-08-21 06:24:40 +00:00
|
|
|
/* Register our shutdown event handler */
|
|
|
|
if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
|
2003-01-06 19:30:21 +00:00
|
|
|
NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
|
1999-08-21 06:24:40 +00:00
|
|
|
printf("dainit: shutdown event registration failed!\n");
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
/*
|
|
|
|
* Callback from GEOM, called when it has finished cleaning up its
|
|
|
|
* resources.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dadiskgonecb(struct disk *dp)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
|
|
|
|
periph = (struct cam_periph *)dp->d_drv1;
|
|
|
|
cam_periph_release(periph);
|
|
|
|
}
|
|
|
|
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
static void
|
|
|
|
daoninvalidate(struct cam_periph *periph)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* De-register any async callbacks.
|
|
|
|
*/
|
2007-05-16 16:54:23 +00:00
|
|
|
xpt_register_async(0, daasync, periph, periph->path);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
|
|
|
|
softc->flags |= DA_FLAG_PACK_INVALID;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return all queued I/O with ENXIO.
|
2010-08-20 17:20:05 +00:00
|
|
|
* XXX Handle any transactions queued to the card
|
|
|
|
* with XPT_ABORT_CCB.
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
*/
|
2003-04-01 15:06:26 +00:00
|
|
|
bioq_flush(&softc->bio_queue, NULL, ENXIO);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_flush(&softc->delete_queue, NULL, ENXIO);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
/*
|
|
|
|
* Tell GEOM that we've gone away, we'll get a callback when it is
|
|
|
|
* done cleaning up its resources.
|
|
|
|
*/
|
Fix a bug that caused some /dev entries to continue to exist after
the underlying drive had been hot-unplugged from the system. Here
is a specific example. Filesystem code had opened /dev/da1s1e.
Subsequently, the drive was hot-unplugged. This (correctly) caused
all of the associated /dev/da1* entries to be deleted. When the
filesystem later realized that the drive was gone it closed the
device, reducing the write-access counts to 0 on the geom providers
for da1s1e, da1s1, and da1. This caused geom to re-taste the
providers, resulting in the devices being created again. When the
drive was hot-plugged back in, it resulted in duplicate /dev entries
for da1s1e, da1s1, and da1.
This fix adds a new disk_gone() function which is called by CAM when a
drive goes away. It orphans all of the providers associated with the
drive, setting an error condition of ENXIO in each one. In addition,
we prevent a re-taste on last close for writing if an error condition
has been set in the provider.
Sponsored by: Isilon Systems
Reviewed by: phk
MFC after: 1 week
2005-11-18 02:43:49 +00:00
|
|
|
disk_gone(softc->disk);
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
xpt_print(periph->path, "lost device - %d outstanding, %d refs\n",
|
|
|
|
softc->outstanding_cmds, periph->refcount);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static void
|
|
|
|
dacleanup(struct cam_periph *periph)
|
|
|
|
{
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path, "removing device entry\n");
|
2009-02-11 22:29:09 +00:00
|
|
|
cam_periph_unlock(periph);
|
|
|
|
|
2003-03-26 04:38:39 +00:00
|
|
|
/*
|
|
|
|
* If we can't free the sysctl tree, oh well...
|
|
|
|
*/
|
2003-10-08 07:12:30 +00:00
|
|
|
if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
|
|
|
|
&& sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path, "can't remove sysctl context\n");
|
2003-03-26 04:38:39 +00:00
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
callout_drain(&softc->mediapoll_c);
|
2007-04-16 19:41:14 +00:00
|
|
|
disk_destroy(softc->disk);
|
2007-04-15 08:49:19 +00:00
|
|
|
callout_drain(&softc->sendordered_c);
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
free(softc, M_DEVBUF);
|
2009-02-11 22:29:09 +00:00
|
|
|
cam_periph_lock(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
daasync(void *callback_arg, u_int32_t code,
|
|
|
|
struct cam_path *path, void *arg)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
2012-07-29 11:51:48 +00:00
|
|
|
struct da_softc *softc;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
periph = (struct cam_periph *)callback_arg;
|
|
|
|
switch (code) {
|
|
|
|
case AC_FOUND_DEVICE:
|
|
|
|
{
|
|
|
|
struct ccb_getdev *cgd;
|
|
|
|
cam_status status;
|
|
|
|
|
|
|
|
cgd = (struct ccb_getdev *)arg;
|
2001-07-04 05:22:42 +00:00
|
|
|
if (cgd == NULL)
|
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Separate the parallel scsi knowledge out of the core of the XPT, and
modularize it so that new transports can be created.
Add a transport for SATA
Add a periph+protocol layer for ATA
Add a driver for AHCI-compliant hardware.
Add a maxio field to CAM so that drivers can advertise their max
I/O capability. Modify various drivers so that they are insulated
from the value of MAXPHYS.
The new ATA/SATA code supports AHCI-compliant hardware, and will override
the classic ATA driver if it is loaded as a module at boot time or compiled
into the kernel. The stack now support NCQ (tagged queueing) for increased
performance on modern SATA drives. It also supports port multipliers.
ATA drives are accessed via 'ada' device nodes. ATAPI drives are
accessed via 'cd' device nodes. They can all be enumerated and manipulated
via camcontrol, just like SCSI drives. SCSI commands are not translated to
their ATA equivalents; ATA native commands are used throughout the entire
stack, including camcontrol. See the camcontrol manpage for further
details. Testing this code may require that you update your fstab, and
possibly modify your BIOS to enable AHCI functionality, if available.
This code is very experimental at the moment. The userland ABI/API has
changed, so applications will need to be recompiled. It may change
further in the near future. The 'ada' device name may also change as
more infrastructure is completed in this project. The goal is to
eventually put all CAM busses and devices until newbus, allowing for
interesting topology and management options.
Few functional changes will be seen with existing SCSI/SAS/FC drivers,
though the userland ABI has still changed. In the future, transports
specific modules for SAS and FC may appear in order to better support
the topologies and capabilities of these technologies.
The modularization of CAM and the addition of the ATA/SATA modules is
meant to break CAM out of the mold of being specific to SCSI, letting it
grow to be a framework for arbitrary transports and protocols. It also
allows drivers to be written to support discrete hardware without
jeopardizing the stability of non-related hardware. While only an AHCI
driver is provided now, a Silicon Image driver is also in the works.
Drivers for ICH1-4, ICH5-6, PIIX, classic IDE, and any other hardware
is possible and encouraged. Help with new transports is also encouraged.
Submitted by: scottl, mav
Approved by: re
2009-07-10 08:18:08 +00:00
|
|
|
if (cgd->protocol != PROTO_SCSI)
|
|
|
|
break;
|
|
|
|
|
2000-01-17 06:27:37 +00:00
|
|
|
if (SID_TYPE(&cgd->inq_data) != T_DIRECT
|
2002-02-21 11:58:47 +00:00
|
|
|
&& SID_TYPE(&cgd->inq_data) != T_RBC
|
2000-01-17 06:27:37 +00:00
|
|
|
&& SID_TYPE(&cgd->inq_data) != T_OPTICAL)
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a peripheral instance for
|
|
|
|
* this device and start the probe
|
|
|
|
* process.
|
|
|
|
*/
|
Fix a problem with the way we handled device invalidation when attaching
to a device failed.
In theory, the same steps that happen when we get an AC_LOST_DEVICE async
notification should have been taken when a driver fails to attach. In
practice, that wasn't the case.
This only affected the da, cd and ch drivers, but the fix affects all
peripheral drivers.
There were several possible problems:
- In the da driver, we didn't remove the peripheral's softc from the da
driver's linked list of softcs. Once the peripheral and softc got
removed, we'd get a kernel panic the next time the timeout routine
called dasendorderedtag().
- In the da, cd and possibly ch drivers, we didn't remove the
peripheral's devstat structure from the devstat queue. Once the
peripheral and softc were removed, this could cause a panic if anyone
tried to access device statistics. (one component of the linked list
wouldn't exist anymore)
- In the cd driver, we didn't take the peripheral off the changer run
queue if it was scheduled to run. In practice, it's highly unlikely,
and maybe impossible that the peripheral would have been on the
changer run queue at that stage of the probe process.
The fix is:
- Add a new peripheral callback function (the "oninvalidate" function)
that is called the first time cam_periph_invalidate() is called for a
peripheral.
- Create new foooninvalidate() routines for each peripheral driver. This
routine is always called at splsoftcam(), and contains all the stuff
that used to be in the AC_LOST_DEVICE case of the async callback
handler.
- Move the devstat cleanup call to the destructor/cleanup routines, since
some of the drivers do I/O in their close routines.
- Make sure that when we're flushing the buffer queue, we traverse it at
splbio().
- Add a check for the invalid flag in the pt driver's open routine.
Reviewed by: gibbs
1998-10-22 22:16:56 +00:00
|
|
|
status = cam_periph_alloc(daregister, daoninvalidate,
|
|
|
|
dacleanup, dastart,
|
|
|
|
"da", CAM_PERIPH_BIO,
|
|
|
|
cgd->ccb_h.path, daasync,
|
|
|
|
AC_FOUND_DEVICE, cgd);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (status != CAM_REQ_CMP
|
|
|
|
&& status != CAM_REQ_INPROG)
|
|
|
|
printf("daasync: Unable to attach to new device "
|
|
|
|
"due to status 0x%x\n", status);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case AC_ADVINFO_CHANGED:
|
|
|
|
{
|
|
|
|
uintptr_t buftype;
|
|
|
|
|
|
|
|
buftype = (uintptr_t)arg;
|
|
|
|
if (buftype == CDAI_TYPE_PHYS_PATH) {
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = periph->softc;
|
|
|
|
disk_attr_changed(softc->disk, "GEOM::physpath",
|
|
|
|
M_NOWAIT);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
case AC_UNIT_ATTENTION:
|
|
|
|
{
|
|
|
|
union ccb *ccb;
|
|
|
|
int error_code, sense_key, asc, ascq;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
ccb = (union ccb *)arg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle all UNIT ATTENTIONs except our own,
|
|
|
|
* as they will be handled by daerror().
|
|
|
|
*/
|
|
|
|
if (xpt_path_periph(ccb->ccb_h.path) != periph &&
|
|
|
|
scsi_extract_sense_ccb(ccb,
|
|
|
|
&error_code, &sense_key, &asc, &ascq)) {
|
|
|
|
if (asc == 0x2A && ascq == 0x09) {
|
|
|
|
xpt_print(ccb->ccb_h.path,
|
|
|
|
"capacity data has changed\n");
|
|
|
|
dareprobe(periph);
|
|
|
|
} else if (asc == 0x28 && ascq == 0x00)
|
|
|
|
disk_media_changed(softc->disk, M_NOWAIT);
|
|
|
|
}
|
|
|
|
cam_periph_async(periph, code, path, arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case AC_SCSI_AEN:
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
2013-01-11 16:10:11 +00:00
|
|
|
if (!softc->tur) {
|
2012-07-29 11:51:48 +00:00
|
|
|
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
|
|
|
softc->tur = 1;
|
2013-01-11 16:10:11 +00:00
|
|
|
daschedule(periph);
|
2012-07-29 11:51:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
1998-09-15 06:36:34 +00:00
|
|
|
case AC_SENT_BDR:
|
|
|
|
case AC_BUS_RESET:
|
|
|
|
{
|
|
|
|
struct ccb_hdr *ccbh;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
/*
|
|
|
|
* Don't fail on the expected unit attention
|
|
|
|
* that will occur.
|
|
|
|
*/
|
|
|
|
softc->flags |= DA_FLAG_RETRY_UA;
|
2001-02-04 13:13:25 +00:00
|
|
|
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
|
1998-09-15 06:36:34 +00:00
|
|
|
ccbh->ccb_state |= DA_CCB_RETRY_UA;
|
2011-06-14 16:05:00 +00:00
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-06-14 16:05:00 +00:00
|
|
|
cam_periph_async(periph, code, path, arg);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
static void
|
|
|
|
dasysctlinit(void *context, int pending)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
|
|
|
char tmpstr[80], tmpstr2[80];
|
2010-06-07 22:43:37 +00:00
|
|
|
struct ccb_trans_settings cts;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
|
|
|
|
periph = (struct cam_periph *)context;
|
2010-06-08 22:46:44 +00:00
|
|
|
/*
|
|
|
|
* periph was held for us when this task was enqueued
|
|
|
|
*/
|
|
|
|
if (periph->flags & CAM_PERIPH_INVALID) {
|
|
|
|
cam_periph_release(periph);
|
2007-04-15 08:49:19 +00:00
|
|
|
return;
|
2010-06-08 22:46:44 +00:00
|
|
|
}
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
|
|
|
|
snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
|
|
|
|
|
|
|
|
sysctl_ctx_init(&softc->sysctl_ctx);
|
2003-10-08 07:12:30 +00:00
|
|
|
softc->flags |= DA_FLAG_SCTX_INIT;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
|
|
|
|
SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
|
|
|
|
CTLFLAG_RD, 0, tmpstr);
|
|
|
|
if (softc->sysctl_tree == NULL) {
|
|
|
|
printf("dasysctlinit: unable to allocate sysctl tree\n");
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_release(periph);
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-07 17:41:34 +00:00
|
|
|
* Now register the sysctl handler, so the user can change the value on
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
* the fly.
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW,
|
2013-01-10 11:57:46 +00:00
|
|
|
softc, 0, dadeletemethodsysctl, "A",
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
"BIO_DELETE execution method");
|
2013-04-26 16:22:54 +00:00
|
|
|
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO, "delete_max", CTLTYPE_U64 | CTLFLAG_RW,
|
|
|
|
softc, 0, dadeletemaxsysctl, "Q",
|
|
|
|
"Maximum BIO_DELETE size");
|
2010-06-07 17:41:34 +00:00
|
|
|
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
|
|
|
|
&softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
|
|
|
|
"Minimum CDB size");
|
2013-03-29 22:58:15 +00:00
|
|
|
SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO, "sort_io_queue", CTLFLAG_RW, &softc->sort_io_queue, 0,
|
|
|
|
"Sort IO queue to try and optimise disk access patterns");
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
SYSCTL_ADD_INT(&softc->sysctl_ctx,
|
|
|
|
SYSCTL_CHILDREN(softc->sysctl_tree),
|
|
|
|
OID_AUTO,
|
|
|
|
"error_inject",
|
|
|
|
CTLFLAG_RW,
|
|
|
|
&softc->error_inject,
|
|
|
|
0,
|
|
|
|
"error_inject leaf");
|
|
|
|
|
|
|
|
|
2010-06-07 17:41:34 +00:00
|
|
|
/*
|
|
|
|
* Add some addressing info.
|
|
|
|
*/
|
|
|
|
memset(&cts, 0, sizeof (cts));
|
2012-10-27 09:40:29 +00:00
|
|
|
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
2010-06-07 17:41:34 +00:00
|
|
|
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
|
|
|
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
|
|
|
cam_periph_lock(periph);
|
|
|
|
xpt_action((union ccb *)&cts);
|
|
|
|
cam_periph_unlock(periph);
|
|
|
|
if (cts.ccb_h.status != CAM_REQ_CMP) {
|
|
|
|
cam_periph_release(periph);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cts.protocol == PROTO_SCSI && cts.transport == XPORT_FC) {
|
|
|
|
struct ccb_trans_settings_fc *fc = &cts.xport_specific.fc;
|
|
|
|
if (fc->valid & CTS_FC_VALID_WWPN) {
|
|
|
|
softc->wwpn = fc->wwpn;
|
2011-01-19 17:04:07 +00:00
|
|
|
SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
|
2010-06-07 17:41:34 +00:00
|
|
|
SYSCTL_CHILDREN(softc->sysctl_tree),
|
2011-01-13 18:20:33 +00:00
|
|
|
OID_AUTO, "wwpn", CTLFLAG_RD,
|
2010-06-07 17:41:34 +00:00
|
|
|
&softc->wwpn, "World Wide Port Name");
|
|
|
|
}
|
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
cam_periph_release(periph);
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
}
|
|
|
|
|
2013-04-26 16:22:54 +00:00
|
|
|
static int
|
|
|
|
dadeletemaxsysctl(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
uint64_t value;
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)arg1;
|
|
|
|
|
|
|
|
value = softc->disk->d_delmaxsize;
|
|
|
|
error = sysctl_handle_64(oidp, &value, 0, req);
|
|
|
|
if ((error != 0) || (req->newptr == NULL))
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/* only accept values smaller than the calculated value */
|
|
|
|
if (value > softc->disk->d_delmaxsize) {
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
softc->disk->d_delmaxsize = value;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
static int
|
|
|
|
dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error, value;
|
|
|
|
|
|
|
|
value = *(int *)arg1;
|
|
|
|
|
|
|
|
error = sysctl_handle_int(oidp, &value, 0, req);
|
|
|
|
|
|
|
|
if ((error != 0)
|
|
|
|
|| (req->newptr == NULL))
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/*
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
* Acceptable values here are 6, 10, 12 or 16.
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
*/
|
|
|
|
if (value < 6)
|
|
|
|
value = 6;
|
|
|
|
else if ((value > 6)
|
|
|
|
&& (value <= 10))
|
|
|
|
value = 10;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
else if ((value > 10)
|
|
|
|
&& (value <= 12))
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
value = 12;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
else if (value > 12)
|
|
|
|
value = 16;
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
|
|
|
|
*(int *)arg1 = value;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2013-04-26 15:31:52 +00:00
|
|
|
static void
|
2013-01-10 11:57:46 +00:00
|
|
|
dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
softc->delete_method = delete_method;
|
2013-04-26 16:22:54 +00:00
|
|
|
softc->disk->d_delmaxsize = dadeletemaxsize(softc, delete_method);
|
2013-01-10 11:57:46 +00:00
|
|
|
|
|
|
|
if (softc->delete_method > DA_DELETE_DISABLE)
|
|
|
|
softc->disk->d_flags |= DISKFLAG_CANDELETE;
|
|
|
|
else
|
|
|
|
softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:22:54 +00:00
|
|
|
static off_t
|
|
|
|
dadeletemaxsize(struct da_softc *softc, da_delete_methods delete_method)
|
|
|
|
{
|
|
|
|
off_t sectors;
|
|
|
|
|
|
|
|
switch(delete_method) {
|
|
|
|
case DA_DELETE_UNMAP:
|
|
|
|
sectors = (off_t)softc->unmap_max_lba * softc->unmap_max_ranges;
|
|
|
|
break;
|
|
|
|
case DA_DELETE_ATA_TRIM:
|
|
|
|
sectors = (off_t)ATA_DSM_RANGE_MAX * softc->trim_max_ranges;
|
|
|
|
break;
|
|
|
|
case DA_DELETE_WS16:
|
|
|
|
sectors = (off_t)min(softc->ws_max_blks, WS16_MAX_BLKS);
|
|
|
|
break;
|
|
|
|
case DA_DELETE_ZERO:
|
|
|
|
case DA_DELETE_WS10:
|
|
|
|
sectors = (off_t)min(softc->ws_max_blks, WS10_MAX_BLKS);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (off_t)softc->params.secsize *
|
|
|
|
min(sectors, (off_t)softc->params.sectors);
|
|
|
|
}
|
|
|
|
|
2013-05-02 14:37:23 +00:00
|
|
|
static void
|
|
|
|
daprobedone(struct cam_periph *periph, union ccb *ccb)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
dadeletemethodchoose(softc, DA_DELETE_NONE);
|
|
|
|
|
|
|
|
if (bootverbose && (softc->flags & DA_FLAG_PROBED) == 0) {
|
|
|
|
char buf[80];
|
|
|
|
int i, sep;
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Delete methods: <");
|
|
|
|
sep = 0;
|
|
|
|
for (i = DA_DELETE_MIN; i <= DA_DELETE_MAX; i++) {
|
|
|
|
if (softc->delete_available & (1 << i)) {
|
|
|
|
if (sep) {
|
|
|
|
strlcat(buf, ",", sizeof(buf));
|
|
|
|
} else {
|
|
|
|
sep = 1;
|
|
|
|
}
|
|
|
|
strlcat(buf, da_delete_method_names[i],
|
|
|
|
sizeof(buf));
|
|
|
|
if (i == softc->delete_method) {
|
|
|
|
strlcat(buf, "(*)", sizeof(buf));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sep == 0) {
|
|
|
|
if (softc->delete_method == DA_DELETE_NONE)
|
|
|
|
strlcat(buf, "NONE(*)", sizeof(buf));
|
|
|
|
else
|
|
|
|
strlcat(buf, "DISABLED(*)", sizeof(buf));
|
|
|
|
}
|
|
|
|
strlcat(buf, ">", sizeof(buf));
|
|
|
|
printf("%s%d: %s\n", periph->periph_name,
|
|
|
|
periph->unit_number, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since our peripheral may be invalidated by an error
|
|
|
|
* above or an external event, we must release our CCB
|
|
|
|
* before releasing the probe lock on the peripheral.
|
|
|
|
* The peripheral will only go away once the last lock
|
|
|
|
* is removed, and we need it around for the CCB release
|
|
|
|
* operation.
|
|
|
|
*/
|
|
|
|
xpt_release_ccb(ccb);
|
|
|
|
softc->state = DA_STATE_NORMAL;
|
|
|
|
daschedule(periph);
|
|
|
|
wakeup(&softc->disk->d_mediasize);
|
|
|
|
if ((softc->flags & DA_FLAG_PROBED) == 0) {
|
|
|
|
softc->flags |= DA_FLAG_PROBED;
|
|
|
|
cam_periph_unhold(periph);
|
|
|
|
} else
|
|
|
|
cam_periph_release_locked(periph);
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
static void
|
|
|
|
dadeletemethodchoose(struct da_softc *softc, da_delete_methods default_method)
|
|
|
|
{
|
|
|
|
int i, delete_method;
|
|
|
|
|
|
|
|
delete_method = default_method;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use the pre-defined order to choose the best
|
|
|
|
* performing delete.
|
|
|
|
*/
|
|
|
|
for (i = DA_DELETE_MIN; i <= DA_DELETE_MAX; i++) {
|
|
|
|
if (softc->delete_available & (1 << i)) {
|
|
|
|
dadeletemethodset(softc, i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dadeletemethodset(softc, delete_method);
|
|
|
|
}
|
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
static int
|
|
|
|
dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
char buf[16];
|
|
|
|
const char *p;
|
2013-01-10 11:57:46 +00:00
|
|
|
struct da_softc *softc;
|
|
|
|
int i, error, value;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
2013-01-10 11:57:46 +00:00
|
|
|
softc = (struct da_softc *)arg1;
|
|
|
|
|
|
|
|
value = softc->delete_method;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
if (value < 0 || value > DA_DELETE_MAX)
|
|
|
|
p = "UNKNOWN";
|
|
|
|
else
|
|
|
|
p = da_delete_method_names[value];
|
|
|
|
strncpy(buf, p, sizeof(buf));
|
|
|
|
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
|
|
|
|
if (error != 0 || req->newptr == NULL)
|
|
|
|
return (error);
|
|
|
|
for (i = 0; i <= DA_DELETE_MAX; i++) {
|
|
|
|
if (strcmp(buf, da_delete_method_names[i]) != 0)
|
|
|
|
continue;
|
2013-04-26 15:31:52 +00:00
|
|
|
dadeletemethodset(softc, i);
|
|
|
|
return (0);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
}
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static cam_status
|
|
|
|
daregister(struct cam_periph *periph, void *arg)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
2003-07-28 06:15:59 +00:00
|
|
|
struct ccb_pathinq cpi;
|
1998-09-15 06:36:34 +00:00
|
|
|
struct ccb_getdev *cgd;
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
char tmpstr[80];
|
1998-10-08 05:46:38 +00:00
|
|
|
caddr_t match;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
cgd = (struct ccb_getdev *)arg;
|
|
|
|
if (cgd == NULL) {
|
|
|
|
printf("daregister: no getdev CCB, can't register device\n");
|
|
|
|
return(CAM_REQ_CMP_ERR);
|
|
|
|
}
|
|
|
|
|
2002-10-11 09:59:22 +00:00
|
|
|
softc = (struct da_softc *)malloc(sizeof(*softc), M_DEVBUF,
|
|
|
|
M_NOWAIT|M_ZERO);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (softc == NULL) {
|
|
|
|
printf("daregister: Unable to probe new device. "
|
|
|
|
"Unable to allocate softc\n");
|
|
|
|
return(CAM_REQ_CMP_ERR);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIST_INIT(&softc->pending_ccbs);
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC;
|
2000-04-15 05:54:02 +00:00
|
|
|
bioq_init(&softc->bio_queue);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_init(&softc->delete_queue);
|
|
|
|
bioq_init(&softc->delete_run_queue);
|
1998-09-15 06:36:34 +00:00
|
|
|
if (SID_IS_REMOVABLE(&cgd->inq_data))
|
|
|
|
softc->flags |= DA_FLAG_PACK_REMOVABLE;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc->unmap_max_ranges = UNMAP_MAX_RANGES;
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->unmap_max_lba = UNMAP_RANGE_MAX;
|
|
|
|
softc->ws_max_blks = WS16_MAX_BLKS;
|
|
|
|
softc->trim_max_ranges = ATA_TRIM_MAX_RANGES;
|
2013-03-29 22:58:15 +00:00
|
|
|
softc->sort_io_queue = -1;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
periph->softc = softc;
|
1998-10-08 05:46:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See if this device has any quirks.
|
|
|
|
*/
|
|
|
|
match = cam_quirkmatch((caddr_t)&cgd->inq_data,
|
|
|
|
(caddr_t)da_quirk_table,
|
|
|
|
sizeof(da_quirk_table)/sizeof(*da_quirk_table),
|
|
|
|
sizeof(*da_quirk_table), scsi_inquiry_match);
|
|
|
|
|
|
|
|
if (match != NULL)
|
|
|
|
softc->quirks = ((struct da_quirk_entry *)match)->quirks;
|
|
|
|
else
|
|
|
|
softc->quirks = DA_Q_NONE;
|
|
|
|
|
2003-07-28 06:15:59 +00:00
|
|
|
/* Check if the SIM does not want 6 byte commands */
|
Separate the parallel scsi knowledge out of the core of the XPT, and
modularize it so that new transports can be created.
Add a transport for SATA
Add a periph+protocol layer for ATA
Add a driver for AHCI-compliant hardware.
Add a maxio field to CAM so that drivers can advertise their max
I/O capability. Modify various drivers so that they are insulated
from the value of MAXPHYS.
The new ATA/SATA code supports AHCI-compliant hardware, and will override
the classic ATA driver if it is loaded as a module at boot time or compiled
into the kernel. The stack now support NCQ (tagged queueing) for increased
performance on modern SATA drives. It also supports port multipliers.
ATA drives are accessed via 'ada' device nodes. ATAPI drives are
accessed via 'cd' device nodes. They can all be enumerated and manipulated
via camcontrol, just like SCSI drives. SCSI commands are not translated to
their ATA equivalents; ATA native commands are used throughout the entire
stack, including camcontrol. See the camcontrol manpage for further
details. Testing this code may require that you update your fstab, and
possibly modify your BIOS to enable AHCI functionality, if available.
This code is very experimental at the moment. The userland ABI/API has
changed, so applications will need to be recompiled. It may change
further in the near future. The 'ada' device name may also change as
more infrastructure is completed in this project. The goal is to
eventually put all CAM busses and devices until newbus, allowing for
interesting topology and management options.
Few functional changes will be seen with existing SCSI/SAS/FC drivers,
though the userland ABI has still changed. In the future, transports
specific modules for SAS and FC may appear in order to better support
the topologies and capabilities of these technologies.
The modularization of CAM and the addition of the ATA/SATA modules is
meant to break CAM out of the mold of being specific to SCSI, letting it
grow to be a framework for arbitrary transports and protocols. It also
allows drivers to be written to support discrete hardware without
jeopardizing the stability of non-related hardware. While only an AHCI
driver is provided now, a Silicon Image driver is also in the works.
Drivers for ICH1-4, ICH5-6, PIIX, classic IDE, and any other hardware
is possible and encouraged. Help with new transports is also encouraged.
Submitted by: scottl, mav
Approved by: re
2009-07-10 08:18:08 +00:00
|
|
|
bzero(&cpi, sizeof(cpi));
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
2003-07-28 06:15:59 +00:00
|
|
|
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
|
|
|
xpt_action((union ccb *)&cpi);
|
|
|
|
if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
|
|
|
|
softc->quirks |= DA_Q_NO_6_BYTE;
|
|
|
|
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
2007-04-15 08:49:19 +00:00
|
|
|
* Take an exclusive refcount on the periph while dastart is called
|
|
|
|
* to finish the probe. The reference will be dropped in dadone at
|
|
|
|
* the end of probe.
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
2007-04-15 08:49:19 +00:00
|
|
|
(void)cam_periph_hold(periph, PRIBIO);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
/*
|
|
|
|
* Schedule a periodic event to occasionally send an
|
|
|
|
* ordered tag to a device.
|
|
|
|
*/
|
|
|
|
callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
|
|
|
|
callout_reset(&softc->sendordered_c,
|
2012-02-02 19:02:15 +00:00
|
|
|
(da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
|
2007-04-15 08:49:19 +00:00
|
|
|
dasendorderedtag, softc);
|
|
|
|
|
2013-04-04 19:07:37 +00:00
|
|
|
cam_periph_unlock(periph);
|
2011-04-16 06:54:41 +00:00
|
|
|
/*
|
|
|
|
* RBC devices don't have to support READ(6), only READ(10).
|
|
|
|
*/
|
|
|
|
if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
|
|
|
|
softc->minimum_cmd_size = 10;
|
|
|
|
else
|
|
|
|
softc->minimum_cmd_size = 6;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load the user's default, if any.
|
|
|
|
*/
|
|
|
|
snprintf(tmpstr, sizeof(tmpstr), "kern.cam.da.%d.minimum_cmd_size",
|
|
|
|
periph->unit_number);
|
|
|
|
TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 6, 10, 12 and 16 are the currently permissible values.
|
|
|
|
*/
|
|
|
|
if (softc->minimum_cmd_size < 6)
|
|
|
|
softc->minimum_cmd_size = 6;
|
|
|
|
else if ((softc->minimum_cmd_size > 6)
|
|
|
|
&& (softc->minimum_cmd_size <= 10))
|
|
|
|
softc->minimum_cmd_size = 10;
|
|
|
|
else if ((softc->minimum_cmd_size > 10)
|
|
|
|
&& (softc->minimum_cmd_size <= 12))
|
|
|
|
softc->minimum_cmd_size = 12;
|
|
|
|
else if (softc->minimum_cmd_size > 12)
|
|
|
|
softc->minimum_cmd_size = 16;
|
|
|
|
|
2011-12-23 19:12:02 +00:00
|
|
|
/* Predict whether device may support READ CAPACITY(16). */
|
2012-03-31 11:23:09 +00:00
|
|
|
if (SID_ANSI_REV(&cgd->inq_data) >= SCSI_REV_SPC3) {
|
2011-12-23 19:12:02 +00:00
|
|
|
softc->flags |= DA_FLAG_CAN_RC16;
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC16;
|
2011-12-23 19:12:02 +00:00
|
|
|
}
|
|
|
|
|
2011-04-16 08:38:11 +00:00
|
|
|
/*
|
|
|
|
* Register this media as a disk.
|
|
|
|
*/
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk = disk_alloc();
|
2011-04-14 21:25:32 +00:00
|
|
|
softc->disk->d_devstat = devstat_new_entry(periph->periph_name,
|
|
|
|
periph->unit_number, 0,
|
|
|
|
DEVSTAT_BS_UNAVAILABLE,
|
|
|
|
SID_TYPE(&cgd->inq_data) |
|
|
|
|
XPORT_DEVSTAT_TYPE(cpi.transport),
|
|
|
|
DEVSTAT_PRIORITY_DISK);
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk->d_open = daopen;
|
|
|
|
softc->disk->d_close = daclose;
|
|
|
|
softc->disk->d_strategy = dastrategy;
|
|
|
|
softc->disk->d_dump = dadump;
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
softc->disk->d_getattr = dagetattr;
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
softc->disk->d_gone = dadiskgonecb;
|
2010-06-08 22:46:44 +00:00
|
|
|
softc->disk->d_name = "da";
|
|
|
|
softc->disk->d_drv1 = periph;
|
|
|
|
if (cpi.maxio == 0)
|
|
|
|
softc->disk->d_maxsize = DFLTPHYS; /* traditional default */
|
|
|
|
else if (cpi.maxio > MAXPHYS)
|
|
|
|
softc->disk->d_maxsize = MAXPHYS; /* for safety */
|
|
|
|
else
|
|
|
|
softc->disk->d_maxsize = cpi.maxio;
|
|
|
|
softc->disk->d_unit = periph->unit_number;
|
|
|
|
softc->disk->d_flags = 0;
|
|
|
|
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
|
|
|
|
softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
|
2013-03-19 15:01:50 +00:00
|
|
|
if ((cpi.hba_misc & PIM_UNMAPPED) != 0)
|
|
|
|
softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
|
2011-02-26 23:30:32 +00:00
|
|
|
cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
|
|
|
|
sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
|
|
|
|
strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
|
|
|
|
cam_strvis(&softc->disk->d_descr[strlen(softc->disk->d_descr)],
|
|
|
|
cgd->inq_data.product, sizeof(cgd->inq_data.product),
|
|
|
|
sizeof(softc->disk->d_descr) - strlen(softc->disk->d_descr));
|
2010-07-25 15:43:52 +00:00
|
|
|
softc->disk->d_hba_vendor = cpi.hba_vendor;
|
|
|
|
softc->disk->d_hba_device = cpi.hba_device;
|
|
|
|
softc->disk->d_hba_subvendor = cpi.hba_subvendor;
|
|
|
|
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Acquire a reference to the periph before we register with GEOM.
|
|
|
|
* We'll release this reference once GEOM calls us back (via
|
|
|
|
* dadiskgonecb()) telling us that our provider has been freed.
|
|
|
|
*/
|
|
|
|
if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
|
|
|
|
xpt_print(periph->path, "%s: lost periph during "
|
|
|
|
"registration!\n", __func__);
|
2013-04-04 19:07:37 +00:00
|
|
|
cam_periph_lock(periph);
|
Fix a bug which causes a panic in daopen(). The panic is caused by
a da(4) instance going away while GEOM is still probing it.
In this case, the GEOM disk class instance has been created by
disk_create(), and the taste of the disk is queued in the GEOM
event queue.
While that event is queued, the da(4) instance goes away. When the
open call comes into the da(4) driver, it dereferences the freed
(but non-NULL) peripheral pointer provided by GEOM, which results
in a panic.
The solution is to add a callback to the GEOM disk code that is
called when all of its resources are cleaned up. This is
implemented inside GEOM by adding an optional callback that is
called when all consumers have detached from a provider, and the
provider is about to be deleted.
scsi_cd.c,
scsi_da.c: In the register routine for the cd(4) and da(4)
routines, acquire a reference to the CAM peripheral
instance just before we call disk_create().
Use the new GEOM disk d_gone() callback to register
a callback (dadiskgonecb()/cddiskgonecb()) that
decrements the peripheral reference count once GEOM
has finished cleaning up its resources.
In the cd(4) driver, clean up open and close
behavior slightly. GEOM makes sure we only get one
open() and one close call, so there is no need to
set an open flag and decrement the reference count
if we are not the first open.
In the cd(4) driver, use cam_periph_release_locked()
in a couple of error scenarios to avoid extra mutex
calls.
geom.h: Add a new, optional, providergone callback that
is called when a provider is about to be deleted.
geom_disk.h: Add a new d_gone() callback to the GEOM disk
interface.
Bump the DISK_VERSION to version 2. This probably
should have been done after a couple of previous
changes, especially the addition of the d_getattr()
callback.
geom_disk.c: Add a providergone callback for the disk class,
g_disk_providergone(), that calls the user's
d_gone() callback if it exists.
Bump the DISK_VERSION to 2.
geom_subr.c: In g_destroy_provider(), call the providergone
callback if it has been provided.
In g_new_geomf(), propagate the class's
providergone callback to the new geom instance.
blkfront.c: Callers of disk_create() are supposed to pass in
DISK_VERSION, not an explicit disk API version
number. Update the blkfront driver to do that.
disk.9: Update the disk(9) man page to include information
on the new d_gone() callback, as well as the
previously added d_getattr() callback, d_descr
field, and HBA PCI ID fields.
MFC after: 5 days
2012-06-24 04:29:03 +00:00
|
|
|
return (CAM_REQ_CMP_ERR);
|
|
|
|
}
|
|
|
|
|
2010-06-08 22:46:44 +00:00
|
|
|
disk_create(softc->disk, DISK_VERSION);
|
2013-04-04 19:07:37 +00:00
|
|
|
cam_periph_lock(periph);
|
2010-06-08 22:46:44 +00:00
|
|
|
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
/*
|
|
|
|
* Add async callbacks for events of interest.
|
|
|
|
* I don't bother checking if this fails as,
|
|
|
|
* in most cases, the system will function just
|
|
|
|
* fine without them and the only alternative
|
|
|
|
* would be to not attach the device on failure.
|
|
|
|
*/
|
2012-07-29 11:51:48 +00:00
|
|
|
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
|
|
|
|
AC_ADVINFO_CHANGED | AC_SCSI_AEN | AC_UNIT_ATTENTION,
|
|
|
|
daasync, periph, periph->path);
|
Plumb device physical path reporting from CAM devices, through GEOM and
DEVFS, and make it accessible via the diskinfo utility.
Extend GEOM's generic attribute query mechanism into generic disk consumers.
sys/geom/geom_disk.c:
sys/geom/geom_disk.h:
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Allow disk providers to implement a new method which can override
the default BIO_GETATTR response, d_getattr(struct bio *). This
function returns -1 if not handled, otherwise it returns 0 or an
errno to be passed to g_io_deliver().
sys/cam/scsi/scsi_da.c:
sys/cam/ata/ata_da.c:
- Don't copy the serial number to dp->d_ident anymore, as the CAM XPT
is now responsible for returning this information via
d_getattr()->(a)dagetattr()->xpt_getatr().
sys/geom/geom_dev.c:
- Implement a new ioctl, DIOCGPHYSPATH, which returns the GEOM
attribute "GEOM::physpath", if possible. If the attribute request
returns a zero-length string, ENOENT is returned.
usr.sbin/diskinfo/diskinfo.c:
- If the DIOCGPHYSPATH ioctl is successful, report physical path
data when diskinfo is executed with the '-v' option.
Submitted by: will
Reviewed by: gibbs
Sponsored by: Spectra Logic Corporation
Add generic attribute change notification support to GEOM.
sys/sys/geom/geom.h:
Add a new attrchanged method field to both g_class
and g_geom.
sys/sys/geom/geom.h:
sys/geom/geom_event.c:
- Provide the g_attr_changed() function that providers
can use to advertise attribute changes.
- Perform delivery of attribute change notifications
from a thread context via the standard GEOM event
mechanism.
sys/geom/geom_subr.c:
Inherit the attrchanged method from class to geom (class instance).
sys/geom/geom_disk.c:
Provide disk_attr_changed() to provide g_attr_changed() access
to consumers of the disk API.
sys/cam/scsi/scsi_pass.c:
sys/cam/scsi/scsi_da.c:
sys/geom/geom_dev.c:
sys/geom/geom_disk.c:
Use attribute changed events to track updates to physical path
information.
sys/cam/scsi/scsi_da.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, and
the updated buffer type references our physical path
attribute, emit a GEOM attribute changed event via the
disk_attr_changed() API.
sys/cam/scsi/scsi_pass.c:
Add AC_ADVINFO_CHANGED to the registered asynchronous CAM
events for this driver. When this event occurs, update
the physical patch devfs alias for this pass instance.
Submitted by: gibbs
Sponsored by: Spectra Logic Corporation
2011-06-14 17:10:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Emit an attribute changed notification just in case
|
|
|
|
* physical path information arrived before our async
|
|
|
|
* event handler was registered, but after anyone attaching
|
|
|
|
* to our disk device polled it.
|
|
|
|
*/
|
|
|
|
disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT);
|
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
/*
|
|
|
|
* Schedule a periodic media polling events.
|
|
|
|
*/
|
|
|
|
callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0);
|
|
|
|
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) &&
|
|
|
|
(cgd->inq_flags & SID_AEN) == 0 &&
|
|
|
|
da_poll_period != 0)
|
|
|
|
callout_reset(&softc->mediapoll_c, da_poll_period * hz,
|
|
|
|
damediapoll, periph);
|
|
|
|
|
2010-06-08 22:46:44 +00:00
|
|
|
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
return(CAM_REQ_CMP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dastart(struct cam_periph *periph, union ccb *start_ccb)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastart\n"));
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
skipstate:
|
1998-09-15 06:36:34 +00:00
|
|
|
switch (softc->state) {
|
|
|
|
case DA_STATE_NORMAL:
|
|
|
|
{
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio *bp, *bp1;
|
|
|
|
uint8_t tag_code;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Execute immediate CCB if waiting. */
|
1998-09-15 06:36:34 +00:00
|
|
|
if (periph->immediate_priority <= periph->pinfo.priority) {
|
2012-06-05 09:45:42 +00:00
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
|
1998-09-15 06:36:34 +00:00
|
|
|
("queuing for immediate ccb\n"));
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
|
|
|
|
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
|
|
|
|
periph_links.sle);
|
|
|
|
periph->immediate_priority = CAM_PRIORITY_NONE;
|
|
|
|
wakeup(&periph->ccb_list);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* May have more work to do, so ensure we stay scheduled */
|
|
|
|
daschedule(periph);
|
|
|
|
break;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Run BIO_DELETE if not running yet. */
|
|
|
|
if (!softc->delete_running &&
|
|
|
|
(bp = bioq_first(&softc->delete_queue)) != NULL) {
|
|
|
|
uint64_t lba;
|
2013-04-26 16:17:04 +00:00
|
|
|
uint64_t count; /* forward compat with WS32 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In each of the methods below, while its the caller's
|
|
|
|
* responsibility to ensure the request will fit into a
|
|
|
|
* single device request, we might have changed the delete
|
|
|
|
* method due to the device incorrectly advertising either
|
|
|
|
* its supported methods or limits.
|
|
|
|
*
|
|
|
|
* To prevent this causing further issues we validate the
|
|
|
|
* against the methods limits, and warn which would
|
|
|
|
* otherwise be unnecessary.
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
if (softc->delete_method == DA_DELETE_UNMAP) {
|
|
|
|
uint8_t *buf = softc->unmap_buf;
|
|
|
|
uint64_t lastlba = (uint64_t)-1;
|
2013-04-26 16:17:04 +00:00
|
|
|
uint32_t lastcount = 0, c;
|
|
|
|
uint64_t totalcount = 0;
|
|
|
|
uint32_t off, ranges = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Currently this doesn't take the UNMAP
|
|
|
|
* Granularity and Granularity Alignment
|
|
|
|
* fields into account.
|
|
|
|
*
|
|
|
|
* This could result in both unoptimal unmap
|
|
|
|
* requests as as well as UNMAP calls unmapping
|
|
|
|
* fewer LBA's than requested.
|
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
softc->delete_running = 1;
|
|
|
|
bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
|
|
|
|
bp1 = bp;
|
|
|
|
do {
|
|
|
|
bioq_remove(&softc->delete_queue, bp1);
|
|
|
|
if (bp1 != bp)
|
|
|
|
bioq_insert_tail(&softc->delete_run_queue, bp1);
|
|
|
|
lba = bp1->bio_pblkno;
|
|
|
|
count = bp1->bio_bcount / softc->params.secsize;
|
|
|
|
|
|
|
|
/* Try to extend the previous range. */
|
|
|
|
if (lba == lastlba) {
|
2013-04-26 16:17:04 +00:00
|
|
|
c = min(count, softc->unmap_max_lba -
|
|
|
|
lastcount);
|
|
|
|
lastcount += c;
|
|
|
|
off = ((ranges - 1) * UNMAP_RANGE_SIZE) +
|
|
|
|
UNMAP_HEAD_SIZE;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
scsi_ulto4b(lastcount, &buf[off + 8]);
|
2013-04-26 16:17:04 +00:00
|
|
|
count -= c;
|
|
|
|
lba +=c;
|
|
|
|
totalcount += c;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (count > 0) {
|
|
|
|
c = min(count, softc->unmap_max_lba);
|
|
|
|
if (totalcount + c > softc->unmap_max_lba ||
|
|
|
|
ranges >= softc->unmap_max_ranges) {
|
|
|
|
xpt_print(periph->path,
|
|
|
|
"%s issuing short delete %ld > %ld"
|
|
|
|
"|| %d >= %d",
|
|
|
|
da_delete_method_desc[softc->delete_method],
|
|
|
|
totalcount + c, softc->unmap_max_lba,
|
|
|
|
ranges, softc->unmap_max_ranges);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
off = (ranges * UNMAP_RANGE_SIZE) +
|
|
|
|
UNMAP_HEAD_SIZE;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
scsi_u64to8b(lba, &buf[off + 0]);
|
2013-04-26 16:17:04 +00:00
|
|
|
scsi_ulto4b(c, &buf[off + 8]);
|
|
|
|
lba += c;
|
|
|
|
totalcount += c;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
ranges++;
|
2013-04-26 16:17:04 +00:00
|
|
|
count -= c;
|
|
|
|
lastcount = c;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
lastlba = lba;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bp1 = bioq_first(&softc->delete_queue);
|
|
|
|
if (bp1 == NULL ||
|
|
|
|
ranges >= softc->unmap_max_ranges ||
|
2013-04-26 16:17:04 +00:00
|
|
|
totalcount + bp1->bio_bcount /
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc->params.secsize > softc->unmap_max_lba)
|
|
|
|
break;
|
|
|
|
} while (1);
|
2012-08-24 17:08:02 +00:00
|
|
|
scsi_ulto2b(ranges * 16 + 6, &buf[0]);
|
|
|
|
scsi_ulto2b(ranges * 16, &buf[2]);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
scsi_unmap(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*byte2*/0,
|
|
|
|
/*data_ptr*/ buf,
|
2012-08-24 17:08:02 +00:00
|
|
|
/*dxfer_len*/ ranges * 16 + 8,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_DELETE;
|
|
|
|
goto out;
|
2013-04-26 16:17:04 +00:00
|
|
|
} else if (softc->delete_method == DA_DELETE_ATA_TRIM) {
|
|
|
|
uint8_t *buf = softc->unmap_buf;
|
|
|
|
uint64_t lastlba = (uint64_t)-1;
|
|
|
|
uint32_t lastcount = 0, c, requestcount;
|
|
|
|
int ranges = 0, off, block_count;
|
|
|
|
|
|
|
|
softc->delete_running = 1;
|
|
|
|
bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
|
|
|
|
bp1 = bp;
|
|
|
|
do {
|
|
|
|
bioq_remove(&softc->delete_queue, bp1);
|
|
|
|
if (bp1 != bp)
|
|
|
|
bioq_insert_tail(&softc->delete_run_queue, bp1);
|
|
|
|
lba = bp1->bio_pblkno;
|
|
|
|
count = bp1->bio_bcount / softc->params.secsize;
|
|
|
|
requestcount = count;
|
|
|
|
|
|
|
|
/* Try to extend the previous range. */
|
|
|
|
if (lba == lastlba) {
|
|
|
|
c = min(count, ATA_DSM_RANGE_MAX - lastcount);
|
|
|
|
lastcount += c;
|
|
|
|
off = (ranges - 1) * 8;
|
|
|
|
buf[off + 6] = lastcount & 0xff;
|
|
|
|
buf[off + 7] = (lastcount >> 8) & 0xff;
|
|
|
|
count -= c;
|
|
|
|
lba += c;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (count > 0) {
|
|
|
|
c = min(count, ATA_DSM_RANGE_MAX);
|
|
|
|
off = ranges * 8;
|
|
|
|
|
|
|
|
buf[off + 0] = lba & 0xff;
|
|
|
|
buf[off + 1] = (lba >> 8) & 0xff;
|
|
|
|
buf[off + 2] = (lba >> 16) & 0xff;
|
|
|
|
buf[off + 3] = (lba >> 24) & 0xff;
|
|
|
|
buf[off + 4] = (lba >> 32) & 0xff;
|
|
|
|
buf[off + 5] = (lba >> 40) & 0xff;
|
|
|
|
buf[off + 6] = c & 0xff;
|
|
|
|
buf[off + 7] = (c >> 8) & 0xff;
|
|
|
|
lba += c;
|
|
|
|
ranges++;
|
|
|
|
count -= c;
|
|
|
|
lastcount = c;
|
|
|
|
if (count != 0 && ranges == softc->trim_max_ranges) {
|
|
|
|
xpt_print(periph->path,
|
|
|
|
"%s issuing short delete %ld > %ld",
|
|
|
|
da_delete_method_desc[softc->delete_method],
|
|
|
|
requestcount,
|
|
|
|
(softc->trim_max_ranges - ranges) *
|
|
|
|
ATA_DSM_RANGE_MAX);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastlba = lba;
|
|
|
|
bp1 = bioq_first(&softc->delete_queue);
|
|
|
|
if (bp1 == NULL ||
|
|
|
|
bp1->bio_bcount / softc->params.secsize >
|
|
|
|
(softc->trim_max_ranges - ranges) *
|
|
|
|
ATA_DSM_RANGE_MAX)
|
|
|
|
break;
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
block_count = (ranges + ATA_DSM_BLK_RANGES - 1) /
|
|
|
|
ATA_DSM_BLK_RANGES;
|
|
|
|
scsi_ata_trim(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
block_count,
|
|
|
|
/*data_ptr*/buf,
|
|
|
|
/*dxfer_len*/block_count * ATA_DSM_BLK_SIZE,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_DELETE;
|
|
|
|
goto out;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
} else if (softc->delete_method == DA_DELETE_ZERO ||
|
|
|
|
softc->delete_method == DA_DELETE_WS10 ||
|
|
|
|
softc->delete_method == DA_DELETE_WS16) {
|
2013-04-26 16:22:54 +00:00
|
|
|
/*
|
|
|
|
* We calculate ws_max_blks here based off d_delmaxsize instead
|
|
|
|
* of using softc->ws_max_blks as it is absolute max for the
|
|
|
|
* device not the protocol max which may well be lower
|
|
|
|
*/
|
2013-04-26 16:17:04 +00:00
|
|
|
uint64_t ws_max_blks;
|
2013-04-26 16:22:54 +00:00
|
|
|
ws_max_blks = softc->disk->d_delmaxsize / softc->params.secsize;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc->delete_running = 1;
|
|
|
|
lba = bp->bio_pblkno;
|
|
|
|
count = 0;
|
|
|
|
bp1 = bp;
|
|
|
|
do {
|
|
|
|
bioq_remove(&softc->delete_queue, bp1);
|
|
|
|
if (bp1 != bp)
|
|
|
|
bioq_insert_tail(&softc->delete_run_queue, bp1);
|
|
|
|
count += bp1->bio_bcount / softc->params.secsize;
|
2013-04-26 16:17:04 +00:00
|
|
|
if (count > ws_max_blks) {
|
|
|
|
count = min(count, ws_max_blks);
|
|
|
|
xpt_print(periph->path,
|
|
|
|
"%s issuing short delete %ld > %ld",
|
|
|
|
da_delete_method_desc[softc->delete_method],
|
|
|
|
count, ws_max_blks);
|
|
|
|
break;
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bp1 = bioq_first(&softc->delete_queue);
|
|
|
|
if (bp1 == NULL ||
|
|
|
|
lba + count != bp1->bio_pblkno ||
|
|
|
|
count + bp1->bio_bcount /
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->params.secsize > ws_max_blks)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
break;
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
scsi_write_same(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*byte2*/softc->delete_method ==
|
|
|
|
DA_DELETE_ZERO ? 0 : SWS_UNMAP,
|
|
|
|
softc->delete_method ==
|
|
|
|
DA_DELETE_WS16 ? 16 : 10,
|
|
|
|
/*lba*/lba,
|
|
|
|
/*block_count*/count,
|
|
|
|
/*data_ptr*/ __DECONST(void *,
|
|
|
|
zero_region),
|
|
|
|
/*dxfer_len*/ softc->params.secsize,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_DELETE;
|
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
bioq_flush(&softc->delete_queue, NULL, 0);
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
}
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/* Run regular command. */
|
|
|
|
bp = bioq_takefirst(&softc->bio_queue);
|
|
|
|
if (bp == NULL) {
|
2012-07-29 11:51:48 +00:00
|
|
|
if (softc->tur) {
|
|
|
|
softc->tur = 0;
|
|
|
|
scsi_test_unit_ready(&start_ccb->csio,
|
|
|
|
/*retries*/ da_retry_count,
|
|
|
|
dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_TUR;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
} else
|
|
|
|
xpt_release_ccb(start_ccb);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-07-29 11:51:48 +00:00
|
|
|
if (softc->tur) {
|
|
|
|
softc->tur = 0;
|
|
|
|
cam_periph_release_locked(periph);
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
if ((bp->bio_flags & BIO_ORDERED) != 0 ||
|
|
|
|
(softc->flags & DA_FLAG_NEED_OTAG) != 0) {
|
|
|
|
softc->flags &= ~DA_FLAG_NEED_OTAG;
|
|
|
|
softc->ordered_tag_count++;
|
|
|
|
tag_code = MSG_ORDERED_Q_TAG;
|
|
|
|
} else {
|
|
|
|
tag_code = MSG_SIMPLE_Q_TAG;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
switch (bp->bio_cmd) {
|
|
|
|
case BIO_READ:
|
|
|
|
case BIO_WRITE:
|
|
|
|
scsi_read_write(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/tag_code,
|
2013-03-19 15:01:50 +00:00
|
|
|
/*read_op*/(bp->bio_cmd == BIO_READ ?
|
|
|
|
SCSI_RW_READ : SCSI_RW_WRITE) |
|
|
|
|
((bp->bio_flags & BIO_UNMAPPED) != 0 ?
|
|
|
|
SCSI_RW_BIO : 0),
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/*byte2*/0,
|
|
|
|
softc->minimum_cmd_size,
|
|
|
|
/*lba*/bp->bio_pblkno,
|
|
|
|
/*block_count*/bp->bio_bcount /
|
|
|
|
softc->params.secsize,
|
2013-03-19 15:01:50 +00:00
|
|
|
/*data_ptr*/ (bp->bio_flags &
|
|
|
|
BIO_UNMAPPED) != 0 ? (void *)bp :
|
|
|
|
bp->bio_data,
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
/*dxfer_len*/ bp->bio_bcount,
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
da_default_timeout * 1000);
|
|
|
|
break;
|
|
|
|
case BIO_FLUSH:
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
* BIO_FLUSH doesn't currently communicate
|
|
|
|
* range data, so we synchronize the cache
|
|
|
|
* over the whole disk. We also force
|
|
|
|
* ordered tag semantics the flush applies
|
|
|
|
* to all previously queued I/O.
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
scsi_synchronize_cache(&start_ccb->csio,
|
|
|
|
/*retries*/1,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_ORDERED_Q_TAG,
|
|
|
|
/*begin_lba*/0,
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
da_default_timeout*1000);
|
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
|
|
|
|
|
|
|
|
out:
|
|
|
|
/*
|
2013-05-10 16:41:26 +00:00
|
|
|
* Block out any asynchronous callbacks
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
* while we touch the pending ccb list.
|
|
|
|
*/
|
|
|
|
LIST_INSERT_HEAD(&softc->pending_ccbs,
|
|
|
|
&start_ccb->ccb_h, periph_links.le);
|
|
|
|
softc->outstanding_cmds++;
|
|
|
|
|
|
|
|
/* We expect a unit attention from this device */
|
|
|
|
if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
|
|
|
|
start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
|
|
|
|
softc->flags &= ~DA_FLAG_RETRY_UA;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
|
|
|
|
start_ccb->ccb_h.ccb_bp = bp;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
|
|
|
|
/* May have more work to do, so ensure we stay scheduled */
|
|
|
|
daschedule(periph);
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_STATE_PROBE_RC:
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct scsi_read_capacity_data *rcap;
|
|
|
|
|
2007-05-18 21:58:07 +00:00
|
|
|
rcap = (struct scsi_read_capacity_data *)
|
|
|
|
malloc(sizeof(*rcap), M_SCSIDA, M_NOWAIT|M_ZERO);
|
1998-09-15 06:36:34 +00:00
|
|
|
if (rcap == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc read_capacity data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
2013-01-10 11:28:12 +00:00
|
|
|
scsi_read_capacity(&start_ccb->csio,
|
2013-01-10 12:25:00 +00:00
|
|
|
/*retries*/da_retry_count,
|
1998-09-15 06:36:34 +00:00
|
|
|
dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
rcap,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
/*timeout*/5000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
2013-04-26 16:17:04 +00:00
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_RC;
|
1998-09-15 06:36:34 +00:00
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_STATE_PROBE_RC16:
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
{
|
|
|
|
struct scsi_read_capacity_data_long *rcaplong;
|
|
|
|
|
|
|
|
rcaplong = (struct scsi_read_capacity_data_long *)
|
2007-05-18 21:58:07 +00:00
|
|
|
malloc(sizeof(*rcaplong), M_SCSIDA, M_NOWAIT|M_ZERO);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
if (rcaplong == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc read_capacity data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
2013-01-10 11:28:12 +00:00
|
|
|
scsi_read_capacity_16(&start_ccb->csio,
|
2013-01-10 12:25:00 +00:00
|
|
|
/*retries*/ da_retry_count,
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
/*cbfcnp*/ dadone,
|
|
|
|
/*tag_action*/ MSG_SIMPLE_Q_TAG,
|
|
|
|
/*lba*/ 0,
|
|
|
|
/*reladr*/ 0,
|
|
|
|
/*pmi*/ 0,
|
2012-01-26 18:09:28 +00:00
|
|
|
/*rcap_buf*/ (uint8_t *)rcaplong,
|
|
|
|
/*rcap_buf_len*/ sizeof(*rcaplong),
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
/*sense_len*/ SSD_FULL_SIZE,
|
2013-01-10 12:25:00 +00:00
|
|
|
/*timeout*/ da_default_timeout * 1000);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
2013-04-26 16:17:04 +00:00
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_RC16;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DA_STATE_PROBE_LBP:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_logical_block_prov *lbp;
|
|
|
|
|
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_LBP)) {
|
|
|
|
/*
|
|
|
|
* If we get here we don't support any SBC-3 delete
|
|
|
|
* methods with UNMAP as the Logical Block Provisioning
|
|
|
|
* VPD page support is required for devices which
|
|
|
|
* support it according to T10/1799-D Revision 31
|
|
|
|
* however older revisions of the spec don't mandate
|
|
|
|
* this so we currently don't remove these methods
|
|
|
|
* from the available set.
|
|
|
|
*/
|
|
|
|
softc->state = DA_STATE_PROBE_BLK_LIMITS;
|
|
|
|
goto skipstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
lbp = (struct scsi_vpd_logical_block_prov *)
|
|
|
|
malloc(sizeof(*lbp), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (lbp == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc lbp data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_inquiry(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*inq_buf*/(u_int8_t *)lbp,
|
|
|
|
/*inq_len*/sizeof(*lbp),
|
|
|
|
/*evpd*/TRUE,
|
|
|
|
/*page_code*/SVPD_LBP,
|
|
|
|
/*sense_len*/SSD_MIN_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_LBP;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DA_STATE_PROBE_BLK_LIMITS:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_limits *block_limits;
|
|
|
|
|
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_BLOCK_LIMITS)) {
|
|
|
|
/* Not supported skip to next probe */
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
goto skipstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
block_limits = (struct scsi_vpd_block_limits *)
|
|
|
|
malloc(sizeof(*block_limits), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (block_limits == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc block_limits data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_inquiry(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*inq_buf*/(u_int8_t *)block_limits,
|
|
|
|
/*inq_len*/sizeof(*block_limits),
|
|
|
|
/*evpd*/TRUE,
|
|
|
|
/*page_code*/SVPD_BLOCK_LIMITS,
|
|
|
|
/*sense_len*/SSD_MIN_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_BLK_LIMITS;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
case DA_STATE_PROBE_BDC:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_characteristics *bdc;
|
|
|
|
|
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_BDC)) {
|
|
|
|
softc->state = DA_STATE_PROBE_ATA;
|
|
|
|
goto skipstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
bdc = (struct scsi_vpd_block_characteristics *)
|
|
|
|
malloc(sizeof(*bdc), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (bdc == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc bdc data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_inquiry(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*inq_buf*/(u_int8_t *)bdc,
|
|
|
|
/*inq_len*/sizeof(*bdc),
|
|
|
|
/*evpd*/TRUE,
|
|
|
|
/*page_code*/SVPD_BDC,
|
|
|
|
/*sense_len*/SSD_MIN_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_BDC;
|
|
|
|
xpt_action(start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_STATE_PROBE_ATA:
|
|
|
|
{
|
|
|
|
struct ata_params *ata_params;
|
|
|
|
|
2013-05-02 14:37:23 +00:00
|
|
|
if (!scsi_vpd_supported_page(periph, SVPD_ATA_INFORMATION)) {
|
|
|
|
daprobedone(periph, start_ccb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
ata_params = (struct ata_params*)
|
|
|
|
malloc(sizeof(*ata_params), M_SCSIDA, M_NOWAIT|M_ZERO);
|
|
|
|
|
|
|
|
if (ata_params == NULL) {
|
|
|
|
printf("dastart: Couldn't malloc ata_params data\n");
|
|
|
|
/* da_free_periph??? */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
scsi_ata_identify(&start_ccb->csio,
|
|
|
|
/*retries*/da_retry_count,
|
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
|
|
|
/*data_ptr*/(u_int8_t *)ata_params,
|
|
|
|
/*dxfer_len*/sizeof(*ata_params),
|
|
|
|
/*sense_len*/SSD_FULL_SIZE,
|
|
|
|
/*timeout*/da_default_timeout * 1000);
|
|
|
|
start_ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_ATA;
|
|
|
|
xpt_action(start_ccb);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
break;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-23 18:18:02 +00:00
|
|
|
static int
|
|
|
|
cmd6workaround(union ccb *ccb)
|
|
|
|
{
|
|
|
|
struct scsi_rw_6 cmd6;
|
|
|
|
struct scsi_rw_10 *cmd10;
|
|
|
|
struct da_softc *softc;
|
2002-08-16 22:05:19 +00:00
|
|
|
u_int8_t *cdb;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio *bp;
|
2002-08-16 22:05:19 +00:00
|
|
|
int frozen;
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
cdb = ccb->csio.cdb_io.cdb_bytes;
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
|
|
|
|
|
|
|
|
if (ccb->ccb_h.ccb_state == DA_CCB_DELETE) {
|
2013-04-26 16:17:04 +00:00
|
|
|
da_delete_methods old_method = softc->delete_method;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Typically there are two reasons for failure here
|
|
|
|
* 1. Delete method was detected as supported but isn't
|
|
|
|
* 2. Delete failed due to invalid params e.g. too big
|
|
|
|
*
|
|
|
|
* While we will attempt to choose an alternative delete method
|
|
|
|
* this may result in short deletes if the existing delete
|
|
|
|
* requests from geom are big for the new method choosen.
|
|
|
|
*
|
|
|
|
* This method assumes that the error which triggered this
|
|
|
|
* will not retry the io otherwise a panic will occur
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, old_method, 0);
|
|
|
|
dadeletemethodchoose(softc, DA_DELETE_DISABLE);
|
|
|
|
if (softc->delete_method == DA_DELETE_DISABLE)
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
2013-04-26 16:17:04 +00:00
|
|
|
"%s failed, disabling BIO_DELETE\n",
|
|
|
|
da_delete_method_desc[old_method]);
|
|
|
|
else
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
xpt_print(ccb->ccb_h.path,
|
2013-04-26 16:17:04 +00:00
|
|
|
"%s failed, switching to %s BIO_DELETE\n",
|
|
|
|
da_delete_method_desc[old_method],
|
|
|
|
da_delete_method_desc[softc->delete_method]);
|
2013-03-29 22:58:15 +00:00
|
|
|
|
|
|
|
if (DA_SIO) {
|
|
|
|
while ((bp = bioq_takefirst(&softc->delete_run_queue))
|
|
|
|
!= NULL)
|
|
|
|
bioq_disksort(&softc->delete_queue, bp);
|
|
|
|
} else {
|
|
|
|
while ((bp = bioq_takefirst(&softc->delete_run_queue))
|
|
|
|
!= NULL)
|
|
|
|
bioq_insert_tail(&softc->delete_queue, bp);
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bioq_insert_tail(&softc->delete_queue,
|
|
|
|
(struct bio *)ccb->ccb_h.ccb_bp);
|
|
|
|
ccb->ccb_h.ccb_bp = NULL;
|
|
|
|
return (0);
|
|
|
|
}
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
/* Translation only possible if CDB is an array and cmd is R/W6 */
|
|
|
|
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
|
|
|
|
(*cdb != READ_6 && *cdb != WRITE_6))
|
2002-03-23 18:18:02 +00:00
|
|
|
return 0;
|
|
|
|
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(ccb->ccb_h.path, "READ(6)/WRITE(6) not supported, "
|
|
|
|
"increasing minimum_cmd_size to 10.\n");
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
softc->minimum_cmd_size = 10;
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
|
|
|
|
cmd10 = (struct scsi_rw_10 *)cdb;
|
2002-03-23 18:18:02 +00:00
|
|
|
cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
|
|
|
|
cmd10->byte2 = 0;
|
|
|
|
scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
|
|
|
|
cmd10->reserved = 0;
|
|
|
|
scsi_ulto2b(cmd6.length, cmd10->length);
|
|
|
|
cmd10->control = cmd6.control;
|
2002-08-16 22:05:19 +00:00
|
|
|
ccb->csio.cdb_len = sizeof(*cmd10);
|
2002-03-23 18:18:02 +00:00
|
|
|
|
2002-08-16 22:05:19 +00:00
|
|
|
/* Requeue request, unfreezing queue if necessary */
|
|
|
|
frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
|
2002-03-23 18:18:02 +00:00
|
|
|
ccb->ccb_h.status = CAM_REQUEUE_REQ;
|
|
|
|
xpt_action(ccb);
|
2002-08-16 22:05:19 +00:00
|
|
|
if (frozen) {
|
2002-03-23 18:18:02 +00:00
|
|
|
cam_release_devq(ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
2002-08-16 22:05:19 +00:00
|
|
|
}
|
2002-03-23 18:18:02 +00:00
|
|
|
return (ERESTART);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
dadone(struct cam_periph *periph, union ccb *done_ccb)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct ccb_scsiio *csio;
|
2009-10-31 10:43:38 +00:00
|
|
|
u_int32_t priority;
|
2013-01-11 16:10:11 +00:00
|
|
|
da_ccb_state state;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
2009-10-31 10:43:38 +00:00
|
|
|
priority = done_ccb->ccb_h.pinfo.priority;
|
2012-06-05 09:45:42 +00:00
|
|
|
|
|
|
|
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
csio = &done_ccb->csio;
|
2013-01-11 16:10:11 +00:00
|
|
|
state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
|
|
|
|
switch (state) {
|
1998-09-15 06:36:34 +00:00
|
|
|
case DA_CCB_BUFFER_IO:
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
case DA_CCB_DELETE:
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
struct bio *bp, *bp1;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
|
|
int error;
|
|
|
|
int sf;
|
2011-06-14 16:05:00 +00:00
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
|
|
|
|
sf = SF_RETRY_UA;
|
|
|
|
else
|
|
|
|
sf = 0;
|
|
|
|
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
|
|
|
|
if (error == ERESTART) {
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
2013-04-26 16:17:04 +00:00
|
|
|
* A retry was scheduled, so
|
1998-09-15 06:36:34 +00:00
|
|
|
* just return.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
|
1998-09-15 06:36:34 +00:00
|
|
|
if (error != 0) {
|
2011-06-14 16:05:00 +00:00
|
|
|
int queued_error;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* return all queued I/O with EIO, so that
|
|
|
|
* the client can retry these I/Os in the
|
|
|
|
* proper order should it attempt to recover.
|
|
|
|
*/
|
|
|
|
queued_error = EIO;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2011-06-14 16:05:00 +00:00
|
|
|
if (error == ENXIO
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_INVALID)== 0) {
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Catastrophic error. Mark our pack as
|
|
|
|
* invalid.
|
|
|
|
*/
|
2006-12-05 07:45:28 +00:00
|
|
|
/*
|
|
|
|
* XXX See if this is really a media
|
|
|
|
* XXX change first?
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path,
|
|
|
|
"Invalidating pack\n");
|
1998-09-15 06:36:34 +00:00
|
|
|
softc->flags |= DA_FLAG_PACK_INVALID;
|
2011-06-14 16:05:00 +00:00
|
|
|
queued_error = ENXIO;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2011-06-14 16:05:00 +00:00
|
|
|
bioq_flush(&softc->bio_queue, NULL,
|
|
|
|
queued_error);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
if (bp != NULL) {
|
|
|
|
bp->bio_error = error;
|
|
|
|
bp->bio_resid = bp->bio_bcount;
|
|
|
|
bp->bio_flags |= BIO_ERROR;
|
|
|
|
}
|
|
|
|
} else if (bp != NULL) {
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_resid = csio->resid;
|
|
|
|
bp->bio_error = 0;
|
2003-08-06 14:24:16 +00:00
|
|
|
if (bp->bio_resid != 0)
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_flags |= BIO_ERROR;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
} else if (bp != NULL) {
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
panic("REQ_CMP with QFRZN");
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_resid = csio->resid;
|
2003-08-06 14:24:16 +00:00
|
|
|
if (csio->resid > 0)
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_flags |= BIO_ERROR;
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
if (softc->error_inject != 0) {
|
|
|
|
bp->bio_error = softc->error_inject;
|
|
|
|
bp->bio_resid = bp->bio_bcount;
|
|
|
|
bp->bio_flags |= BIO_ERROR;
|
|
|
|
softc->error_inject = 0;
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-05-10 16:41:26 +00:00
|
|
|
* Block out any asynchronous callbacks
|
1998-09-15 06:36:34 +00:00
|
|
|
* while we touch the pending ccb list.
|
|
|
|
*/
|
|
|
|
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
|
2003-03-15 11:00:56 +00:00
|
|
|
softc->outstanding_cmds--;
|
|
|
|
if (softc->outstanding_cmds == 0)
|
1998-09-15 06:36:34 +00:00
|
|
|
softc->flags |= DA_FLAG_WENT_IDLE;
|
|
|
|
|
2013-01-11 16:10:11 +00:00
|
|
|
if (state == DA_CCB_DELETE) {
|
Add BIO_DELETE support for SCSI Direct Access devices (da).
Depending on device capabilities use different methods to implement it.
Currently used method can be read/set via kern.cam.da.X.delete_method
sysctls. Possible values are:
NONE - no provisioning support reported by the device;
DISABLE - provisioning support was disabled because of errors;
ZERO - use WRITE SAME (10) command to write zeroes;
WS10 - use WRITE SAME (10) command with UNMAP bit set;
WS16 - use WRITE SAME (16) command with UNMAP bit set;
UNMAP - use UNMAP command (equivalent of the ATA DSM TRIM command).
The last two methods (UNMAP and WS16) are defined by SBC specification and
the UNMAP method is the most advanced one. The rest of methods I've found
supported in Linux, and as soon as they were trivial to implement, then
why not? Hope they will be useful in some cases.
Unluckily I have no devices properly reporting parameters of the logical
block provisioning support via respective VPD pages (0xB0 and 0xB2). So
all info I have/use now is the flag telling whether logical block
provisioning is supported or not. As result, specific methods chosen now
by trying different ones in order (UNMAP, WS16, DISABLE) and checking
completion status to fallback if needed. I don't expect problems from this,
as if something go wrong, it should just disable itself. It may disable
even too aggressively if only some command parameter misfit.
Unlike Linux, which executes each delete with separate request, I've
implemented here the same request aggregation as implemented in ada driver.
Tests on SSDs I have show much better results doing it this way: above
8GB/s of the linear delete on Intel SATA SSD on LSI SAS HBA (mps).
Reviewed by: silence on scsi@
MFC after: 2 month
Sponsored by: iXsystems, Inc.
2012-01-13 10:21:17 +00:00
|
|
|
while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
|
|
|
|
!= NULL) {
|
|
|
|
bp1->bio_resid = bp->bio_resid;
|
|
|
|
bp1->bio_error = bp->bio_error;
|
|
|
|
if (bp->bio_flags & BIO_ERROR)
|
|
|
|
bp1->bio_flags |= BIO_ERROR;
|
|
|
|
biodone(bp1);
|
|
|
|
}
|
|
|
|
softc->delete_running = 0;
|
|
|
|
if (bp != NULL)
|
|
|
|
biodone(bp);
|
|
|
|
daschedule(periph);
|
|
|
|
} else if (bp != NULL)
|
|
|
|
biodone(bp);
|
1998-09-15 06:36:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_CCB_PROBE_RC:
|
|
|
|
case DA_CCB_PROBE_RC16:
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct scsi_read_capacity_data *rdcap;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
struct scsi_read_capacity_data_long *rcaplong;
|
1998-09-15 06:36:34 +00:00
|
|
|
char announce_buf[80];
|
2013-04-26 16:17:04 +00:00
|
|
|
int lbp;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
lbp = 0;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
rdcap = NULL;
|
|
|
|
rcaplong = NULL;
|
2013-04-26 16:17:04 +00:00
|
|
|
if (state == DA_CCB_PROBE_RC)
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
|
|
|
|
else
|
|
|
|
rcaplong = (struct scsi_read_capacity_data_long *)
|
|
|
|
csio->data_ptr;
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
|
|
|
struct disk_params *dp;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
uint32_t block_size;
|
|
|
|
uint64_t maxsector;
|
2011-12-23 19:12:02 +00:00
|
|
|
u_int lbppbe; /* LB per physical block exponent. */
|
|
|
|
u_int lalba; /* Lowest aligned LBA. */
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
if (state == DA_CCB_PROBE_RC) {
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
block_size = scsi_4btoul(rdcap->length);
|
|
|
|
maxsector = scsi_4btoul(rdcap->addr);
|
2011-12-23 19:12:02 +00:00
|
|
|
lbppbe = 0;
|
|
|
|
lalba = 0;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
/*
|
|
|
|
* According to SBC-2, if the standard 10
|
|
|
|
* byte READ CAPACITY command returns 2^32,
|
|
|
|
* we should issue the 16 byte version of
|
|
|
|
* the command, since the device in question
|
|
|
|
* has more sectors than can be represented
|
|
|
|
* with the short version of the command.
|
|
|
|
*/
|
|
|
|
if (maxsector == 0xffffffff) {
|
2007-05-14 21:48:53 +00:00
|
|
|
free(rdcap, M_SCSIDA);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC16;
|
2009-10-31 10:43:38 +00:00
|
|
|
xpt_schedule(periph, priority);
|
2003-05-03 00:21:40 +00:00
|
|
|
return;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
block_size = scsi_4btoul(rcaplong->length);
|
|
|
|
maxsector = scsi_8btou64(rcaplong->addr);
|
2011-12-23 19:12:02 +00:00
|
|
|
lbppbe = rcaplong->prot_lbppbe & SRC16_LBPPBE;
|
|
|
|
lalba = scsi_2btoul(rcaplong->lalba_lbp);
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
}
|
2006-09-16 21:21:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Because GEOM code just will panic us if we
|
|
|
|
* give them an 'illegal' value we'll avoid that
|
|
|
|
* here.
|
|
|
|
*/
|
2010-10-24 18:53:16 +00:00
|
|
|
if (block_size == 0 && maxsector == 0) {
|
2013-05-03 11:53:06 +00:00
|
|
|
block_size = 512;
|
|
|
|
maxsector = -1;
|
|
|
|
}
|
|
|
|
if (block_size >= MAXPHYS || block_size == 0) {
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path,
|
|
|
|
"unsupportable block size %ju\n",
|
|
|
|
(uintmax_t) block_size);
|
2006-09-16 21:21:07 +00:00
|
|
|
announce_buf[0] = '\0';
|
|
|
|
cam_periph_invalidate(periph);
|
|
|
|
} else {
|
2012-01-26 18:09:28 +00:00
|
|
|
/*
|
|
|
|
* We pass rcaplong into dasetgeom(),
|
|
|
|
* because it will only use it if it is
|
|
|
|
* non-NULL.
|
|
|
|
*/
|
2011-12-23 19:12:02 +00:00
|
|
|
dasetgeom(periph, block_size, maxsector,
|
2012-01-26 18:09:28 +00:00
|
|
|
rcaplong, sizeof(*rcaplong));
|
2013-04-26 16:17:04 +00:00
|
|
|
lbp = (lalba & SRC16_LBPME_A);
|
2006-09-16 21:21:07 +00:00
|
|
|
dp = &softc->params;
|
|
|
|
snprintf(announce_buf, sizeof(announce_buf),
|
|
|
|
"%juMB (%ju %u byte sectors: %dH %dS/T "
|
|
|
|
"%dC)", (uintmax_t)
|
|
|
|
(((uintmax_t)dp->secsize *
|
|
|
|
dp->sectors) / (1024*1024)),
|
|
|
|
(uintmax_t)dp->sectors,
|
|
|
|
dp->secsize, dp->heads,
|
|
|
|
dp->secs_per_track, dp->cylinders);
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
|
1999-08-15 23:34:40 +00:00
|
|
|
announce_buf[0] = '\0';
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Retry any UNIT ATTENTION type errors. They
|
|
|
|
* are expected at boot.
|
|
|
|
*/
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
1998-09-15 06:36:34 +00:00
|
|
|
if (error == ERESTART) {
|
|
|
|
/*
|
|
|
|
* A retry was scheuled, so
|
|
|
|
* just return.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
} else if (error != 0) {
|
|
|
|
int asc, ascq;
|
|
|
|
int sense_key, error_code;
|
|
|
|
int have_sense;
|
|
|
|
cam_status status;
|
|
|
|
struct ccb_getdev cgd;
|
|
|
|
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
status = done_ccb->ccb_h.status;
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
if ((status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
xpt_setup_ccb(&cgd.ccb_h,
|
|
|
|
done_ccb->ccb_h.path,
|
2009-10-23 08:27:55 +00:00
|
|
|
CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
|
|
|
|
xpt_action((union ccb *)&cgd);
|
|
|
|
|
2012-06-23 12:32:53 +00:00
|
|
|
if (scsi_extract_sense_ccb(done_ccb,
|
|
|
|
&error_code, &sense_key, &asc, &ascq))
|
1998-09-15 06:36:34 +00:00
|
|
|
have_sense = TRUE;
|
2012-06-23 12:32:53 +00:00
|
|
|
else
|
|
|
|
have_sense = FALSE;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2011-12-23 19:12:02 +00:00
|
|
|
/*
|
|
|
|
* If we tried READ CAPACITY(16) and failed,
|
|
|
|
* fallback to READ CAPACITY(10).
|
|
|
|
*/
|
2013-04-26 16:17:04 +00:00
|
|
|
if ((state == DA_CCB_PROBE_RC16) &&
|
2011-12-23 19:12:02 +00:00
|
|
|
(softc->flags & DA_FLAG_CAN_RC16) &&
|
|
|
|
(((csio->ccb_h.status & CAM_STATUS_MASK) ==
|
|
|
|
CAM_REQ_INVALID) ||
|
|
|
|
((have_sense) &&
|
|
|
|
(error_code == SSD_CURRENT_ERROR) &&
|
|
|
|
(sense_key == SSD_KEY_ILLEGAL_REQUEST)))) {
|
|
|
|
softc->flags &= ~DA_FLAG_CAN_RC16;
|
|
|
|
free(rdcap, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC;
|
2011-12-23 19:12:02 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
} else
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland
applications, like cdrecord, xmcd, etc., that use the CAM passthrough
interface. A make world is recommended.
camcontrol.[c8]:
- We now support two new commands, "tags" and "negotiate".
- The tags commands allows users to view the number of tagged
openings for a device as well as a number of other related
parameters, and it allows users to set tagged openings for
a device.
- The negotiate command allows users to enable and disable
disconnection and tagged queueing, set sync rates, offsets
and bus width. Note that not all of those features are
available for all controllers. Only the adv, ahc, and ncr
drivers fully support all of the features at this point.
Some cards do not allow the setting of sync rates, offsets and
the like, and some of the drivers don't have any facilities to
do so. Some drivers, like the adw driver, only support enabling
or disabling sync negotiation, but do not support setting sync
rates.
- new description in the camcontrol man page of how to format a disk
- cleanup of the camcontrol inquiry command
- add support in the 'devlist' command for skipping unconfigured devices if
-v was not specified on the command line.
- make use of the new base_transfer_speed in the path inquiry CCB.
- fix CCB bzero cases
cam_xpt.c, cam_sim.[ch], cam_ccb.h:
- new flags on many CCB function codes to designate whether they're
non-immediate, use a user-supplied CCB, and can only be passed from
userland programs via the xpt device. Use these flags in the transport
layer and pass driver to categorize CCBs.
- new flag in the transport layer device matching code for device nodes
that indicates whether a device is unconfigured
- bump the CAM version from 0x10 to 0x11
- Change the CAM ioctls to use the version as their group code, so we can
force users to recompile code even when the CCB size doesn't change.
- add + fill in a new value in the path inquiry CCB, base_transfer_speed.
Remove a corresponding field from the cam_sim structure, and add code to
every SIM to set this field to the proper value.
- Fix the set transfer settings code in the transport layer.
scsi_cd.c:
- make some variables volatile instead of just casting them in various
places
- fix a race condition in the changer code
- attach unless we get a "logical unit not supported" error. This should
fix all of the cases where people have devices that return weird errors
when they don't have media in the drive.
scsi_da.c:
- attach unless we get a "logical unit not supported" error
scsi_pass.c:
- for immediate CCBs, just malloc a CCB to send the user request in. This
gets rid of the 'held' count problem in camcontrol tags.
scsi_pass.h:
- change the CAM ioctls to use the CAM version as their group code.
adv driver:
- Allow changing the sync rate and offset separately.
adw driver
- Allow changing the sync rate and offset separately.
aha driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
ahc driver:
- Allow setting offset and sync rate separately
bt driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
NCR driver:
- Fix the ultra/ultra 2 negotiation bug
- allow setting both the sync rate and offset separately
Other HBA drivers:
- Put code in to set the base_transfer_speed field for
XPT_GET_TRAN_SETTINGS CCBs.
Reviewed by: gibbs, mjacob (isp), imp (aha)
1999-05-06 20:16:39 +00:00
|
|
|
* Attach to anything that claims to be a
|
|
|
|
* direct access or optical disk device,
|
|
|
|
* as long as it doesn't return a "Logical
|
|
|
|
* unit not supported" (0x25) error.
|
1998-09-15 06:36:34 +00:00
|
|
|
*/
|
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland
applications, like cdrecord, xmcd, etc., that use the CAM passthrough
interface. A make world is recommended.
camcontrol.[c8]:
- We now support two new commands, "tags" and "negotiate".
- The tags commands allows users to view the number of tagged
openings for a device as well as a number of other related
parameters, and it allows users to set tagged openings for
a device.
- The negotiate command allows users to enable and disable
disconnection and tagged queueing, set sync rates, offsets
and bus width. Note that not all of those features are
available for all controllers. Only the adv, ahc, and ncr
drivers fully support all of the features at this point.
Some cards do not allow the setting of sync rates, offsets and
the like, and some of the drivers don't have any facilities to
do so. Some drivers, like the adw driver, only support enabling
or disabling sync negotiation, but do not support setting sync
rates.
- new description in the camcontrol man page of how to format a disk
- cleanup of the camcontrol inquiry command
- add support in the 'devlist' command for skipping unconfigured devices if
-v was not specified on the command line.
- make use of the new base_transfer_speed in the path inquiry CCB.
- fix CCB bzero cases
cam_xpt.c, cam_sim.[ch], cam_ccb.h:
- new flags on many CCB function codes to designate whether they're
non-immediate, use a user-supplied CCB, and can only be passed from
userland programs via the xpt device. Use these flags in the transport
layer and pass driver to categorize CCBs.
- new flag in the transport layer device matching code for device nodes
that indicates whether a device is unconfigured
- bump the CAM version from 0x10 to 0x11
- Change the CAM ioctls to use the version as their group code, so we can
force users to recompile code even when the CCB size doesn't change.
- add + fill in a new value in the path inquiry CCB, base_transfer_speed.
Remove a corresponding field from the cam_sim structure, and add code to
every SIM to set this field to the proper value.
- Fix the set transfer settings code in the transport layer.
scsi_cd.c:
- make some variables volatile instead of just casting them in various
places
- fix a race condition in the changer code
- attach unless we get a "logical unit not supported" error. This should
fix all of the cases where people have devices that return weird errors
when they don't have media in the drive.
scsi_da.c:
- attach unless we get a "logical unit not supported" error
scsi_pass.c:
- for immediate CCBs, just malloc a CCB to send the user request in. This
gets rid of the 'held' count problem in camcontrol tags.
scsi_pass.h:
- change the CAM ioctls to use the CAM version as their group code.
adv driver:
- Allow changing the sync rate and offset separately.
adw driver
- Allow changing the sync rate and offset separately.
aha driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
ahc driver:
- Allow setting offset and sync rate separately
bt driver:
- Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs.
NCR driver:
- Fix the ultra/ultra 2 negotiation bug
- allow setting both the sync rate and offset separately
Other HBA drivers:
- Put code in to set the base_transfer_speed field for
XPT_GET_TRAN_SETTINGS CCBs.
Reviewed by: gibbs, mjacob (isp), imp (aha)
1999-05-06 20:16:39 +00:00
|
|
|
if ((have_sense) && (asc != 0x25)
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
&& (error_code == SSD_CURRENT_ERROR)) {
|
|
|
|
const char *sense_key_desc;
|
|
|
|
const char *asc_desc;
|
|
|
|
|
2013-05-03 11:53:06 +00:00
|
|
|
dasetgeom(periph, 512, -1, NULL, 0);
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
scsi_sense_desc(sense_key, asc, ascq,
|
|
|
|
&cgd.inq_data,
|
|
|
|
&sense_key_desc,
|
|
|
|
&asc_desc);
|
1998-12-04 22:54:57 +00:00
|
|
|
snprintf(announce_buf,
|
|
|
|
sizeof(announce_buf),
|
1998-09-15 06:36:34 +00:00
|
|
|
"Attempt to query device "
|
|
|
|
"size failed: %s, %s",
|
Rewrite of the CAM error recovery code.
Some of the major changes include:
- The SCSI error handling portion of cam_periph_error() has
been broken out into a number of subfunctions to better
modularize the code that handles the hierarchy of SCSI errors.
As a result, the code is now much easier to read.
- String handling and error printing has been significantly
revamped. We now use sbufs to do string formatting instead
of using printfs (for the kernel) and snprintf/strncat (for
userland) as before.
There is a new catchall error printing routine,
cam_error_print() and its string-based counterpart,
cam_error_string() that allow the kernel and userland
applications to pass in a CCB and have errors printed out
properly, whether or not they're SCSI errors. Among other
things, this helped eliminate a fair amount of duplicate code
in camcontrol.
We now print out more information than before, including
the CAM status and SCSI status and the error recovery action
taken to remedy the problem.
- sbufs are now available in userland, via libsbuf. This
change was necessary since most of the error printing code
is shared between libcam and the kernel.
- A new transfer settings interface is included in this checkin.
This code is #ifdef'ed out, and is primarily intended to aid
discussion with HBA driver authors on the final form the
interface should take. There is example code in the ahc(4)
driver that implements the HBA driver side of the new
interface. The new transfer settings code won't be enabled
until we're ready to switch all HBA drivers over to the new
interface.
src/Makefile.inc1,
lib/Makefile: Add libsbuf. It must be built before libcam,
since libcam uses sbuf routines.
libcam/Makefile: libcam now depends on libsbuf.
libsbuf/Makefile: Add a makefile for libsbuf. This pulls in the
sbuf sources from sys/kern.
bsd.libnames.mk: Add LIBSBUF.
camcontrol/Makefile: Add -lsbuf. Since camcontrol is statically
linked, we can't depend on the dynamic linker
to pull in libsbuf.
camcontrol.c: Use cam_error_print() instead of checking for
CAM_SCSI_STATUS_ERROR on every failed CCB.
sbuf.9: Change the prototypes for sbuf_cat() and
sbuf_cpy() so that the source string is now a
const char *. This is more in line wth the
standard system string functions, and helps
eliminate warnings when dealing with a const
source buffer.
Fix a typo.
cam.c: Add description strings for the various CAM
error status values, as well as routines to
look up those strings.
Add new cam_error_string() and
cam_error_print() routines for userland and
the kernel.
cam.h: Add a new CAM flag, CAM_RETRY_SELTO.
Add enumerated types for the various options
available with cam_error_print() and
cam_error_string().
cam_ccb.h: Add new transfer negotiation structures/types.
Change inq_len in the ccb_getdev structure to
be "reserved". This field has never been
filled in, and will be removed when we next
bump the CAM version.
cam_debug.h: Fix typo.
cam_periph.c: Modularize cam_periph_error(). The SCSI error
handling part of cam_periph_error() is now
in camperiphscsistatuserror() and
camperiphscsisenseerror().
In cam_periph_lock(), increase the reference
count on the periph while we wait for our lock
attempt to succeed so that the periph won't go
away while we're sleeping.
cam_xpt.c: Add new transfer negotiation code. (ifdefed
out)
Add a new function, xpt_path_string(). This
is a string/sbuf analog to xpt_print_path().
scsi_all.c: Revamp string handing and error printing code.
We now use sbufs for much of the string
formatting code. More of that code is shared
between userland the kernel.
scsi_all.h: Get rid of SS_TURSTART, it wasn't terribly
useful in the first place.
Add a new error action, SS_REQSENSE. (Send a
request sense and then retry the command.)
This is useful when the controller hasn't
performed autosense for some reason.
Change the default actions around a bit.
scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c: SF_RETRY_SELTO -> CAM_RETRY_SELTO. Selection
timeouts shouldn't be covered by a sense flag.
scsi_pass.[ch]: SF_RETRY_SELTO -> CAM_RETRY_SELTO.
Get rid of the last vestiges of a read/write
interface.
libkern/bsearch.c,
sys/libkern.h,
conf/files: Add bsearch.c, which is needed for some of the
new table lookup routines.
aic7xxx_freebsd.c: Define AHC_NEW_TRAN_SETTINGS if
CAM_NEW_TRAN_CODE is defined.
sbuf.h,
subr_sbuf.c: Add the appropriate #ifdefs so sbufs can
compile and run in userland.
Change sbuf_printf() to use vsnprintf()
instead of kvprintf(), which is only available
in the kernel.
Change the source string for sbuf_cpy() and
sbuf_cat() to be a const char *.
Add __BEGIN_DECLS and __END_DECLS around
function prototypes since they're now exported
to userland.
kdump/mkioctls: Include stdio.h before cam.h since cam.h now
includes a function with a FILE * argument.
Submitted by: gibbs (mostly)
Reviewed by: jdp, marcel (libsbuf makefile changes)
Reviewed by: des (sbuf changes)
Reviewed by: ken
2001-03-27 05:45:52 +00:00
|
|
|
sense_key_desc,
|
|
|
|
asc_desc);
|
|
|
|
} else {
|
1998-10-07 02:57:57 +00:00
|
|
|
if (have_sense)
|
|
|
|
scsi_sense_print(
|
|
|
|
&done_ccb->csio);
|
|
|
|
else {
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path,
|
|
|
|
"got CAM status %#x\n",
|
|
|
|
done_ccb->ccb_h.status);
|
1998-10-07 02:57:57 +00:00
|
|
|
}
|
1999-01-07 20:19:09 +00:00
|
|
|
|
2006-12-05 07:45:28 +00:00
|
|
|
xpt_print(periph->path, "fatal error, "
|
|
|
|
"failed to attach to device\n");
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Free up resources.
|
|
|
|
*/
|
|
|
|
cam_periph_invalidate(periph);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-14 21:48:53 +00:00
|
|
|
free(csio->data_ptr, M_SCSIDA);
|
2012-04-12 12:58:14 +00:00
|
|
|
if (announce_buf[0] != '\0' && ((softc->flags & DA_FLAG_PROBED) == 0)) {
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
/*
|
|
|
|
* Create our sysctl variables, now that we know
|
|
|
|
* we have successfully attached.
|
|
|
|
*/
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
/* increase the refcount */
|
|
|
|
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
|
|
|
taskqueue_enqueue(taskqueue_thread,
|
|
|
|
&softc->sysctl_task);
|
|
|
|
xpt_announce_periph(periph, announce_buf);
|
2013-04-26 16:17:04 +00:00
|
|
|
|
Fix a race condition in CAM peripheral free handling, locking
in the CAM XPT bus traversal code, and a number of other periph level
issues.
cam_periph.h,
cam_periph.c: Modify cam_periph_acquire() to test the CAM_PERIPH_INVALID
flag prior to allowing a reference count to be gained
on a peripheral. Callers of this function will receive
CAM_REQ_CMP_ERR status in the situation of attempting to
reference an invalidated periph. This guarantees that
a peripheral scheduled for a deferred free will not
be accessed during its wait for destruction.
Panic during attempts to drop a reference count on
a peripheral that already has a zero reference count.
In cam_periph_list(), use a local sbuf with SBUF_FIXEDLEN
set so that mallocs do not occur while the xpt topology
lock is held, regardless of the allocation policy of the
passed in sbuf.
Add a new routine, cam_periph_release_locked_buses(),
that can be called when the caller already holds
the CAM topology lock.
Add some extra debugging for duplicate peripheral
allocations in cam_periph_alloc().
Treat CAM_DEV_NOT_THERE much the same as a selection
timeout (AC_LOST_DEVICE is emitted), but forgo retries.
cam_xpt.c: Revamp the way the EDT traversal code does locking
and reference counting. This was broken, since it
assumed that the EDT would not change during
traversal, but that assumption is no longer valid.
So, to prevent devices from going away while we
traverse the EDT, make sure we properly lock
everything and hold references on devices that
we are using.
The two peripheral driver traversal routines should
be examined. xptpdperiphtraverse() holds the
topology lock for the entire time it runs.
xptperiphtraverse() is now locked properly, but
only holds the topology lock while it is traversing
the list, and not while the traversal function is
running.
The bus locking code in xptbustraverse() should
also be revisited at a later time, since it is
complex and should probably be simplified.
scsi_da.c: Pay attention to the return value from cam_periph_acquire().
Return 0 always from daclose() even if the disk is now gone.
Add some rudimentary error injection support.
scsi_sg.c: Fix reference counting in the sg(4) driver.
The sg driver was calling cam_periph_release() on close,
but never called cam_periph_acquire() (which increments
the reference count) on open.
The periph code correctly complained that the sg(4)
driver was trying to decrement the refcount when it
was already 0.
Sponsored by: Spectra Logic
MFC after: 2 weeks
2012-01-12 00:41:48 +00:00
|
|
|
} else {
|
|
|
|
xpt_print(periph->path, "fatal error, "
|
|
|
|
"could not acquire reference count\n");
|
|
|
|
}
|
Move dynamic sysctl(8) variable creation for the cd(4) and da(4) drivers
out of cdregister() and daregister(), which are run from interrupt context.
The sysctl code does blocking mallocs (M_WAITOK), which causes problems
if malloc(9) actually needs to sleep.
The eventual fix for this issue will involve moving the CAM probe process
inside a kernel thread. For now, though, I have fixed the issue by moving
dynamic sysctl variable creation for these two drivers to a task queue
running in a kernel thread.
The existing task queues (taskqueue_swi and taskqueue_swi_giant) run in
software interrupt handlers, which wouldn't fix the problem at hand. So I
have created a new task queue, taskqueue_thread, that runs inside a kernel
thread. (It also runs outside of Giant -- clients must explicitly acquire
and release Giant in their taskqueue functions.)
scsi_cd.c: Remove sysctl variable creation code from cdregister(), and
move it to a new function, cdsysctlinit(). Queue
cdsysctlinit() to the taskqueue_thread taskqueue once we
have fully registered the cd(4) driver instance.
scsi_da.c: Remove sysctl variable creation code from daregister(), and
move it to move it to a new function, dasysctlinit().
Queue dasysctlinit() to the taskqueue_thread taskqueue once
we have fully registered the da(4) instance.
taskqueue.h: Declare the new taskqueue_thread taskqueue, update some
comments.
subr_taskqueue.c:
Create the new kernel thread taskqueue. This taskqueue
runs outside of Giant, so any functions queued to it would
need to explicitly acquire/release Giant if they need it.
cd.4: Update the cd(4) man page to talk about the minimum command
size sysctl/loader tunable. Also note that the changer
variables are available as loader tunables as well.
da.4: Update the da(4) man page to cover the retry_count,
default_timeout and minimum_cmd_size sysctl variables/loader
tunables. Remove references to /dev/r???, they aren't used
any longer.
cd.9: Update the cd(9) man page to describe the CD_Q_10_BYTE_ONLY
quirk.
taskqueue.9: Update the taskqueue(9) man page to describe the new thread
task queue, and the taskqueue_swi_giant queue.
MFC after: 3 days
2003-09-03 04:46:28 +00:00
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
|
2013-05-02 14:14:57 +00:00
|
|
|
/* Ensure re-probe doesn't see old delete. */
|
|
|
|
softc->delete_available = 0;
|
|
|
|
if (lbp) {
|
|
|
|
/*
|
|
|
|
* Based on older SBC-3 spec revisions
|
|
|
|
* any of the UNMAP methods "may" be
|
|
|
|
* available via LBP given this flag so
|
|
|
|
* we flag all of them as availble and
|
|
|
|
* then remove those which further
|
|
|
|
* probes confirm aren't available
|
|
|
|
* later.
|
|
|
|
*
|
|
|
|
* We could also check readcap(16) p_type
|
|
|
|
* flag to exclude one or more invalid
|
|
|
|
* write same (X) types here
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS16, 1);
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS10, 1);
|
|
|
|
dadeleteflag(softc, DA_DELETE_ZERO, 1);
|
|
|
|
dadeleteflag(softc, DA_DELETE_UNMAP, 1);
|
|
|
|
|
|
|
|
xpt_release_ccb(done_ccb);
|
|
|
|
softc->state = DA_STATE_PROBE_LBP;
|
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
2013-04-26 16:31:03 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case DA_CCB_PROBE_LBP:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_logical_block_prov *lbp;
|
|
|
|
|
|
|
|
lbp = (struct scsi_vpd_logical_block_prov *)csio->data_ptr;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
|
|
|
/*
|
|
|
|
* T10/1799-D Revision 31 states at least one of these
|
|
|
|
* must be supported but we don't currently enforce this.
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS16,
|
|
|
|
(lbp->flags & SVPD_LBP_WS16));
|
|
|
|
dadeleteflag(softc, DA_DELETE_WS10,
|
|
|
|
(lbp->flags & SVPD_LBP_WS10));
|
|
|
|
dadeleteflag(softc, DA_DELETE_ZERO,
|
|
|
|
(lbp->flags & SVPD_LBP_WS10));
|
|
|
|
dadeleteflag(softc, DA_DELETE_UNMAP,
|
|
|
|
(lbp->flags & SVPD_LBP_UNMAP));
|
|
|
|
|
|
|
|
if (lbp->flags & SVPD_LBP_UNMAP) {
|
|
|
|
free(lbp, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BLK_LIMITS;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Failure indicates we don't support any SBC-3
|
|
|
|
* delete methods with UNMAP
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(lbp, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case DA_CCB_PROBE_BLK_LIMITS:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_limits *block_limits;
|
|
|
|
|
|
|
|
block_limits = (struct scsi_vpd_block_limits *)csio->data_ptr;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
|
|
|
uint32_t max_unmap_lba_cnt = scsi_4btoul(
|
|
|
|
block_limits->max_unmap_lba_cnt);
|
|
|
|
uint32_t max_unmap_blk_cnt = scsi_4btoul(
|
|
|
|
block_limits->max_unmap_blk_cnt);
|
|
|
|
uint64_t ws_max_blks = scsi_8btou64(
|
|
|
|
block_limits->max_write_same_length);
|
|
|
|
/*
|
|
|
|
* We should already support UNMAP but we check lba
|
|
|
|
* and block count to be sure
|
|
|
|
*/
|
|
|
|
if (max_unmap_lba_cnt != 0x00L &&
|
|
|
|
max_unmap_blk_cnt != 0x00L) {
|
|
|
|
softc->unmap_max_lba = max_unmap_lba_cnt;
|
|
|
|
softc->unmap_max_ranges = min(max_unmap_blk_cnt,
|
|
|
|
UNMAP_MAX_RANGES);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Unexpected UNMAP limits which means the
|
|
|
|
* device doesn't actually support UNMAP
|
|
|
|
*/
|
|
|
|
dadeleteflag(softc, DA_DELETE_UNMAP, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ws_max_blks != 0x00L)
|
|
|
|
softc->ws_max_blks = ws_max_blks;
|
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Failure here doesn't mean UNMAP is not
|
|
|
|
* supported as this is an optional page.
|
|
|
|
*/
|
|
|
|
softc->unmap_max_lba = 1;
|
|
|
|
softc->unmap_max_ranges = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(block_limits, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_BDC;
|
2013-04-26 16:17:04 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
case DA_CCB_PROBE_BDC:
|
|
|
|
{
|
|
|
|
struct scsi_vpd_block_characteristics *bdc;
|
|
|
|
|
|
|
|
bdc = (struct scsi_vpd_block_characteristics *)csio->data_ptr;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
2013-04-28 21:14:23 +00:00
|
|
|
/*
|
|
|
|
* Disable queue sorting for non-rotational media
|
|
|
|
* by default.
|
|
|
|
*/
|
2013-04-26 16:31:03 +00:00
|
|
|
if (scsi_2btoul(bdc->medium_rotation_rate) ==
|
|
|
|
SVPD_BDC_RATE_NONE_ROTATING)
|
|
|
|
softc->sort_io_queue = 0;
|
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(bdc, M_SCSIDA);
|
|
|
|
xpt_release_ccb(done_ccb);
|
2013-05-02 14:14:57 +00:00
|
|
|
softc->state = DA_STATE_PROBE_ATA;
|
2013-04-26 16:31:03 +00:00
|
|
|
xpt_schedule(periph, priority);
|
|
|
|
return;
|
|
|
|
}
|
2013-04-26 16:17:04 +00:00
|
|
|
case DA_CCB_PROBE_ATA:
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct ata_params *ata_params;
|
|
|
|
int16_t *ptr;
|
|
|
|
|
|
|
|
ata_params = (struct ata_params *)csio->data_ptr;
|
|
|
|
ptr = (uint16_t *)ata_params;
|
|
|
|
|
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
|
|
|
|
for (i = 0; i < sizeof(*ata_params) / 2; i++)
|
|
|
|
ptr[i] = le16toh(ptr[i]);
|
|
|
|
if (ata_params->support_dsm & ATA_SUPPORT_DSM_TRIM) {
|
|
|
|
dadeleteflag(softc, DA_DELETE_ATA_TRIM, 1);
|
|
|
|
if (ata_params->max_dsm_blocks != 0)
|
|
|
|
softc->trim_max_ranges = min(
|
|
|
|
softc->trim_max_ranges,
|
|
|
|
ata_params->max_dsm_blocks *
|
|
|
|
ATA_DSM_BLK_RANGES);
|
|
|
|
}
|
2013-04-26 16:31:03 +00:00
|
|
|
/*
|
2013-04-28 21:14:23 +00:00
|
|
|
* Disable queue sorting for non-rotational media
|
|
|
|
* by default.
|
2013-04-26 16:31:03 +00:00
|
|
|
*/
|
|
|
|
if (ata_params->media_rotation_rate == 1)
|
|
|
|
softc->sort_io_queue = 0;
|
2013-04-26 16:17:04 +00:00
|
|
|
} else {
|
|
|
|
int error;
|
|
|
|
error = daerror(done_ccb, CAM_RETRY_SELTO,
|
2013-05-02 14:37:23 +00:00
|
|
|
SF_RETRY_UA|SF_NO_PRINT);
|
2013-04-26 16:17:04 +00:00
|
|
|
if (error == ERESTART)
|
|
|
|
return;
|
|
|
|
else if (error != 0) {
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
|
|
|
/* Don't wedge this device's queue */
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(ata_params, M_SCSIDA);
|
2013-05-02 14:37:23 +00:00
|
|
|
daprobedone(periph, done_ccb);
|
1999-01-07 20:19:09 +00:00
|
|
|
return;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
case DA_CCB_WAITING:
|
|
|
|
{
|
|
|
|
/* Caller will release the CCB */
|
|
|
|
wakeup(&done_ccb->ccb_h.cbfcnp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case DA_CCB_DUMP:
|
|
|
|
/* No-op. We're polling */
|
|
|
|
return;
|
2012-07-29 11:51:48 +00:00
|
|
|
case DA_CCB_TUR:
|
|
|
|
{
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
|
|
|
|
|
|
if (daerror(done_ccb, CAM_RETRY_SELTO,
|
|
|
|
SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) ==
|
|
|
|
ERESTART)
|
|
|
|
return;
|
|
|
|
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(done_ccb->ccb_h.path,
|
|
|
|
/*relsim_flags*/0,
|
|
|
|
/*reduction*/0,
|
|
|
|
/*timeout*/0,
|
|
|
|
/*getcount_only*/0);
|
|
|
|
}
|
|
|
|
xpt_release_ccb(done_ccb);
|
|
|
|
cam_periph_release_locked(periph);
|
|
|
|
return;
|
|
|
|
}
|
1999-01-07 20:19:09 +00:00
|
|
|
default:
|
|
|
|
break;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
1999-01-07 20:19:09 +00:00
|
|
|
xpt_release_ccb(done_ccb);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
2012-04-12 12:58:14 +00:00
|
|
|
static void
|
|
|
|
dareprobe(struct cam_periph *periph)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
cam_status status;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
/* Probe in progress; don't interfere. */
|
2013-05-02 14:19:42 +00:00
|
|
|
if (softc->state != DA_STATE_NORMAL)
|
2012-04-12 12:58:14 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
status = cam_periph_acquire(periph);
|
|
|
|
KASSERT(status == CAM_REQ_CMP,
|
|
|
|
("dareprobe: cam_periph_acquire failed"));
|
|
|
|
|
|
|
|
if (softc->flags & DA_FLAG_CAN_RC16)
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC16;
|
2012-04-12 12:58:14 +00:00
|
|
|
else
|
2013-04-26 16:17:04 +00:00
|
|
|
softc->state = DA_STATE_PROBE_RC;
|
2012-04-12 12:58:14 +00:00
|
|
|
|
|
|
|
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static int
|
|
|
|
daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct cam_periph *periph;
|
2012-06-23 12:32:53 +00:00
|
|
|
int error, error_code, sense_key, asc, ascq;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
periph = xpt_path_periph(ccb->ccb_h.path);
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
2002-03-23 18:18:02 +00:00
|
|
|
/*
|
|
|
|
* Automatically detect devices that do not support
|
|
|
|
* READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
|
|
|
|
*/
|
|
|
|
error = 0;
|
Fix ATAPI/USB/Firewire CDROM drive handling in cd(4) and hopefully fix
a number of related problems along the way.
- Automatically detect CDROM drives that can't handle 6 byte mode
sense and mode select, and adjust our command size accordingly.
We have to handle this in the cd(4) driver (where the buffers are
allocated), since the parameter list length is different for the
6 and 10 byte mode sense commands.
- Remove MODE_SENSE and MODE_SELECT translation removed in ATAPICAM
and in the umass(4) driver, since there's no way for that to work
properly.
- Add a quirk entry for CDROM drives that just hang when they get a 6
byte mode sense or mode select. The reason for the quirk must be
documented in a PR, and all quirks must be approved by
ken@FreeBSD.org. This is to make sure that we fully understand why
each quirk is needed. Once the CAM_NEW_TRAN_CODE is finished, we
should be able to remove any such quirks, since we'll know what
protocol the drive speaks (SCSI, ATAPI, etc.) and therefore whether
we should use 6 or 10 byte mode sense/select commands.
- Change the way the da(4) handles the no_6_byte sysctl. There is
now a per-drive sysctl to set the minimum command size for that
particular disk. (Since you could have multiple disks with
multiple requirements in one system.)
- Loader tunable support for all the sysctls in the da(4) and cd(4)
drivers.
- Add a CDIOCCLOSE ioctl for cd(4) (bde pointed this out a long
time ago).
- Add a media validation routine (cdcheckmedia()) to the cd(4)
driver, to fix some problems bde pointed out a long time ago. We
now allow open() to succeed no matter what, but if we don't detect
valid media, the user can only issue CDIOCCLOSE or CDIOCEJECT
ioctls.
- The media validation routine also reads the table of contents off
the drive. We use the table of contents to implement the
CDIOCPLAYTRACKS ioctl using the PLAY AUDIO MSF command. The
PLAY AUDIO TRACK INDEX command that we previously used was
deprecated after SCSI-2. It works in every SCSI CDROM I've tried,
but doesn't seem to work on ATAPI CDROM drives. We still use the
play audio track index command if we don't have a valid TOC, but
I suppose it'll fail anyway in that case.
- Add _len() versions of scsi_mode_sense() and scsi_mode_select() so
that we can specify the minimum command length.
- Fix a couple of formatting problems in the sense printing code.
MFC after: 4 weeks
2003-02-21 06:19:38 +00:00
|
|
|
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
|
|
|
|
error = cmd6workaround(ccb);
|
2012-06-23 12:32:53 +00:00
|
|
|
} else if (scsi_extract_sense_ccb(ccb,
|
|
|
|
&error_code, &sense_key, &asc, &ascq)) {
|
2002-03-23 18:18:02 +00:00
|
|
|
if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
|
|
|
|
error = cmd6workaround(ccb);
|
2012-04-12 12:58:14 +00:00
|
|
|
/*
|
|
|
|
* If the target replied with CAPACITY DATA HAS CHANGED UA,
|
|
|
|
* query the capacity and notify upper layers.
|
|
|
|
*/
|
|
|
|
else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
|
|
|
|
asc == 0x2A && ascq == 0x09) {
|
|
|
|
xpt_print(periph->path, "capacity data has changed\n");
|
|
|
|
dareprobe(periph);
|
|
|
|
sense_flags |= SF_NO_PRINT;
|
2012-07-29 11:51:48 +00:00
|
|
|
} else if (sense_key == SSD_KEY_UNIT_ATTENTION &&
|
|
|
|
asc == 0x28 && ascq == 0x00)
|
|
|
|
disk_media_changed(softc->disk, M_NOWAIT);
|
|
|
|
else if (sense_key == SSD_KEY_NOT_READY &&
|
2013-05-03 11:53:06 +00:00
|
|
|
asc == 0x3a && (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
|
|
|
|
softc->flags |= DA_FLAG_PACK_INVALID;
|
2012-07-29 11:51:48 +00:00
|
|
|
disk_media_gone(softc->disk, M_NOWAIT);
|
2012-04-12 12:58:14 +00:00
|
|
|
}
|
2002-03-23 18:18:02 +00:00
|
|
|
}
|
|
|
|
if (error == ERESTART)
|
2002-08-16 22:05:19 +00:00
|
|
|
return (ERESTART);
|
2002-03-23 18:18:02 +00:00
|
|
|
|
1998-09-20 07:17:11 +00:00
|
|
|
/*
|
|
|
|
* XXX
|
|
|
|
* Until we have a better way of doing pack validation,
|
|
|
|
* don't treat UAs as errors.
|
|
|
|
*/
|
|
|
|
sense_flags |= SF_RETRY_UA;
|
1998-09-15 06:36:34 +00:00
|
|
|
return(cam_periph_error(ccb, cam_flags, sense_flags,
|
|
|
|
&softc->saved_ccb));
|
|
|
|
}
|
|
|
|
|
2012-07-29 11:51:48 +00:00
|
|
|
static void
|
|
|
|
damediapoll(void *arg)
|
|
|
|
{
|
|
|
|
struct cam_periph *periph = arg;
|
|
|
|
struct da_softc *softc = periph->softc;
|
|
|
|
|
2013-01-11 16:10:11 +00:00
|
|
|
if (!softc->tur && softc->outstanding_cmds == 0) {
|
2012-07-29 11:51:48 +00:00
|
|
|
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
|
|
|
softc->tur = 1;
|
|
|
|
daschedule(periph);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Queue us up again */
|
|
|
|
if (da_poll_period != 0)
|
|
|
|
callout_schedule(&softc->mediapoll_c, da_poll_period * hz);
|
|
|
|
}
|
|
|
|
|
1998-09-15 06:36:34 +00:00
|
|
|
static void
|
|
|
|
daprevent(struct cam_periph *periph, int action)
|
|
|
|
{
|
|
|
|
struct da_softc *softc;
|
|
|
|
union ccb *ccb;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
if (((action == PR_ALLOW)
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
|
|
|
|
|| ((action == PR_PREVENT)
|
|
|
|
&& (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-23 08:27:55 +00:00
|
|
|
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
scsi_prevent(&ccb->csio,
|
|
|
|
/*retries*/1,
|
|
|
|
/*cbcfp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
action,
|
|
|
|
SSD_FULL_SIZE,
|
|
|
|
5000);
|
|
|
|
|
2012-06-05 10:08:22 +00:00
|
|
|
error = cam_periph_runccb(ccb, daerror, CAM_RETRY_SELTO,
|
2013-05-12 09:33:33 +00:00
|
|
|
SF_RETRY_UA | SF_NO_PRINT, softc->disk->d_devstat);
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
if (error == 0) {
|
|
|
|
if (action == PR_ALLOW)
|
|
|
|
softc->flags &= ~DA_FLAG_PACK_LOCKED;
|
|
|
|
else
|
|
|
|
softc->flags |= DA_FLAG_PACK_LOCKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
xpt_release_ccb(ccb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-12-23 00:10:17 +00:00
|
|
|
dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector,
|
2012-01-26 18:09:28 +00:00
|
|
|
struct scsi_read_capacity_data_long *rcaplong, size_t rcap_len)
|
1998-09-15 06:36:34 +00:00
|
|
|
{
|
|
|
|
struct ccb_calc_geometry ccg;
|
|
|
|
struct da_softc *softc;
|
|
|
|
struct disk_params *dp;
|
2012-01-26 18:09:28 +00:00
|
|
|
u_int lbppbe, lalba;
|
2012-10-29 17:52:43 +00:00
|
|
|
int error;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
dp = &softc->params;
|
Add support to CAM for devices with more than 2^32 blocks. (2TB if you're
using 512 byte blocks).
cam_ccb.h: Bump up volume_size and cylinders in ccb_calc_geometry to
64 bits and 32 bits respectively, so we can hold larger
device sizes. cylinders would overflow at about 500GB.
Bump CAM_VERSION for this change. Note that this will
require a recompile of all applications that talk to the
pass(4) driver.
scsi_all.c: Add descriptions for READ/WRITE(16), update READ/WRITE(12)
descriptions, add descriptions for SERVICE ACTION IN/OUT.
Add a new function, scsi_read_capacity_16(), that issues
the read capacity service action. (Necessary for arrays
larger than 2^32 sectors.) Update scsi_read_write() to use
a 64 bit LBA and issue READ(16) or WRITE(16) if necessary.
NOTE the API change. This should be largely transparnet
to most userland applications at compile time, but will
break binary compatibility. The CAM_VERSION bump, above,
also serves the purpose of forcing a recompile for any
applications that talk to CAM.
scsi_all.h: Add 16 byte READ/WRITE structures, structures for 16 byte
READ CAPACITY/SERVICE ACTION IN. Add scsi_u64to8b() and
scsi_8btou64.
scsi_da.c: The da(4) driver probe now has two stages for devices
larger than 2TB. If a standard READ CAPACITY(10) returns
0xffffffff, we issue the 16 byte version of read capacity
to determine the true array capacity. We also do the same
thing in daopen() -- use the 16 byte read capacity if the
device is large enough.
The sysctl/loader code has also been updated to accept
16 bytes as a minimum command size.
2003-04-30 00:35:22 +00:00
|
|
|
dp->secsize = block_len;
|
|
|
|
dp->sectors = maxsector + 1;
|
2012-01-26 18:09:28 +00:00
|
|
|
if (rcaplong != NULL) {
|
|
|
|
lbppbe = rcaplong->prot_lbppbe & SRC16_LBPPBE;
|
|
|
|
lalba = scsi_2btoul(rcaplong->lalba_lbp);
|
|
|
|
lalba &= SRC16_LALBA_A;
|
|
|
|
} else {
|
|
|
|
lbppbe = 0;
|
|
|
|
lalba = 0;
|
|
|
|
}
|
|
|
|
|
2011-12-23 00:10:17 +00:00
|
|
|
if (lbppbe > 0) {
|
|
|
|
dp->stripesize = block_len << lbppbe;
|
2011-12-23 20:59:13 +00:00
|
|
|
dp->stripeoffset = (dp->stripesize - block_len * lalba) %
|
|
|
|
dp->stripesize;
|
2011-12-23 00:10:17 +00:00
|
|
|
} else if (softc->quirks & DA_Q_4K) {
|
|
|
|
dp->stripesize = 4096;
|
|
|
|
dp->stripeoffset = 0;
|
|
|
|
} else {
|
|
|
|
dp->stripesize = 0;
|
|
|
|
dp->stripeoffset = 0;
|
|
|
|
}
|
1998-09-15 06:36:34 +00:00
|
|
|
/*
|
|
|
|
* Have the controller provide us with a geometry
|
|
|
|
* for this disk. The only time the geometry
|
|
|
|
* matters is when we boot and the controller
|
|
|
|
* is the only one knowledgeable enough to come
|
|
|
|
* up with something that will make this a bootable
|
|
|
|
* device.
|
|
|
|
*/
|
2009-10-23 08:27:55 +00:00
|
|
|
xpt_setup_ccb(&ccg.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
1998-09-15 06:36:34 +00:00
|
|
|
ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
|
|
|
|
ccg.block_size = dp->secsize;
|
|
|
|
ccg.volume_size = dp->sectors;
|
|
|
|
ccg.heads = 0;
|
|
|
|
ccg.secs_per_track = 0;
|
|
|
|
ccg.cylinders = 0;
|
|
|
|
xpt_action((union ccb*)&ccg);
|
2006-04-18 22:01:59 +00:00
|
|
|
if ((ccg.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
|
|
/*
|
|
|
|
* We don't know what went wrong here- but just pick
|
|
|
|
* a geometry so we don't have nasty things like divide
|
|
|
|
* by zero.
|
|
|
|
*/
|
|
|
|
dp->heads = 255;
|
|
|
|
dp->secs_per_track = 255;
|
|
|
|
dp->cylinders = dp->sectors / (255 * 255);
|
|
|
|
if (dp->cylinders == 0) {
|
|
|
|
dp->cylinders = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dp->heads = ccg.heads;
|
|
|
|
dp->secs_per_track = ccg.secs_per_track;
|
|
|
|
dp->cylinders = ccg.cylinders;
|
|
|
|
}
|
2012-01-26 18:09:28 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the user supplied a read capacity buffer, and if it is
|
|
|
|
* different than the previous buffer, update the data in the EDT.
|
|
|
|
* If it's the same, we don't bother. This avoids sending an
|
|
|
|
* update every time someone opens this device.
|
|
|
|
*/
|
|
|
|
if ((rcaplong != NULL)
|
|
|
|
&& (bcmp(rcaplong, &softc->rcaplong,
|
|
|
|
min(sizeof(softc->rcaplong), rcap_len)) != 0)) {
|
|
|
|
struct ccb_dev_advinfo cdai;
|
|
|
|
|
|
|
|
xpt_setup_ccb(&cdai.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
|
|
|
cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
|
|
|
|
cdai.buftype = CDAI_TYPE_RCAPLONG;
|
|
|
|
cdai.flags |= CDAI_FLAG_STORE;
|
|
|
|
cdai.bufsiz = rcap_len;
|
|
|
|
cdai.buf = (uint8_t *)rcaplong;
|
|
|
|
xpt_action((union ccb *)&cdai);
|
|
|
|
if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
|
|
|
|
cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
|
|
|
|
if (cdai.ccb_h.status != CAM_REQ_CMP) {
|
|
|
|
xpt_print(periph->path, "%s: failed to set read "
|
|
|
|
"capacity advinfo\n", __func__);
|
|
|
|
/* Use cam_error_print() to decode the status */
|
|
|
|
cam_error_print((union ccb *)&cdai, CAM_ESF_CAM_STATUS,
|
|
|
|
CAM_EPF_ALL);
|
|
|
|
} else {
|
|
|
|
bcopy(rcaplong, &softc->rcaplong,
|
|
|
|
min(sizeof(softc->rcaplong), rcap_len));
|
|
|
|
}
|
|
|
|
}
|
2012-04-12 12:58:14 +00:00
|
|
|
|
|
|
|
softc->disk->d_sectorsize = softc->params.secsize;
|
|
|
|
softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
|
|
|
|
softc->disk->d_stripesize = softc->params.stripesize;
|
|
|
|
softc->disk->d_stripeoffset = softc->params.stripeoffset;
|
|
|
|
/* XXX: these are not actually "firmware" values, so they may be wrong */
|
|
|
|
softc->disk->d_fwsectors = softc->params.secs_per_track;
|
|
|
|
softc->disk->d_fwheads = softc->params.heads;
|
|
|
|
softc->disk->d_devstat->block_size = softc->params.secsize;
|
|
|
|
softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
|
2012-07-07 22:19:51 +00:00
|
|
|
|
2012-10-29 17:52:43 +00:00
|
|
|
error = disk_resize(softc->disk, M_NOWAIT);
|
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "disk_resize(9) failed, error = %d\n", error);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dasendorderedtag(void *arg)
|
|
|
|
{
|
2007-04-15 08:49:19 +00:00
|
|
|
struct da_softc *softc = arg;
|
1998-09-15 06:36:34 +00:00
|
|
|
|
2007-04-15 08:49:19 +00:00
|
|
|
if (da_send_ordered) {
|
|
|
|
if ((softc->ordered_tag_count == 0)
|
|
|
|
&& ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
|
|
|
|
softc->flags |= DA_FLAG_NEED_OTAG;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
if (softc->outstanding_cmds > 0)
|
|
|
|
softc->flags &= ~DA_FLAG_WENT_IDLE;
|
|
|
|
|
|
|
|
softc->ordered_tag_count = 0;
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
2007-04-15 08:49:19 +00:00
|
|
|
/* Queue us up again */
|
|
|
|
callout_reset(&softc->sendordered_c,
|
2012-02-02 19:02:15 +00:00
|
|
|
(da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
|
2007-04-15 08:49:19 +00:00
|
|
|
dasendorderedtag, softc);
|
1998-09-15 06:36:34 +00:00
|
|
|
}
|
1998-10-08 05:46:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step through all DA peripheral drivers, and if the device is still open,
|
|
|
|
* sync the disk cache to physical media.
|
|
|
|
*/
|
|
|
|
static void
|
1999-08-21 06:24:40 +00:00
|
|
|
dashutdown(void * arg, int howto)
|
1998-10-08 05:46:38 +00:00
|
|
|
{
|
|
|
|
struct cam_periph *periph;
|
|
|
|
struct da_softc *softc;
|
2013-03-29 08:33:18 +00:00
|
|
|
union ccb *ccb;
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
int error;
|
1998-10-08 05:46:38 +00:00
|
|
|
|
2013-03-29 07:50:47 +00:00
|
|
|
CAM_PERIPH_FOREACH(periph, &dadriver) {
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_lock(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
softc = (struct da_softc *)periph->softc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We only sync the cache if the drive is still open, and
|
|
|
|
* if the drive is capable of it..
|
|
|
|
*/
|
|
|
|
if (((softc->flags & DA_FLAG_OPEN) == 0)
|
2007-04-19 22:18:15 +00:00
|
|
|
|| (softc->quirks & DA_Q_NO_SYNC_CACHE)) {
|
|
|
|
cam_periph_unlock(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
continue;
|
2007-04-19 22:18:15 +00:00
|
|
|
}
|
1998-10-08 05:46:38 +00:00
|
|
|
|
2013-03-29 08:33:18 +00:00
|
|
|
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
|
|
|
|
scsi_synchronize_cache(&ccb->csio,
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
/*retries*/0,
|
1998-10-08 05:46:38 +00:00
|
|
|
/*cbfcnp*/dadone,
|
|
|
|
MSG_SIMPLE_Q_TAG,
|
|
|
|
/*begin_lba*/0, /* whole disk */
|
|
|
|
/*lb_count*/0,
|
|
|
|
SSD_FULL_SIZE,
|
2001-11-17 18:26:00 +00:00
|
|
|
60 * 60 * 1000);
|
1998-10-08 05:46:38 +00:00
|
|
|
|
2013-03-29 08:33:18 +00:00
|
|
|
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
|
|
|
|
/*sense_flags*/ SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR,
|
|
|
|
softc->disk->d_devstat);
|
One more major cam_periph_error() rewrite to improve error handling and
reporting. It includes:
- removing of error messages controlled by bootverbose, replacing them
with more universal and informative debugging on CAM_DEBUG_INFO level,
that is now built into the kernel by default;
- more close following to the arguments submitted by caller, such as
SF_PRINT_ALWAYS, SF_QUIET_IR and SF_NO_PRINT; consumer knows better which
errors are usual/expected at this point and which are really informative;
- adding two new flags SF_NO_RECOVERY and SF_NO_RETRY to allow caller
specify how much assistance it needs at this point; previously consumers
controlled that by not calling cam_periph_error() at all, but that made
behavior inconsistent and debugging complicated;
- tuning debug messages and taken actions order to make debugging output
more readable and cause-effect relationships visible;
- making camperiphdone() (common device recovery completion handler) to
also use cam_periph_error() in most cases, instead of own dumb code;
- removing manual sense fetching code from cam_periph_error(); I was told
by number of people that it is SIM obligation to fetch sense data, so this
code is useless and only significantly complicates recovery logic;
- making ada, da and pass driver to use cam_periph_error() with new limited
recovery options to handle error recovery and debugging in common way;
as one of results, CAM_REQUEUE_REQ and other retrying statuses are now
working fine with pass driver, that caused many problems before.
- reverting r186891 by raj@ to avoid burning few seconds in tight DELAY()
loops on device probe, while device simply loads media; I think that problem
may already be fixed in other way, and even if it is not, solution must be
different.
Sponsored by: iXsystems, Inc.
MFC after: 2 weeks
2012-06-09 13:07:44 +00:00
|
|
|
if (error != 0)
|
|
|
|
xpt_print(periph->path, "Synchronize cache failed\n");
|
2013-04-03 11:30:18 +00:00
|
|
|
xpt_release_ccb(ccb);
|
2007-04-18 05:14:16 +00:00
|
|
|
cam_periph_unlock(periph);
|
1998-10-08 05:46:38 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-21 23:57:52 +00:00
|
|
|
|
|
|
|
#else /* !_KERNEL */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX This is only left out of the kernel build to silence warnings. If,
|
|
|
|
* for some reason this function is used in the kernel, the ifdefs should
|
|
|
|
* be moved so it is included both in the kernel and userland.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
|
|
|
|
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
|
|
|
u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
|
|
|
|
u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
|
|
|
|
u_int32_t timeout)
|
|
|
|
{
|
|
|
|
struct scsi_format_unit *scsi_cmd;
|
|
|
|
|
|
|
|
scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
|
|
|
|
scsi_cmd->opcode = FORMAT_UNIT;
|
|
|
|
scsi_cmd->byte2 = byte2;
|
|
|
|
scsi_ulto2b(ileave, scsi_cmd->interleave);
|
|
|
|
|
|
|
|
cam_fill_csio(csio,
|
|
|
|
retries,
|
|
|
|
cbfcnp,
|
|
|
|
/*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
|
|
|
|
tag_action,
|
|
|
|
data_ptr,
|
|
|
|
dxfer_len,
|
|
|
|
sense_len,
|
|
|
|
sizeof(*scsi_cmd),
|
|
|
|
timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _KERNEL */
|