summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-all.h8
-rw-r--r--sys/dev/ata/ata-queue.c23
2 files changed, 24 insertions, 7 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 1b98e04..4361824 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -372,6 +372,8 @@ struct ata_request {
#define ATA_R_DIRECT 0x00001000
#define ATA_R_DEBUG 0x10000000
+#define ATA_R_DANGER1 0x20000000
+#define ATA_R_DANGER2 0x40000000
u_int8_t status; /* ATA status */
u_int8_t error; /* ATA error */
@@ -569,8 +571,10 @@ int ata_generic_command(struct ata_request *request);
/* macros for alloc/free of struct ata_request */
extern uma_zone_t ata_request_zone;
#define ata_alloc_request() uma_zalloc(ata_request_zone, M_NOWAIT | M_ZERO)
-#define ata_free_request(request) uma_zfree(ata_request_zone, request)
-
+#define ata_free_request(request) { \
+ if (!(request->flags & ATA_R_DANGER2)) \
+ uma_zfree(ata_request_zone, request); \
+ }
/* macros for alloc/free of struct ata_composite */
extern uma_zone_t ata_composite_zone;
#define ata_alloc_composite() uma_zalloc(ata_composite_zone, M_NOWAIT | M_ZERO)
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c
index 036b008..5de54ff 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -95,12 +95,14 @@ ata_queue_request(struct ata_request *request)
/* if this is not a callback wait until request is completed */
if (!request->callback) {
ATA_DEBUG_RQ(request, "wait for completition");
- while (!dumping &&
- sema_timedwait(&request->done, request->timeout * hz * 4)) {
+ if (!dumping &&
+ sema_timedwait(&request->done, request->timeout * hz * 4)) {
device_printf(request->dev,
- "req=%p %s semaphore timeout !! DANGER Will Robinson !!\n",
- request, ata_cmd2str(request));
- ata_start(ch->dev);
+ "WARNING - %s taskqueue timeout "
+ "- completing request directly\n",
+ ata_cmd2str(request));
+ request->flags |= ATA_R_DANGER1;
+ ata_completed(request, 0);
}
sema_destroy(&request->done);
}
@@ -252,6 +254,17 @@ ata_completed(void *context, int dummy)
struct ata_device *atadev = device_get_softc(request->dev);
struct ata_composite *composite;
+ if (request->flags & ATA_R_DANGER2) {
+ device_printf(request->dev,
+ "WARNING - %s freeing taskqueue zombie request\n",
+ ata_cmd2str(request));
+ request->flags &= ~(ATA_R_DANGER1 | ATA_R_DANGER2);
+ ata_free_request(request);
+ return;
+ }
+ if (request->flags & ATA_R_DANGER1)
+ request->flags |= ATA_R_DANGER2
+
ATA_DEBUG_RQ(request, "completed entered");
/* if we had a timeout, reinit channel and deal with the falldown */
OpenPOWER on IntegriCloud