Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/ata/ata_da.c
Show First 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | #ifdef CAM_IO_STATS | ||||
u_int invalidations; | u_int invalidations; | ||||
#endif | #endif | ||||
#define ADA_ANNOUNCETMP_SZ 80 | #define ADA_ANNOUNCETMP_SZ 80 | ||||
char announce_temp[ADA_ANNOUNCETMP_SZ]; | char announce_temp[ADA_ANNOUNCETMP_SZ]; | ||||
#define ADA_ANNOUNCE_SZ 400 | #define ADA_ANNOUNCE_SZ 400 | ||||
char announce_buffer[ADA_ANNOUNCE_SZ]; | char announce_buffer[ADA_ANNOUNCE_SZ]; | ||||
}; | }; | ||||
static uma_zone_t ada_ccb_zone; | |||||
struct ada_quirk_entry { | struct ada_quirk_entry { | ||||
struct scsi_inquiry_pattern inq_pat; | struct scsi_inquiry_pattern inq_pat; | ||||
ada_quirks quirks; | ada_quirks quirks; | ||||
}; | }; | ||||
static struct ada_quirk_entry ada_quirk_table[] = | static struct ada_quirk_entry ada_quirk_table[] = | ||||
{ | { | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 589 Lines • ▼ Show 20 Lines | |||||
static int ada_retry_count = ADA_DEFAULT_RETRY; | static int ada_retry_count = ADA_DEFAULT_RETRY; | ||||
static int ada_default_timeout = ADA_DEFAULT_TIMEOUT; | static int ada_default_timeout = ADA_DEFAULT_TIMEOUT; | ||||
static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED; | static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED; | ||||
static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN; | static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN; | ||||
static int ada_spindown_suspend = ADA_DEFAULT_SPINDOWN_SUSPEND; | static int ada_spindown_suspend = ADA_DEFAULT_SPINDOWN_SUSPEND; | ||||
static int ada_read_ahead = ADA_DEFAULT_READ_AHEAD; | static int ada_read_ahead = ADA_DEFAULT_READ_AHEAD; | ||||
static int ada_write_cache = ADA_DEFAULT_WRITE_CACHE; | static int ada_write_cache = ADA_DEFAULT_WRITE_CACHE; | ||||
static int ada_enable_biospeedup = 1; | static int ada_enable_biospeedup = 1; | ||||
static int ada_enable_small_ccbs = 1; | |||||
static SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | static SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||
"CAM Direct Access Disk driver"); | "CAM Direct Access Disk driver"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RWTUN, | ||||
&ada_retry_count, 0, "Normal I/O retry count"); | &ada_retry_count, 0, "Normal I/O retry count"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RWTUN, | ||||
&ada_default_timeout, 0, "Normal I/O timeout (in seconds)"); | &ada_default_timeout, 0, "Normal I/O timeout (in seconds)"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, send_ordered, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, send_ordered, CTLFLAG_RWTUN, | ||||
&ada_send_ordered, 0, "Send Ordered Tags"); | &ada_send_ordered, 0, "Send Ordered Tags"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RWTUN, | ||||
&ada_spindown_shutdown, 0, "Spin down upon shutdown"); | &ada_spindown_shutdown, 0, "Spin down upon shutdown"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_suspend, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_suspend, CTLFLAG_RWTUN, | ||||
&ada_spindown_suspend, 0, "Spin down upon suspend"); | &ada_spindown_suspend, 0, "Spin down upon suspend"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, read_ahead, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, read_ahead, CTLFLAG_RWTUN, | ||||
&ada_read_ahead, 0, "Enable disk read-ahead"); | &ada_read_ahead, 0, "Enable disk read-ahead"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RWTUN, | ||||
&ada_write_cache, 0, "Enable disk write cache"); | &ada_write_cache, 0, "Enable disk write cache"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, enable_biospeedup, CTLFLAG_RDTUN, | SYSCTL_INT(_kern_cam_ada, OID_AUTO, enable_biospeedup, CTLFLAG_RDTUN, | ||||
&ada_enable_biospeedup, 0, "Enable BIO_SPEEDUP processing"); | &ada_enable_biospeedup, 0, "Enable BIO_SPEEDUP processing"); | ||||
SYSCTL_INT(_kern_cam_ada, OID_AUTO, enable_small_ccbs, CTLFLAG_RWTUN, | |||||
&ada_enable_small_ccbs, 0, "Use small CCBs"); | |||||
/* | /* | ||||
* ADA_ORDEREDTAG_INTERVAL determines how often, relative | * ADA_ORDEREDTAG_INTERVAL determines how often, relative | ||||
* to the default timeout, we check to see whether an ordered | * to the default timeout, we check to see whether an ordered | ||||
* tagged transaction is appropriate to prevent simple tag | * tagged transaction is appropriate to prevent simple tag | ||||
* starvation. Since we'd like to ensure that there is at least | * starvation. Since we'd like to ensure that there is at least | ||||
* 1/2 of the timeout length left for a starved transaction to | * 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 | * complete after we've sent an ordered tag, we must poll at least | ||||
▲ Show 20 Lines • Show All 262 Lines • ▼ Show 20 Lines | if ((EVENTHANDLER_REGISTER(power_suspend, adasuspend, | ||||
printf("adainit: power event registration failed!\n"); | printf("adainit: power event registration failed!\n"); | ||||
if ((EVENTHANDLER_REGISTER(power_resume, adaresume, | if ((EVENTHANDLER_REGISTER(power_resume, adaresume, | ||||
NULL, EVENTHANDLER_PRI_LAST)) == NULL) | NULL, EVENTHANDLER_PRI_LAST)) == NULL) | ||||
printf("adainit: power event registration failed!\n"); | printf("adainit: power event registration failed!\n"); | ||||
if ((EVENTHANDLER_REGISTER(shutdown_post_sync, adashutdown, | if ((EVENTHANDLER_REGISTER(shutdown_post_sync, adashutdown, | ||||
NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) | NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) | ||||
printf("adainit: shutdown event registration failed!\n"); | printf("adainit: shutdown event registration failed!\n"); | ||||
} | } | ||||
if (ada_ccb_zone == NULL) { | |||||
ada_ccb_zone = uma_zcreate("ada_ccb", | |||||
sizeof(struct ccb_ataio), NULL, NULL, NULL, NULL, | |||||
UMA_ALIGN_PTR, 0); | |||||
} | } | ||||
} | |||||
/* | /* | ||||
* Callback from GEOM, called when it has finished cleaning up its | * Callback from GEOM, called when it has finished cleaning up its | ||||
* resources. | * resources. | ||||
*/ | */ | ||||
static void | static void | ||||
adadiskgonecb(struct disk *dp) | adadiskgonecb(struct disk *dp) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | case AC_FOUND_DEVICE: | ||||
&& status != CAM_REQ_INPROG) | && status != CAM_REQ_INPROG) | ||||
printf("adaasync: Unable to attach to new device " | printf("adaasync: Unable to attach to new device " | ||||
"due to status 0x%x\n", status); | "due to status 0x%x\n", status); | ||||
break; | break; | ||||
} | } | ||||
case AC_GETDEV_CHANGED: | case AC_GETDEV_CHANGED: | ||||
{ | { | ||||
softc = (struct ada_softc *)periph->softc; | softc = (struct ada_softc *)periph->softc; | ||||
memset(&cgd, 0, sizeof(cgd)); | |||||
xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); | xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); | ||||
cgd.ccb_h.func_code = XPT_GDEV_TYPE; | cgd.ccb_h.func_code = XPT_GDEV_TYPE; | ||||
xpt_action((union ccb *)&cgd); | xpt_action((union ccb *)&cgd); | ||||
/* | /* | ||||
* Update our information based on the new Identify data. | * Update our information based on the new Identify data. | ||||
*/ | */ | ||||
adasetflags(softc, &cgd); | adasetflags(softc, &cgd); | ||||
Show All 19 Lines | adaasync(void *callback_arg, u_int32_t code, | ||||
} | } | ||||
case AC_SENT_BDR: | case AC_SENT_BDR: | ||||
case AC_BUS_RESET: | case AC_BUS_RESET: | ||||
{ | { | ||||
softc = (struct ada_softc *)periph->softc; | softc = (struct ada_softc *)periph->softc; | ||||
cam_periph_async(periph, code, path, arg); | cam_periph_async(periph, code, path, arg); | ||||
if (softc->state != ADA_STATE_NORMAL) | if (softc->state != ADA_STATE_NORMAL) | ||||
break; | break; | ||||
memset(&cgd, 0, sizeof(cgd)); | |||||
xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); | xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); | ||||
cgd.ccb_h.func_code = XPT_GDEV_TYPE; | cgd.ccb_h.func_code = XPT_GDEV_TYPE; | ||||
xpt_action((union ccb *)&cgd); | xpt_action((union ccb *)&cgd); | ||||
if (ADA_RA >= 0 && softc->flags & ADA_FLAG_CAN_RAHEAD) | if (ADA_RA >= 0 && softc->flags & ADA_FLAG_CAN_RAHEAD) | ||||
softc->state = ADA_STATE_RAHEAD; | softc->state = ADA_STATE_RAHEAD; | ||||
else if (ADA_WC >= 0 && softc->flags & ADA_FLAG_CAN_WCACHE) | else if (ADA_WC >= 0 && softc->flags & ADA_FLAG_CAN_WCACHE) | ||||
softc->state = ADA_STATE_WCACHE; | softc->state = ADA_STATE_WCACHE; | ||||
else if ((softc->flags & ADA_FLAG_CAN_LOG) | else if ((softc->flags & ADA_FLAG_CAN_LOG) | ||||
▲ Show 20 Lines • Show All 474 Lines • ▼ Show 20 Lines | adaregister(struct cam_periph *periph, void *arg) | ||||
softc->read_ahead = -1; | softc->read_ahead = -1; | ||||
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, | snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, | ||||
"kern.cam.ada.%d.read_ahead", periph->unit_number); | "kern.cam.ada.%d.read_ahead", periph->unit_number); | ||||
TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead); | TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead); | ||||
softc->write_cache = -1; | softc->write_cache = -1; | ||||
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, | snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, | ||||
"kern.cam.ada.%d.write_cache", periph->unit_number); | "kern.cam.ada.%d.write_cache", periph->unit_number); | ||||
TUNABLE_INT_FETCH(announce_buf, &softc->write_cache); | TUNABLE_INT_FETCH(announce_buf, &softc->write_cache); | ||||
/* | |||||
* XXX: This shouldn't be needed; for some reason this runs | |||||
* _before_ adainit(). | |||||
imp: Can you get a traceback of where it's called from before adainit()? I'd think it was only… | |||||
Done Inline ActionsIt is; the problem was, adainit was called before adaregister, as expected, but it didn't finish until after adaregister() was already running. Moving the UMA zone initialization to run earlier fixes the problem. trasz: It is; the problem was, adainit was called before adaregister, as expected, but it didn't… | |||||
*/ | |||||
Done Inline ActionsYou only need to kassert this when ada_enable_uma_ccbs is true. imp: You only need to kassert this when ada_enable_uma_ccbs is true.
| |||||
if (ada_ccb_zone == NULL) { | |||||
ada_ccb_zone = uma_zcreate("ada_ccb", | |||||
sizeof(struct ccb_ataio), NULL, NULL, NULL, NULL, | |||||
UMA_ALIGN_PTR, 0); | |||||
} | |||||
/* | |||||
* Let XPT know we can use small CCBs. | |||||
*/ | |||||
if (ada_enable_small_ccbs) { | |||||
periph->small_ccb_len = sizeof(struct ccb_ataio); | |||||
periph->small_ccb_zone = ada_ccb_zone; | |||||
} | |||||
/* | /* | ||||
* Set support flags based on the Identify data and quirks. | * Set support flags based on the Identify data and quirks. | ||||
*/ | */ | ||||
adasetflags(softc, cgd); | adasetflags(softc, cgd); | ||||
if (softc->cpi.hba_misc & PIM_ATA_EXT) | if (softc->cpi.hba_misc & PIM_ATA_EXT) | ||||
softc->flags |= ADA_FLAG_PIM_ATA_EXT; | softc->flags |= ADA_FLAG_PIM_ATA_EXT; | ||||
▲ Show 20 Lines • Show All 1,834 Lines • Show Last 20 Lines |
Can you get a traceback of where it's called from before adainit()? I'd think it was only enterable after atainit() completes, but maybe the 'master callback' races this and we should do all the init prior to establishing that?