diff options
author | mav <mav@FreeBSD.org> | 2011-04-19 08:01:17 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2011-04-19 08:01:17 +0000 |
commit | cc8f016bc18d45715487b51cf1921fa81a59259d (patch) | |
tree | b127f1c0f2074a00cefb5b52a4696a36352ccb98 /sys/dev/ahci/ahci.c | |
parent | ebedcfac8977c396375e952c56d739bc5eb917ed (diff) | |
download | FreeBSD-src-cc8f016bc18d45715487b51cf1921fa81a59259d.zip FreeBSD-src-cc8f016bc18d45715487b51cf1921fa81a59259d.tar.gz |
Properly handle memory allocation errors during error recovery.
Diffstat (limited to 'sys/dev/ahci/ahci.c')
-rw-r--r-- | sys/dev/ahci/ahci.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index e765a32..ac200cb 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -2132,7 +2132,6 @@ ahci_issue_recovery(device_t dev) struct ccb_scsiio *csio; int i; - ch->recoverycmd = 1; /* Find some holden command. */ for (i = 0; i < ch->numslots; i++) { if (ch->hold[i]) @@ -2140,8 +2139,20 @@ ahci_issue_recovery(device_t dev) } ccb = xpt_alloc_ccb_nowait(); if (ccb == NULL) { - device_printf(dev, "Unable allocate READ LOG command"); - return; /* XXX */ + device_printf(dev, "Unable allocate recovery command\n"); +completeall: + /* We can't do anything -- complete holden commands. */ + for (i = 0; i < ch->numslots; i++) { + if (ch->hold[i] == NULL) + continue; + ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; + ch->hold[i]->ccb_h.status |= CAM_RESRC_UNAVAIL; + xpt_done(ch->hold[i]); + ch->hold[i] = NULL; + ch->numhslots--; + } + ahci_reset(dev); + return; } ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */ if (ccb->ccb_h.func_code == XPT_ATA_IO) { @@ -2154,8 +2165,9 @@ ahci_issue_recovery(device_t dev) ataio->data_ptr = malloc(512, M_AHCI, M_NOWAIT); if (ataio->data_ptr == NULL) { xpt_free_ccb(ccb); - device_printf(dev, "Unable allocate memory for READ LOG command"); - return; /* XXX */ + device_printf(dev, + "Unable allocate memory for READ LOG command\n"); + goto completeall; } ataio->dxfer_len = 512; bzero(&ataio->cmd, sizeof(ataio->cmd)); @@ -2183,6 +2195,7 @@ ahci_issue_recovery(device_t dev) csio->cdb_io.cdb_bytes[4] = csio->dxfer_len; } /* Freeze SIM while doing recovery. */ + ch->recoverycmd = 1; xpt_freeze_simq(ch->sim, 1); ahci_begin_transaction(dev, ccb); } |