static void retry_erase(erase_busy_t *busy, u_int cause) { eraseq_entry_t *erase = busy->erase; mtd_request_t req; client_t *mtd; socket_info_t *s; int ret; DEBUG(2, "cs: trying erase request 0x%p...\n", busy); if (busy->next) remove_queue(busy); req.Function = MTD_REQ_ERASE | cause; req.TransferLength = erase->Size; req.DestCardOffset = erase->Offset + erase->Handle->info.CardOffset; req.MediaID = erase->Handle->MediaID; mtd = erase->Handle->mtd; s = SOCKET(mtd); mtd->event_callback_args.mtdrequest = &req; wacquire(&mtd->mtd_req); ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW); wrelease(&mtd->mtd_req); if (ret == CS_BUSY) { DEBUG(2, " Status = %d, requeueing.\n", req.Status); switch (req.Status) { case MTD_WAITREQ: case MTD_WAITPOWER: insert_queue(&mtd->erase_busy, busy); break; case MTD_WAITTIMER: case MTD_WAITRDY: if (req.Status == MTD_WAITRDY) insert_queue(&s->erase_busy, busy); mod_timer(&busy->timeout, jiffies + req.Timeout*HZ/1000); break; } } else { /* update erase queue status */ DEBUG(2, " Ret = %d\n", ret); switch (ret) { case CS_SUCCESS: erase->State = ERASE_PASSED; break; case CS_WRITE_PROTECTED: erase->State = ERASE_MEDIA_WRPROT; break; case CS_BAD_OFFSET: erase->State = ERASE_BAD_OFFSET; break; case CS_BAD_SIZE: erase->State = ERASE_BAD_SIZE; break; case CS_NO_CARD: erase->State = ERASE_BAD_SOCKET; break; default: erase->State = ERASE_FAILED; break; } busy->client->event_callback_args.info = erase; EVENT(busy->client, CS_EVENT_ERASE_COMPLETE, CS_EVENT_PRI_LOW); kfree(busy); /* Resubmit anything waiting for a request to finish */ wakeup(&mtd->mtd_req); retry_erase_list(&mtd->erase_busy, 0); } } /* retry_erase */
static int do_mtd_request(memory_handle_t handle, mtd_request_t *req, caddr_t buf) { int ret, tries; client_t *mtd; socket_info_t *s; mtd = handle->mtd; if (mtd == NULL) return CS_GENERAL_FAILURE; s = SOCKET(mtd); wacquire(&mtd->mtd_req); for (ret = tries = 0; tries < 100; tries++) { mtd->event_callback_args.mtdrequest = req; mtd->event_callback_args.buffer = buf; ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW); if (ret != CS_BUSY) break; switch (req->Status) { case MTD_WAITREQ: /* Not that we should ever need this... */ wsleeptimeout(&mtd->mtd_req, HZ); break; case MTD_WAITTIMER: case MTD_WAITRDY: wsleeptimeout(&mtd->mtd_req, req->Timeout*HZ/1000); req->Function |= MTD_REQ_TIMEOUT; break; case MTD_WAITPOWER: wsleep(&mtd->mtd_req); break; } #ifndef __MACOSX__ if (signal_pending(current)) printk(KERN_NOTICE "cs: do_mtd_request interrupted!\n"); #endif } wrelease(&mtd->mtd_req); if (tries == 20) { printk(KERN_NOTICE "cs: MTD request timed out!\n"); ret = CS_GENERAL_FAILURE; } wakeup(&mtd->mtd_req); retry_erase_list(&mtd->erase_busy, 0); return ret; } /* do_mtd_request */