static int init_cgr(struct device *qidev) { int ret; struct qm_mcc_initcgr opts; const u64 cpus = *(u64 *)qman_affine_cpus(); const int num_cpus = hweight64(cpus); const u64 val = num_cpus * MAX_RSP_FQ_BACKLOG_PER_CPU; ret = qman_alloc_cgrid(&qipriv.cgr.cgrid); if (ret) { dev_err(qidev, "CGR alloc failed for rsp FQs: %d\n", ret); return ret; } qipriv.cgr.cb = cgr_cb; memset(&opts, 0, sizeof(opts)); opts.we_mask = cpu_to_be16(QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES | QM_CGR_WE_MODE); opts.cgr.cscn_en = QM_CGR_EN; opts.cgr.mode = QMAN_CGR_MODE_FRAME; qm_cgr_cs_thres_set64(&opts.cgr.cs_thres, val, 1); ret = qman_create_cgr(&qipriv.cgr, QMAN_CGR_FLAG_USE_INIT, &opts); if (ret) { dev_err(qidev, "Error %d creating CAAM CGRID: %u\n", ret, qipriv.cgr.cgrid); return ret; } dev_info(qidev, "Congestion threshold set to %llu\n", val); return 0; }
static int alloc_rsp_fqs(struct device *qidev) { int ret, i; const cpumask_t *cpus = qman_affine_cpus(); /*Now create response FQs*/ for_each_cpu(i, cpus) { ret = alloc_rsp_fq_cpu(qidev, i); if (ret) { dev_err(qidev, "CAAM rsp FQ alloc failed, cpu: %u", i); return ret; } }
static int alloc_cgrs(struct device *qidev) { struct qm_mcc_initcgr opts; int ret; const u64 cpus = *(u64 *)qman_affine_cpus(); const int num_cpus = hweight64(cpus); u64 val; /*Allocate response CGR*/ ret = qman_alloc_cgrid(&qipriv.rsp_cgr.cgrid); if (ret) { dev_err(qidev, "CGR alloc failed for rsp FQs"); return ret; } qipriv.rsp_cgr.cb = rsp_cgr_cb; memset(&opts, 0, sizeof(opts)); opts.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES | QM_CGR_WE_MODE; opts.cgr.cscn_en = QM_CGR_EN; opts.cgr.mode = QMAN_CGR_MODE_FRAME; #ifdef CONFIG_FSL_DPAA_ETH /* * This effectively sets the to-CPU threshold equal to half of the * number of buffers available to dpa_eth driver. It means that at most * half of the buffers can be in the queues from SEC, waiting * to be transmitted to the core (and then on the TX queues). * NOTE: This is an arbitrary division; the factor '2' below could * also be '3' or '4'. It also depends on the number of devices * using the dpa_eth buffers (which can be >1 if f.i. PME/DCE are * also used. */ val = num_cpus * CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT / 2; #else val = num_cpus * MAX_RSP_FQ_BACKLOG_PER_CPU; #endif qm_cgr_cs_thres_set64(&opts.cgr.cs_thres, val, 1); ret = qman_create_cgr(&qipriv.rsp_cgr, QMAN_CGR_FLAG_USE_INIT, &opts); if (ret) { dev_err(qidev, "Error %d creating CAAM rsp CGRID: %u\n", ret, qipriv.rsp_cgr.cgrid); return ret; } #ifdef DEBUG dev_info(qidev, "CAAM to CPU threshold set to %llu\n", val); #endif return 0; }
int caam_qi_shutdown(struct device *qidev) { struct caam_qi_priv *priv = dev_get_drvdata(qidev); int i, ret; const cpumask_t *cpus = qman_affine_cpus(); struct cpumask old_cpumask = *tsk_cpus_allowed(current); for_each_cpu(i, cpus) { struct napi_struct *irqtask; irqtask = &per_cpu_ptr(&pcpu_qipriv.caam_napi, i)->irqtask; napi_disable(irqtask); netif_napi_del(irqtask); if (kill_fq(qidev, &per_cpu(pcpu_qipriv.rsp_fq, i))) dev_err(qidev, "Rsp FQ kill failed, cpu: %d\n", i); } /* * QMAN driver requires CGRs to be deleted from same CPU from where * they were instantiated. Hence we get the module removal execute * from the same CPU from where it was originally inserted. */ set_cpus_allowed_ptr(current, get_cpu_mask(mod_init_cpu)); ret = qman_delete_cgr(&priv->rsp_cgr); if (ret) dev_err(qidev, "Delete response CGR failed: %d\n", ret); else qman_release_cgrid(priv->rsp_cgr.cgrid); if (qi_cache) kmem_cache_destroy(qi_cache); /* Now that we're done with the CGRs, restore the cpus allowed mask */ set_cpus_allowed_ptr(current, &old_cpumask); platform_device_unregister(priv->qi_pdev); return ret; }
void caam_qi_shutdown(struct device *qidev) { int i; struct caam_qi_priv *priv = dev_get_drvdata(qidev); const cpumask_t *cpus = qman_affine_cpus(); for_each_cpu(i, cpus) { struct napi_struct *irqtask; irqtask = &per_cpu_ptr(&pcpu_qipriv.caam_napi, i)->irqtask; napi_disable(irqtask); netif_napi_del(irqtask); if (kill_fq(qidev, per_cpu(pcpu_qipriv.rsp_fq, i))) dev_err(qidev, "Rsp FQ kill failed, cpu: %d\n", i); } qman_delete_cgr_safe(&priv->cgr); qman_release_cgrid(priv->cgr.cgrid); kmem_cache_destroy(qi_cache); platform_device_unregister(priv->qi_pdev); }
struct caam_drv_ctx *caam_drv_ctx_init(struct device *qidev, int *cpu, u32 *sh_desc) { size_t size; u32 num_words; dma_addr_t hwdesc; struct caam_drv_ctx *drv_ctx; const cpumask_t *cpus = qman_affine_cpus(); static DEFINE_PER_CPU(int, last_cpu); num_words = desc_len(sh_desc); if (num_words > MAX_SDLEN) { dev_err(qidev, "Invalid descriptor len: %d words\n", num_words); return ERR_PTR(-EINVAL); } drv_ctx = kzalloc(sizeof(*drv_ctx), GFP_ATOMIC); if (!drv_ctx) return ERR_PTR(-ENOMEM); /* * Initialise pre-header - set RSLS and SDLEN - and shared descriptor * and dma-map them. */ drv_ctx->prehdr[0] = cpu_to_caam32((1 << PREHDR_RSLS_SHIFT) | num_words); memcpy(drv_ctx->sh_desc, sh_desc, desc_bytes(sh_desc)); size = sizeof(drv_ctx->prehdr) + sizeof(drv_ctx->sh_desc); hwdesc = dma_map_single(qidev, drv_ctx->prehdr, size, DMA_BIDIRECTIONAL); if (dma_mapping_error(qidev, hwdesc)) { dev_err(qidev, "DMA map error for preheader + shdesc\n"); kfree(drv_ctx); return ERR_PTR(-ENOMEM); } drv_ctx->context_a = hwdesc; /* If given CPU does not own the portal, choose another one that does */ if (!cpumask_test_cpu(*cpu, cpus)) { int *pcpu = &get_cpu_var(last_cpu); *pcpu = cpumask_next(*pcpu, cpus); if (*pcpu >= nr_cpu_ids) *pcpu = cpumask_first(cpus); *cpu = *pcpu; put_cpu_var(last_cpu); } drv_ctx->cpu = *cpu; /* Find response FQ hooked with this CPU */ drv_ctx->rsp_fq = per_cpu(pcpu_qipriv.rsp_fq, drv_ctx->cpu); /* Attach request FQ */ drv_ctx->req_fq = create_caam_req_fq(qidev, drv_ctx->rsp_fq, hwdesc, QMAN_INITFQ_FLAG_SCHED); if (unlikely(IS_ERR_OR_NULL(drv_ctx->req_fq))) { dev_err(qidev, "create_caam_req_fq failed\n"); dma_unmap_single(qidev, hwdesc, size, DMA_BIDIRECTIONAL); kfree(drv_ctx); return ERR_PTR(-ENOMEM); } drv_ctx->qidev = qidev; return drv_ctx; }