int q6usm_us_client_buf_alloc(unsigned int dir,
			      struct us_client *usc,
			      unsigned int bufsz,
			      unsigned int bufcnt)
{
	int rc = 0;
	struct us_port_data *port = NULL;
	unsigned int size = bufsz*bufcnt;

	if ((usc == NULL) ||
	    ((dir != IN) && (dir != OUT)) || (size == 0) ||
	    (usc->session <= 0 || usc->session > SESSION_MAX)) {
		pr_err("%s: wrong parameters: size=%d; bufcnt=%d\n",
		       __func__, size, bufcnt);
		return -EINVAL;
	}

	mutex_lock(&usc->cmd_lock);

	port = &usc->port[dir];

	port->data = dma_alloc_coherent(NULL, size, &(port->phys), GFP_KERNEL);
	if (port->data == NULL) {
		pr_err("%s: US region allocation failed\n", __func__);
		mutex_unlock(&usc->cmd_lock);
		return -ENOMEM;
	}

	port->buf_cnt = bufcnt;
	port->buf_size = bufsz;
	pr_debug("%s: data[%p]; phys[%p]; [%p]\n", __func__,
		 (void *)port->data,
		 (void *)port->phys,
		 (void *)&port->phys);

	size = (size + MEM_4K_OFFSET) & MEM_4K_MASK;
	rc = q6usm_memory_map(port->phys, dir, size, 1, usc->session,
				(uint32_t *)port->ext);
	if (rc < 0) {
		pr_err("%s: CMD Memory_map failed\n", __func__);
		mutex_unlock(&usc->cmd_lock);
		q6usm_us_client_buf_free(dir, usc);
		q6usm_us_param_buf_free(dir, usc);
	} else {
		mutex_unlock(&usc->cmd_lock);
		rc = 0;
	}

	return rc;
}
void q6usm_us_client_free(struct us_client *usc)
{
	int loopcnt = 0;
	struct us_port_data *port;
	uint32_t *p_mem_handle = NULL;

	if (usc == NULL)
		return;
	if (!(usc->session)) {
		kfree(usc);
		return;
	}

	for (loopcnt = 0; loopcnt <= OUT; ++loopcnt) {
		port = &usc->port[loopcnt];
		if (port->data == NULL)
			continue;
		pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
		q6usm_us_client_buf_free(loopcnt, usc);
		q6usm_us_param_buf_free(loopcnt, usc);
	}
	q6usm_session_free(usc);
	apr_deregister(usc->apr);

	pr_debug("%s: APR De-Register\n", __func__);

	if (atomic_read(&this_mmap.ref_cnt) <= 0) {
		pr_err("%s: APR Common Port Already Closed\n", __func__);
		goto done;
	}

	atomic_dec(&this_mmap.ref_cnt);
	if (atomic_read(&this_mmap.ref_cnt) == 0) {
		apr_deregister(this_mmap.apr);
		pr_debug("%s: APR De-Register common port\n", __func__);
	}

done:
	p_mem_handle = (uint32_t *)usc->port[IN].ext;
	kfree(p_mem_handle);
	kfree(usc);
	pr_debug("%s:\n", __func__);
	return;
}
Example #3
0
int q6usm_us_param_buf_alloc(unsigned int dir,
			struct us_client *usc,
			unsigned int bufsz)
{
	int rc = 0;
	struct us_port_data *port = NULL;
	unsigned int size = bufsz;
	size_t len;

	if ((usc == NULL) ||
		((dir != IN) && (dir != OUT)) ||
		(usc->session <= 0 || usc->session > USM_SESSION_MAX)) {
		pr_err("%s: wrong parameters: direction=%d, bufsz=%d\n",
			__func__, dir, bufsz);
		return -EINVAL;
	}

	mutex_lock(&usc->cmd_lock);

	port = &usc->port[dir];

	if (bufsz == 0) {
		pr_debug("%s: bufsz=0, get/set param commands are forbidden\n",
			__func__);
		port->param_buf = NULL;
		mutex_unlock(&usc->cmd_lock);
		return rc;
	}

	/* The size to allocate should be multiple of 4K bytes */
	size = PAGE_ALIGN(size);

	rc = msm_audio_ion_alloc("ultrasound_client",
		&port->param_client, &port->param_handle,
		size, &port->param_phys,
		&len, &port->param_buf);

	if (rc) {
		pr_err("%s: US ION allocation failed, rc = %d\n",
			__func__, rc);
		mutex_unlock(&usc->cmd_lock);
		return -ENOMEM;
	}

	port->param_buf_size = bufsz;
	pr_debug("%s: param_buf[%p]; param_phys[%llx]; [%p]\n", __func__,
		 (void *)port->param_buf,
		 (u64)port->param_phys,
		 (void *)&port->param_phys);

	rc = q6usm_memory_map(port->param_phys, (IN | OUT), size, 1,
			usc->session, (uint32_t *)port->param_buf_mem_handle);
	if (rc < 0) {
		pr_err("%s: CMD Memory_map failed\n", __func__);
		mutex_unlock(&usc->cmd_lock);
		q6usm_us_client_buf_free(dir, usc);
		q6usm_us_param_buf_free(dir, usc);
	} else {
		mutex_unlock(&usc->cmd_lock);
		rc = 0;
	}

	return rc;
}