summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-09-30 13:31:37 +0000
committermav <mav@FreeBSD.org>2015-09-30 13:31:37 +0000
commitefed61f85c8d42437b2f71f0e78164039dbf876b (patch)
treef93ec68cb45de7a3c0f34e6d6eb086a29122c036
parent0ed33a9921d09f4a4c791d98ffe797a71936e42a (diff)
downloadFreeBSD-src-efed61f85c8d42437b2f71f0e78164039dbf876b.zip
FreeBSD-src-efed61f85c8d42437b2f71f0e78164039dbf876b.tar.gz
Make pass, sg and targ drivers respect HBA's maxio.
Previous limitation of 64K (DFLTPHYS) is quite annoying.
-rw-r--r--sys/cam/cam_compat.c2
-rw-r--r--sys/cam/cam_periph.c9
-rw-r--r--sys/cam/cam_periph.h3
-rw-r--r--sys/cam/cam_xpt.c2
-rw-r--r--sys/cam/scsi/scsi_pass.c10
-rw-r--r--sys/cam/scsi/scsi_sg.c10
-rw-r--r--sys/cam/scsi/scsi_target.c9
7 files changed, 36 insertions, 9 deletions
diff --git a/sys/cam/cam_compat.c b/sys/cam/cam_compat.c
index bcce814..b8e57bb 100644
--- a/sys/cam/cam_compat.c
+++ b/sys/cam/cam_compat.c
@@ -300,7 +300,7 @@ cam_compat_translate_dev_match_0x18(union ccb *ccb)
/* Remap the CCB into kernel address space */
bzero(&mapinfo, sizeof(mapinfo));
- cam_periph_mapmem(ccb, &mapinfo);
+ cam_periph_mapmem(ccb, &mapinfo, MAXPHYS);
dm = ccb->cdm.matches;
/* Translate in-place: old fields are smaller */
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 956e5d0..91cb45d 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -716,16 +716,19 @@ camperiphfree(struct cam_periph *periph)
* buffers to map stuff in and out, we're limited to the buffer size.
*/
int
-cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
+cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo,
+ u_int maxmap)
{
int numbufs, i, j;
int flags[CAM_PERIPH_MAXMAPS];
u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
u_int32_t lengths[CAM_PERIPH_MAXMAPS];
u_int32_t dirs[CAM_PERIPH_MAXMAPS];
- /* Some controllers may not be able to handle more data. */
- size_t maxmap = DFLTPHYS;
+ if (maxmap == 0)
+ maxmap = DFLTPHYS; /* traditional default */
+ else if (maxmap > MAXPHYS)
+ maxmap = MAXPHYS; /* for safety */
switch(ccb->ccb_h.func_code) {
case XPT_DEV_MATCH:
if (ccb->cdm.match_buf_len == 0) {
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
index ebcf1a4..e28d5b1 100644
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -160,7 +160,8 @@ int cam_periph_hold(struct cam_periph *periph, int priority);
void cam_periph_unhold(struct cam_periph *periph);
void cam_periph_invalidate(struct cam_periph *periph);
int cam_periph_mapmem(union ccb *ccb,
- struct cam_periph_map_info *mapinfo);
+ struct cam_periph_map_info *mapinfo,
+ u_int maxmap);
void cam_periph_unmapmem(union ccb *ccb,
struct cam_periph_map_info *mapinfo);
union ccb *cam_periph_getccb(struct cam_periph *periph,
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index ad55373..4ce48a3 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -536,7 +536,7 @@ xptdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *
* Map the pattern and match buffers into kernel
* virtual address space.
*/
- error = cam_periph_mapmem(inccb, &mapinfo);
+ error = cam_periph_mapmem(inccb, &mapinfo, MAXPHYS);
if (error) {
inccb->ccb_h.path = old_path;
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index 584b6b3..055291b 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -77,6 +77,7 @@ struct pass_softc {
u_int8_t pd_type;
union ccb saved_ccb;
int open_count;
+ u_int maxio;
struct devstat *device_stats;
struct cdev *dev;
struct cdev *alias_dev;
@@ -366,6 +367,13 @@ passregister(struct cam_periph *periph, void *arg)
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
+ if (cpi.maxio == 0)
+ softc->maxio = DFLTPHYS; /* traditional default */
+ else if (cpi.maxio > MAXPHYS)
+ softc->maxio = MAXPHYS; /* for safety */
+ else
+ softc->maxio = cpi.maxio; /* real value */
+
/*
* We pass in 0 for a blocksize, since we don't
* know what the blocksize of this device is, if
@@ -657,7 +665,7 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
* Dropping it here is reasonably safe.
*/
cam_periph_unlock(periph);
- error = cam_periph_mapmem(ccb, &mapinfo);
+ error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio);
cam_periph_lock(periph);
/*
diff --git a/sys/cam/scsi/scsi_sg.c b/sys/cam/scsi/scsi_sg.c
index 3e80ac3..3e13003 100644
--- a/sys/cam/scsi/scsi_sg.c
+++ b/sys/cam/scsi/scsi_sg.c
@@ -99,6 +99,7 @@ struct sg_softc {
sg_state state;
sg_flags flags;
int open_count;
+ u_int maxio;
struct devstat *device_stats;
TAILQ_HEAD(, sg_rdwr) rdwr_done;
struct cdev *dev;
@@ -325,6 +326,13 @@ sgregister(struct cam_periph *periph, void *arg)
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
+ if (cpi.maxio == 0)
+ softc->maxio = DFLTPHYS; /* traditional default */
+ else if (cpi.maxio > MAXPHYS)
+ softc->maxio = MAXPHYS; /* for safety */
+ else
+ softc->maxio = cpi.maxio; /* real value */
+
/*
* We pass in 0 for all blocksize, since we don't know what the
* blocksize of the device is, if it even has a blocksize.
@@ -894,7 +902,7 @@ sgsendccb(struct cam_periph *periph, union ccb *ccb)
* need for additional checks.
*/
cam_periph_unlock(periph);
- error = cam_periph_mapmem(ccb, &mapinfo);
+ error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio);
cam_periph_lock(periph);
if (error)
return (error);
diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c
index 42dc152..f2504ab 100644
--- a/sys/cam/scsi/scsi_target.c
+++ b/sys/cam/scsi/scsi_target.c
@@ -94,6 +94,7 @@ struct targ_softc {
struct cam_periph *periph;
struct cam_path *path;
targ_state state;
+ u_int maxio;
struct selinfo read_select;
struct devstat device_stats;
};
@@ -403,6 +404,12 @@ targenable(struct targ_softc *softc, struct cam_path *path, int grp6_len,
status = CAM_FUNC_NOTAVAIL;
goto enable_fail;
}
+ if (cpi.maxio == 0)
+ softc->maxio = DFLTPHYS; /* traditional default */
+ else if (cpi.maxio > MAXPHYS)
+ softc->maxio = MAXPHYS; /* for safety */
+ else
+ softc->maxio = cpi.maxio; /* real value */
/* Destroy any periph on our path if it is disabled */
periph = cam_periph_find(path, "targ");
@@ -725,7 +732,7 @@ targsendccb(struct targ_softc *softc, union ccb *ccb,
if ((ccb_h->func_code == XPT_CONT_TARGET_IO) ||
(ccb_h->func_code == XPT_DEV_MATCH)) {
- error = cam_periph_mapmem(ccb, mapinfo);
+ error = cam_periph_mapmem(ccb, mapinfo, softc->maxio);
/*
* cam_periph_mapmem returned an error, we can't continue.
OpenPOWER on IntegriCloud