/*
 * Copyright (c) 2010 Atheros Communications Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "htc.h"

static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
			  u16 len, u8 flags, u8 epid,
			  struct ath9k_htc_tx_ctl *tx_ctl)
{
	struct htc_frame_hdr *hdr;
	struct htc_endpoint *endpoint = &target->endpoint[epid];
	int status;

	hdr = (struct htc_frame_hdr *)
		skb_push(skb, sizeof(struct htc_frame_hdr));
	hdr->endpoint_id = epid;
	hdr->flags = flags;
	hdr->payload_len = cpu_to_be16(len);

	status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb,
				   tx_ctl);
	return status;
}

static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint)
{
	enum htc_endpoint_id avail_epid;

	for (avail_epid = (ENDPOINT_MAX - 1); avail_epid > ENDPOINT0; avail_epid--)
		if (endpoint[avail_epid].service_id == 0)
			return &endpoint[avail_epid];
	return NULL;
}

static u8 service_to_ulpipe(u16 service_id)
{
	switch (service_id) {
	case WMI_CONTROL_SVC:
		return 4;
	case WMI_BEACON_SVC:
	case WMI_CAB_SVC:
	case WMI_UAPSD_SVC:
	case WMI_MGMT_SVC:
	case WMI_DATA_VO_SVC:
	case WMI_DATA_VI_SVC:
	case WMI_DATA_BE_SVC:
	case WMI_DATA_BK_SVC:
		return 1;
	default:
		return 0;
	}
}

static u8 service_to_dlpipe(u16 service_id)
{
	switch (service_id) {
	case WMI_CONTROL_SVC:
		return 3;
	case WMI_BEACON_SVC:
	case WMI_CAB_SVC:
	case WMI_UAPSD_SVC:
	case WMI_MGMT_SVC:
	case WMI_DATA_VO_SVC:
	case WMI_DATA_VI_SVC:
	case WMI_DATA_BE_SVC:
	case WMI_DATA_BK_SVC:
		return 2;
	default:
		return 0;
	}
}

static void htc_process_target_rdy(struct htc_target *target,
				   void *buf)
{
	struct htc_endpoint *endpoint;
	struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf;

	target->credit_size = be16_to_cpu(htc_ready_msg->credit_size);

	endpoint = &target->endpoint[ENDPOINT0];
	endpoint->service_id = HTC_CTRL_RSVD_SVC;
	endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH;
	atomic_inc(&target->tgt_ready);
	complete(&target->target_wait);
}

static void htc_process_conn_rsp(struct htc_target *target,
				 struct htc_frame_hdr *htc_hdr)
{
	struct htc_conn_svc_rspmsg *svc_rspmsg;
	struct htc_endpoint *endpoint, *tmp_endpoint = NULL;
	u16 service_id;
	u16 max_msglen;
	enum htc_endpoint_id epid, tepid;

	svc_rspmsg = (struct htc_conn_svc_rspmsg *)
		((void *) htc_hdr + sizeof(struct htc_frame_hdr));

	if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
		epid = svc_rspmsg->endpoint_id;
		service_id = be16_to_cpu(svc_rspmsg->service_id);
		max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len);
		endpoint = &target->endpoint[epid];

		for (tepid = (ENDPOINT_MAX - 1); tepid > ENDPOINT0; tepid--) {
			tmp_endpoint = &target->endpoint[tepid];
			if (tmp_endpoint->service_id == service_id) {
				tmp_endpoint->service_id = 0;
				break;
			}
		}

		if (tepid == ENDPOINT0)
			return;

		endpoint->service_id = service_id;
		endpoint->max_txqdepth = tmp_endpoint->max_txqdepth;
		endpoint->ep_callbacks = tmp_endpoint->ep_callbacks;
		endpoint->ul_pipeid = tmp_endpoint->ul_pipeid;
		endpoint->dl_pipeid = tmp_endpoint->dl_pipeid;
		endpoint->max_msglen = max_msglen;
		target->conn_rsp_epid = epid;
		complete(&target->cmd_wait);
	} else {
		target->conn_rsp_epid = ENDPOINT_UNUSED;
	}
}

static int htc_config_pipe_credits(struct htc_target *target)
{
	struct sk_buff *skb;
	struct htc_config_pipe_msg *cp_msg;
	int ret, time_left;

	skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
	if (!skb) {
		dev_err(target->dev, "failed to allocate send buffer\n");
		return -ENOMEM;
	}
	skb_reserve(skb, sizeof(struct htc_frame_hdr));

	cp_msg = (struct htc_config_pipe_msg *)
		skb_put(skb, sizeof(struct htc_config_pipe_msg));

	cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID);
	cp_msg->pipe_id = USB_WLAN_TX_PIPE;
	cp_msg->credits = target->credits;

	target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;

	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
	if (ret)
		goto err;

	time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
	if (!time_left) {
		dev_err(target->dev, "HTC credit config timeout\n");
		return -ETIMEDOUT;
	}

	return 0;
err:
	kfree_skb(skb);
	return -EINVAL;
}

static int htc_setup_complete(struct htc_target *target)
{
	struct sk_buff *skb;
	struct htc_comp_msg *comp_msg;
	int ret = 0, time_left;

	skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC);
	if (!skb) {
		dev_err(target->dev, "failed to allocate send buffer\n");
		return -ENOMEM;
	}
	skb_reserve(skb, sizeof(struct htc_frame_hdr));

	comp_msg = (struct htc_comp_msg *)
		skb_put(skb, sizeof(struct htc_comp_msg));
	comp_msg->msg_id = cpu_to_be16(HTC_MSG_SETUP_COMPLETE_ID);

	target->htc_flags |= HTC_OP_START_WAIT;

	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
	if (ret)
		goto err;

	time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
	if (!time_left) {
		dev_err(target->dev, "HTC start timeout\n");
		return -ETIMEDOUT;
	}

	return 0;

err:
	kfree_skb(skb);
	return -EINVAL;
}

/* HTC APIs */

int htc_init(struct htc_target *target)
{
	int ret;

	ret = htc_config_pipe_credits(target);
	if (ret)
		return ret;

	return htc_setup_complete(target);
}

int htc_connect_service(struct htc_target *target,
		     struct htc_service_connreq *service_connreq,
		     enum htc_endpoint_id *conn_rsp_epid)
{
	struct sk_buff *skb;
	struct htc_endpoint *endpoint;
	struct htc_conn_svc_msg *conn_msg;
	int ret, time_left;

	/* Find an available endpoint */
	endpoint = get_next_avail_ep(target->endpoint);
	if (!endpoint) {
		dev_err(target->dev, "Endpoint is not available for"
			"service %d\n", service_connreq->service_id);
		return -EINVAL;
	}

	endpoint->service_id = service_connreq->service_id;
	endpoint->max_txqdepth = service_connreq->max_send_qdepth;
	endpoint->ul_pipeid = service_to_ulpipe(service_connreq->service_id);
	endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id);
	endpoint->ep_callbacks = service_connreq->ep_callbacks;

	skb = alloc_skb(sizeof(struct htc_conn_svc_msg) +
			    sizeof(struct htc_frame_hdr), GFP_ATOMIC);
	if (!skb) {
		dev_err(target->dev, "Failed to allocate buf to send"
			"service connect req\n");
		return -ENOMEM;
	}

	skb_reserve(skb, sizeof(struct htc_frame_hdr));

	conn_msg = (struct htc_conn_svc_msg *)
			skb_put(skb, sizeof(struct htc_conn_svc_msg));
	conn_msg->service_id = cpu_to_be16(service_connreq->service_id);
	conn_msg->msg_id = cpu_to_be16(HTC_MSG_CONNECT_SERVICE_ID);
	conn_msg->con_flags = cpu_to_be16(service_connreq->con_flags);
	conn_msg->dl_pipeid = endpoint->dl_pipeid;
	conn_msg->ul_pipeid = endpoint->ul_pipeid;

	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
	if (ret)
		goto err;

	time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
	if (!time_left) {
		dev_err(target->dev, "Service connection timeout for: %d\n",
			service_connreq->service_id);
		return -ETIMEDOUT;
	}

	*conn_rsp_epid = target->conn_rsp_epid;
	return 0;
err:
	kfree_skb(skb);
	return ret;
}

int htc_send(struct htc_target *target, struct sk_buff *skb,
	     enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl)
{
	return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl);
}

void htc_stop(struct htc_target *target)
{
	enum htc_endpoint_id epid;
	struct htc_endpoint *endpoint;

	for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
		endpoint = &target->endpoint[epid];
		if (endpoint->service_id != 0)
			target->hif->stop(target->hif_dev, endpoint->ul_pipeid);
	}
}

void htc_start(struct htc_target *target)
{
	enum htc_endpoint_id epid;
	struct htc_endpoint *endpoint;

	for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
		endpoint = &target->endpoint[epid];
		if (endpoint->service_id != 0)
			target->hif->start(target->hif_dev,
					   endpoint->ul_pipeid);
	}
}

void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
			       struct sk_buff *skb, bool txok)
{
	struct htc_endpoint *endpoint;
	struct htc_frame_hdr *htc_hdr = NULL;

	if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) {
		complete(&htc_handle->cmd_wait);
		htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS;
		goto ret;
	}

	if (htc_handle->htc_flags & HTC_OP_START_WAIT) {
		complete(&htc_handle->cmd_wait);
		htc_handle->htc_flags &= ~HTC_OP_START_WAIT;
		goto ret;
	}

	if (skb) {
		htc_hdr = (struct htc_frame_hdr *) skb->data;
		endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id];
		skb_pull(skb, sizeof(struct htc_frame_hdr));

		if (endpoint->ep_callbacks.tx) {
			endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
						  skb, htc_hdr->endpoint_id,
						  txok);
		}
	}

	return;
ret:
	/* HTC-generated packets are freed here. */
	if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0)
		dev_kfree_skb_any(skb);
	else
		kfree_skb(skb);
}

/*
 * HTC Messages are handled directly here and the obtained SKB
 * is freed.
 *
 * Sevice messages (Data, WMI) passed to the corresponding
 * endpoint RX handlers, which have to free the SKB.
 */
void ath9k_htc_rx_msg(struct htc_target *htc_handle,
		      struct sk_buff *skb, u32 len, u8 pipe_id)
{
	struct htc_frame_hdr *htc_hdr;
	enum htc_endpoint_id epid;
	struct htc_endpoint *endpoint;
	__be16 *msg_id;

	if (!htc_handle || !skb)
		return;

	htc_hdr = (struct htc_frame_hdr *) skb->data;
	epid = htc_hdr->endpoint_id;

	if (epid >= ENDPOINT_MAX) {
		if (pipe_id != USB_REG_IN_PIPE)
			dev_kfree_skb_any(skb);
		else
			kfree_skb(skb);
		return;
	}

	if (epid == ENDPOINT0) {

		/* Handle trailer */
		if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
			if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
				/* Move past the Watchdog pattern */
				htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
		}

		/* Get the message ID */
		msg_id = (__be16 *) ((void *) htc_hdr +
				     sizeof(struct htc_frame_hdr));

		/* Now process HTC messages */
		switch (be16_to_cpu(*msg_id)) {
		case HTC_MSG_READY_ID:
			htc_process_target_rdy(htc_handle, htc_hdr);
			break;
		case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
			htc_process_conn_rsp(htc_handle, htc_hdr);
			break;
		default:
			break;
		}

		kfree_skb(skb);

	} else {
		if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER)
			skb_trim(skb, len - htc_hdr->control[0]);

		skb_pull(skb, sizeof(struct htc_frame_hdr));

		endpoint = &htc_handle->endpoint[epid];
		if (endpoint->ep_callbacks.rx)
			endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv,
						  skb, epid);
	}
}

struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
				      struct ath9k_htc_hif *hif,
				      struct device *dev)
{
	struct htc_endpoint *endpoint;
	struct htc_target *target;

	target = kzalloc(sizeof(struct htc_target), GFP_KERNEL);
	if (!target) {
		printk(KERN_ERR "Unable to allocate memory for"
			"target device\n");
		return NULL;
	}

	init_completion(&target->target_wait);
	init_completion(&target->cmd_wait);

	target->hif = hif;
	target->hif_dev = hif_handle;
	target->dev = dev;

	/* Assign control endpoint pipe IDs */
	endpoint = &target->endpoint[ENDPOINT0];
	endpoint->ul_pipeid = hif->control_ul_pipe;
	endpoint->dl_pipeid = hif->control_dl_pipe;

	atomic_set(&target->tgt_ready, 0);

	return target;
}

void ath9k_htc_hw_free(struct htc_target *htc)
{
	kfree(htc);
}

int ath9k_htc_hw_init(struct htc_target *target,
		      struct device *dev, u16 devid,
		      char *product, u32 drv_info)
{
	if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) {
		printk(KERN_ERR "Failed to initialize the device\n");
		return -ENODEV;
	}

	return 0;
}

void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug)
{
	if (target)
		ath9k_htc_disconnect_device(target, hot_unplug);
}
