Keep the parent device (in this case the channel) around in ata_request,
so we dont panic device removal or failure. Clean up ata_fail_requests to prevent the queue munging to fail.
This commit is contained in:
parent
555253faf1
commit
cacaead301
@ -338,6 +338,7 @@ struct ata_composite {
|
||||
/* structure used to queue an ATA/ATAPI request */
|
||||
struct ata_request {
|
||||
device_t dev; /* device handle */
|
||||
device_t parent; /* channel handle */
|
||||
union {
|
||||
struct {
|
||||
u_int8_t command; /* command reg */
|
||||
|
@ -55,6 +55,7 @@ ata_queue_request(struct ata_request *request)
|
||||
|
||||
/* mark request as virgin (this might be a ATA_R_REQUEUE) */
|
||||
request->result = request->status = request->error = 0;
|
||||
request->parent = device_get_parent(request->dev);
|
||||
callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED);
|
||||
|
||||
if (!request->callback && !(request->flags & ATA_R_REQUEUE))
|
||||
@ -218,7 +219,7 @@ ata_start(device_t dev)
|
||||
void
|
||||
ata_finish(struct ata_request *request)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
|
||||
struct ata_channel *ch = device_get_softc(request->parent);
|
||||
|
||||
/*
|
||||
* if in ATA_STALL_QUEUE state or request has ATA_R_DIRECT flags set
|
||||
@ -247,7 +248,7 @@ static void
|
||||
ata_completed(void *context, int dummy)
|
||||
{
|
||||
struct ata_request *request = (struct ata_request *)context;
|
||||
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
|
||||
struct ata_channel *ch = device_get_softc(request->parent);
|
||||
struct ata_device *atadev = device_get_softc(request->dev);
|
||||
struct ata_composite *composite;
|
||||
|
||||
@ -466,7 +467,7 @@ ata_completed(void *context, int dummy)
|
||||
void
|
||||
ata_timeout(struct ata_request *request)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
|
||||
struct ata_channel *ch = device_get_softc(request->parent);
|
||||
|
||||
//request->flags |= ATA_R_DEBUG;
|
||||
ATA_DEBUG_RQ(request, "timeout");
|
||||
@ -479,7 +480,6 @@ ata_timeout(struct ata_request *request)
|
||||
*/
|
||||
if (ch->state == ATA_ACTIVE) {
|
||||
request->flags |= ATA_R_TIMEOUT;
|
||||
ch->running = NULL;
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
|
||||
ata_finish(request);
|
||||
@ -493,34 +493,43 @@ void
|
||||
ata_fail_requests(device_t dev)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(device_get_parent(dev));
|
||||
struct ata_request *request;
|
||||
struct ata_request *request, *tmp;
|
||||
TAILQ_HEAD(, ata_request) fail_requests;
|
||||
TAILQ_INIT(&fail_requests);
|
||||
|
||||
/* do we have any outstanding request to care about ?*/
|
||||
/* grap all channel locks to avoid races */
|
||||
mtx_lock(&ch->queue_mtx);
|
||||
mtx_lock(&ch->state_mtx);
|
||||
|
||||
/* do we have any running request to care about ? */
|
||||
if ((request = ch->running) && (!dev || request->dev == dev)) {
|
||||
callout_stop(&request->callout);
|
||||
ch->running = NULL;
|
||||
}
|
||||
else
|
||||
request = NULL;
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
if (request) {
|
||||
ch->state = ATA_IDLE;
|
||||
request->result = ENXIO;
|
||||
ata_finish(request);
|
||||
TAILQ_INSERT_TAIL(&fail_requests, request, chain);
|
||||
}
|
||||
|
||||
/* fail all requests queued on this channel for device dev if !NULL */
|
||||
mtx_lock(&ch->queue_mtx);
|
||||
while ((request = TAILQ_FIRST(&ch->ata_queue))) {
|
||||
TAILQ_FOREACH_SAFE(request, &ch->ata_queue, chain, tmp) {
|
||||
if (!dev || request->dev == dev) {
|
||||
TAILQ_REMOVE(&ch->ata_queue, request, chain);
|
||||
mtx_unlock(&ch->queue_mtx);
|
||||
request->result = ENXIO;
|
||||
ata_finish(request);
|
||||
mtx_lock(&ch->queue_mtx);
|
||||
TAILQ_INSERT_TAIL(&fail_requests, request, chain);
|
||||
}
|
||||
}
|
||||
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
mtx_unlock(&ch->queue_mtx);
|
||||
|
||||
/* finish up all requests collected above */
|
||||
TAILQ_FOREACH_SAFE(request, &fail_requests, chain, tmp) {
|
||||
TAILQ_REMOVE(&fail_requests, request, chain);
|
||||
ata_finish(request);
|
||||
}
|
||||
|
||||
/* we might have work for the other device on this channel */
|
||||
ata_start(ch->dev);
|
||||
}
|
||||
|
||||
static u_int64_t
|
||||
|
Loading…
Reference in New Issue
Block a user