diff --git a/sys/dev/raid/ips/ips.c b/sys/dev/raid/ips/ips.c index 1111111..2222222 100644 --- a/sys/dev/raid/ips/ips.c +++ b/sys/dev/raid/ips/ips.c @@ -352,7 +352,22 @@ ips_timeout(void *arg) * Grr, I hate this solution. I run waiting commands * one at a time and error them out just before they * would go to the card. This sucks. */ - } else + } else sc->state &= ~IPS_TIMEOUT; } + /* + * DF-4613: the forced reinit issues config-sync / error-table + * commands and tsleeps for their completion (ips_commands.c:722,743). + * That completion is only delivered by the interrupt handler, which + * must first acquire sc->queue_lock (ips.c:585/769). Running the + * reinit with queue_lock held therefore deadlocks the softclock + * thread and the IPS ithread permanently (timer-path twin of the + * DF-2163 ioctl deadlock). Drop the lock around the reinit. + */ + lockmgr(&sc->queue_lock, LK_RELEASE); + if (!state && (sc->state & IPS_TIMEOUT)) { + if (sc->ips_adapter_reinit(sc, 1)) { + device_printf(sc->dev, "AIEE! adapter reset failed, " + "giving up and going home! Have a nice day.\n"); + sc->state |= IPS_OFFLINE; + } + sc->state &= ~IPS_TIMEOUT; + } + lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY); if (sc->state != IPS_OFFLINE) callout_reset(&sc->timer, 10 * hz, ips_timeout, sc); - lockmgr(&sc->queue_lock, LK_RELEASE); } diff --git a/sys/dev/raid/ips/ips_commands.c b/sys/dev/raid/ips/ips_commands.c index 1111111..2222222 100644 --- a/sys/dev/raid/ips/ips_commands.c +++ b/sys/dev/raid/ips/ips_commands.c @@ -719,7 +719,7 @@ ips_send_config_sync_cmd(ips_command_t *command) sc->ips_issue_cmd(command); if (command->status.value != IPS_ERROR_STATUS) - ips_timed_wait(command, "ipssyn", 0); + ips_timed_wait(command, "ipssyn", 60 * hz); ips_insert_free_cmd(sc, command); return 0; } @@ -740,7 +740,7 @@ ips_send_error_table_cmd(ips_command_t *command) sc->ips_issue_cmd(command); if (command->status.value != IPS_ERROR_STATUS) - ips_timed_wait(command, "ipsetc", 0); + ips_timed_wait(command, "ipsetc", 60 * hz); ips_insert_free_cmd(sc, command); return 0; }