summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-06-01 09:32:37 +0000
committermav <mav@FreeBSD.org>2012-06-01 09:32:37 +0000
commit8e77e366f62cd5e13d4f09087f8967e02277b5a5 (patch)
treece4798316dd5c4bfd635571984726eed80ad0d09
parent99a3cbfc7ca2a01c0ced609cadf5adda3423dcb1 (diff)
downloadFreeBSD-src-8e77e366f62cd5e13d4f09087f8967e02277b5a5.zip
FreeBSD-src-8e77e366f62cd5e13d4f09087f8967e02277b5a5.tar.gz
Use AC_GETDEV_CHANGED async to notify ada driver about DMA and NCQ status
change. Now that allows switching between PIO and DMA modes on the fly.
-rw-r--r--sys/cam/ata/ata_da.c39
-rw-r--r--sys/cam/ata/ata_xpt.c2
-rw-r--r--sys/cam/cam_xpt.c2
3 files changed, 37 insertions, 6 deletions
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 9f892a5..87f8d4a 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -742,6 +742,7 @@ static void
adaasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg)
{
+ struct ccb_getdev cgd;
struct cam_periph *periph;
struct ada_softc *softc;
@@ -776,6 +777,32 @@ adaasync(void *callback_arg, u_int32_t code,
"due to status 0x%x\n", status);
break;
}
+ case AC_GETDEV_CHANGED:
+ {
+ softc = (struct ada_softc *)periph->softc;
+ xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
+
+ if ((cgd.ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
+ (cgd.inq_flags & SID_DMA))
+ softc->flags |= ADA_FLAG_CAN_DMA;
+ else
+ softc->flags &= ~ADA_FLAG_CAN_DMA;
+ if ((cgd.ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
+ (cgd.inq_flags & SID_DMA) && (cgd.inq_flags & SID_CmdQue))
+ softc->flags |= ADA_FLAG_CAN_NCQ;
+ else
+ softc->flags &= ~ADA_FLAG_CAN_NCQ;
+ if ((cgd.ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) &&
+ (cgd.inq_flags & SID_DMA))
+ softc->flags |= ADA_FLAG_CAN_TRIM;
+ else
+ softc->flags &= ~ADA_FLAG_CAN_TRIM;
+
+ cam_periph_async(periph, code, path, arg);
+ break;
+ }
case AC_ADVINFO_CHANGED:
{
uintptr_t buftype;
@@ -793,8 +820,6 @@ adaasync(void *callback_arg, u_int32_t code,
case AC_SENT_BDR:
case AC_BUS_RESET:
{
- struct ccb_getdev cgd;
-
softc = (struct ada_softc *)periph->softc;
cam_periph_async(periph, code, path, arg);
if (softc->state != ADA_STATE_NORMAL)
@@ -933,7 +958,7 @@ adaregister(struct cam_periph *periph, void *arg)
bioq_init(&softc->bio_queue);
bioq_init(&softc->trim_queue);
- if (cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA &&
+ if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
(cgd->inq_flags & SID_DMA))
softc->flags |= ADA_FLAG_CAN_DMA;
if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
@@ -942,10 +967,11 @@ adaregister(struct cam_periph *periph, void *arg)
softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT)
softc->flags |= ADA_FLAG_CAN_POWERMGT;
- if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
+ if ((cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
(cgd->inq_flags & SID_DMA) && (cgd->inq_flags & SID_CmdQue))
softc->flags |= ADA_FLAG_CAN_NCQ;
- if (cgd->ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) {
+ if ((cgd->ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) &&
+ (cgd->inq_flags & SID_DMA)) {
softc->flags |= ADA_FLAG_CAN_TRIM;
softc->trim_max_ranges = TRIM_MAX_RANGES;
if (cgd->ident_data.max_dsm_blocks != 0) {
@@ -1103,7 +1129,8 @@ adaregister(struct cam_periph *periph, void *arg)
* not attach the device on failure.
*/
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
- AC_ADVINFO_CHANGED, adaasync, periph, periph->path);
+ AC_GETDEV_CHANGED | AC_ADVINFO_CHANGED,
+ adaasync, periph, periph->path);
/*
* Schedule a periodic event to occasionally send an
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 3a25b69..b1fd947 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -413,6 +413,7 @@ negotiate:
path->device->inq_flags &= ~SID_DMA;
else
path->device->inq_flags |= SID_DMA;
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
cam_fill_ataio(ataio,
1,
probedone,
@@ -1018,6 +1019,7 @@ noerror:
}
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
}
if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) {
path->device->mintags = 2;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 338fc6e..1126248 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -4715,6 +4715,7 @@ xpt_start_tags(struct cam_path *path)
newopenings = min(device->maxtags,
sim->max_tagged_dev_openings);
xpt_dev_ccbq_resize(path, newopenings);
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL);
crs.ccb_h.func_code = XPT_REL_SIMQ;
crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
@@ -4739,6 +4740,7 @@ xpt_stop_tags(struct cam_path *path)
xpt_freeze_devq(path, /*count*/1);
device->inq_flags &= ~SID_CmdQue;
xpt_dev_ccbq_resize(path, sim->max_dev_openings);
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL);
crs.ccb_h.func_code = XPT_REL_SIMQ;
crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
OpenPOWER on IntegriCloud