/** * crystalhd_create_dioq - Create Generic DIO queue * @adp: Adapter instance * @dioq_hnd: Handle to the dio queue created * @cb : Optional - Call back To free the element. * @cbctx: Context to pass to callback. * * Return: * status * * Initialize Generic DIO queue to hold any data. Callback * will be used to free elements while deleting the queue. */ BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp, crystalhd_dioq_t **dioq_hnd, crystalhd_data_free_cb cb, void *cbctx) { crystalhd_dioq_t *dioq = NULL; if (!adp || !dioq_hnd) { printk(KERN_ERR "%s: Invalid arg\n", __func__); return BC_STS_INV_ARG; } #ifndef __APPLE__ dioq = kzalloc(sizeof(*dioq), GFP_KERNEL); #else dioq = (crystalhd_dioq_t*)kzalloc(sizeof(*dioq), GFP_KERNEL); #endif if (!dioq) return BC_STS_INSUFF_RES; spin_lock_init(&dioq->lock); dioq->sig = BC_LINK_DIOQ_SIG; dioq->head = (crystalhd_elem_t *)&dioq->head; dioq->tail = (crystalhd_elem_t *)&dioq->head; crystalhd_create_event(&dioq->event); dioq->adp = adp; dioq->data_rel_cb = cb; dioq->cb_context = cbctx; *dioq_hnd = dioq; return BC_STS_SUCCESS; }
static enum BC_STATUS bc_cproc_codein_sleep(struct crystalhd_cmd *ctx) { wait_queue_head_t sleep_ev; int rc = 0; if (ctx->state & BC_LINK_SUSPEND) return BC_STS_IO_USER_ABORT; if (ctx->cin_wait_exit) { ctx->cin_wait_exit = 0; return BC_STS_CMD_CANCELLED; } crystalhd_create_event(&sleep_ev); crystalhd_wait_on_event(&sleep_ev, 0, 100, rc, 0); if (rc == -EINTR) return BC_STS_IO_USER_ABORT; return BC_STS_SUCCESS; }
static enum BC_STATUS bc_cproc_hw_txdma(struct crystalhd_cmd *ctx, struct crystalhd_ioctl_data *idata, struct crystalhd_dio_req *dio) { uint32_t tx_listid = 0; enum BC_STATUS sts = BC_STS_SUCCESS; wait_queue_head_t event; int rc = 0; if (!ctx || !idata || !dio) { BCMLOG_ERR("Invalid Arg!!\n"); return BC_STS_INV_ARG; } crystalhd_create_event(&event); ctx->tx_list_id = 0; /* msleep_interruptible(2000); */ sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion, &event, &tx_listid, idata->udata.u.ProcInput.Encrypted); while (sts == BC_STS_BUSY) { sts = bc_cproc_codein_sleep(ctx); if (sts != BC_STS_SUCCESS) break; sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion, &event, &tx_listid, idata->udata.u.ProcInput.Encrypted); } if (sts != BC_STS_SUCCESS) { BCMLOG(BCMLOG_DBG, "_hw_txdma returning sts:%d\n", sts); return sts; } if (ctx->cin_wait_exit) ctx->cin_wait_exit = 0; ctx->tx_list_id = tx_listid; /* _post() succeeded.. wait for the completion. */ crystalhd_wait_on_event(&event, (dio->uinfo.ev_sts), 3000, rc, 0); ctx->tx_list_id = 0; if (!rc) { return dio->uinfo.comp_sts; } else if (rc == -EBUSY) { BCMLOG(BCMLOG_DBG, "_tx_post() T/O\n"); sts = BC_STS_TIMEOUT; } else if (rc == -EINTR) { BCMLOG(BCMLOG_DBG, "Tx Wait Signal int.\n"); sts = BC_STS_IO_USER_ABORT; } else { sts = BC_STS_IO_ERROR; } /* We are cancelling the IO from the same context as the _post(). * so no need to wait on the event again.. the return itself * ensures the release of our resources. */ crystalhd_hw_cancel_tx(&ctx->hw_ctx, tx_listid); return sts; }