Exemplo n.º 1
0
struct fm_timer *fm_timer_create(const fm_s8 *name)
{
	struct fm_timer *tmp;
	struct timer_list *timerlist;

	tmp = fm_zalloc(sizeof(struct fm_timer));
	if (!tmp) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_timer) -ENOMEM\n");
		return NULL;
	}

	timerlist = fm_zalloc(sizeof(struct timer_list));
	if (!timerlist) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct timer_list) -ENOMEM\n");
		fm_free(tmp);
		return NULL;
	}

	init_timer(timerlist);

	fm_memcpy(tmp->name, name, (strlen(name) > FM_NAME_MAX) ? (FM_NAME_MAX) : (strlen(name)));
	tmp->priv = timerlist;
	tmp->ref = 0;
	tmp->init = fm_timer_init;
	tmp->start = fm_timer_start;
	tmp->stop = fm_timer_stop;
	tmp->update = fm_timer_update;
	tmp->control = fm_timer_control;

	return tmp;
}
Exemplo n.º 2
0
struct fm_flag_event *fm_flag_event_create(const fm_s8 *name)
{
	struct fm_flag_event *tmp;
	wait_queue_head_t *wq;

	tmp = fm_zalloc(sizeof(struct fm_flag_event));
	if (!tmp) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_event) -ENOMEM\n");
		return NULL;
	}

	wq = fm_zalloc(sizeof(wait_queue_head_t));
	if (!wq) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(wait_queue_head_t) -ENOMEM\n");
		fm_free(tmp);
		return NULL;
	}

	fm_memcpy(tmp->name, name, (strlen(name) > FM_NAME_MAX) ? (FM_NAME_MAX) : (strlen(name)));
	tmp->priv = wq;
	init_waitqueue_head(wq);
	tmp->ref = 0;

	tmp->send = fm_event_send;
	tmp->wait = fm_event_wait;
	tmp->wait_timeout = fm_event_wait_timeout;
	tmp->clr = fm_event_clr;
	tmp->get = fm_event_get;
	tmp->rst = fm_event_rst;

	tmp->rst(tmp);		/* set flag to 0x00000000 */

	return tmp;
}
Exemplo n.º 3
0
struct fm_lock *fm_spin_lock_create(const fm_s8 *name)
{
	struct fm_lock *tmp;
	spinlock_t *spin_lock;

	tmp = fm_zalloc(sizeof(struct fm_lock));
	if (!tmp) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n");
		return NULL;
	}

	spin_lock = fm_zalloc(sizeof(spinlock_t));
	if (!spin_lock) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(spinlock_t) -ENOMEM\n");
		fm_free(tmp);
		return NULL;
	}

	tmp->priv = spin_lock;
	spin_lock_init(spin_lock);
	tmp->ref = 0;
	fm_memcpy(tmp->name, name, (strlen(name) > FM_NAME_MAX) ? (FM_NAME_MAX) : (strlen(name)));

	tmp->lock = fm_spin_lock_lock;
	tmp->unlock = fm_spin_lock_unlock;

	return tmp;
}
Exemplo n.º 4
0
struct fm_lock *fm_lock_create(const fm_s8 *name)
{
	struct fm_lock *tmp;
	struct semaphore *mutex;

	tmp = fm_zalloc(sizeof(struct fm_lock));
	if (!tmp) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_lock) -ENOMEM\n");
		return NULL;
	}

	mutex = fm_zalloc(sizeof(struct semaphore));
	if (!mutex) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct semaphore) -ENOMEM\n");
		fm_free(tmp);
		return NULL;
	}

	tmp->priv = mutex;
	sema_init(mutex, 1);
	tmp->ref = 0;
	fm_memcpy(tmp->name, name, (strlen(name) > FM_NAME_MAX) ? (FM_NAME_MAX) : (strlen(name)));

	tmp->lock = fm_lock_lock;
	tmp->trylock = fm_lock_try;
	tmp->unlock = fm_lock_unlock;

	return tmp;
}
Exemplo n.º 5
0
fm_s32 fm_trace_out(struct fm_trace_fifo_t *thiz, struct fm_trace_t *dst_tra)
{
	if (thiz->len > 0) {
		if (dst_tra) {
			fm_memcpy(dst_tra, &(thiz->trace[thiz->out]), sizeof(struct fm_trace_t));
			fm_memset(&(thiz->trace[thiz->out]), 0, sizeof(struct fm_trace_t));
		}
		thiz->out = (thiz->out + 1) % thiz->size;
		thiz->len--;
		/* WCN_DBG(FM_DBG | RDSC, "del a tra[len=%d]\n", thiz->len); */
	} else {
		WCN_DBG(FM_WAR | RDSC, "tra buf is empty\n");
	}

	return 0;
}
Exemplo n.º 6
0
fm_s32 fm_fifo_out(struct fm_fifo *thiz, void *item)
{
	if (thiz->len > 0) {
		if (item) {
			fm_memcpy(item, (thiz->obj.priv + (thiz->item_size * thiz->out)), thiz->item_size);
			fm_memset((thiz->obj.priv + (thiz->item_size * thiz->out)), 0, thiz->item_size);
		}
		thiz->out = (thiz->out + 1) % thiz->size;
		thiz->len--;
		/* WCN_DBG(FM_DBG | MAIN, "del an item[len=%d]\n", thiz->len); */
	} else {
		WCN_DBG(FM_WAR | MAIN, "%s fifo is empty\n", thiz->obj.name);
	}

	return 0;
}
Exemplo n.º 7
0
fm_s32 fm_fifo_in(struct fm_fifo *thiz, void *item)
{
	FMR_ASSERT(item);

	if (thiz->len < thiz->size) {
		fm_memcpy((thiz->obj.priv + (thiz->item_size * thiz->in)), item, thiz->item_size);
		thiz->in = (thiz->in + 1) % thiz->size;
		thiz->len++;
		/* WCN_DBG(FM_DBG | MAIN, "add a new item[len=%d]\n", thiz->len); */
	} else {
		WCN_DBG(FM_WAR | MAIN, "%s fifo is full\n", thiz->obj.name);
		return -FM_ENOMEM;
	}

	return 0;
}
Exemplo n.º 8
0
fm_s32 fm_trace_in(struct fm_trace_fifo_t *thiz, struct fm_trace_t *new_tra)
{
	FMR_ASSERT(new_tra);

	if (thiz->len < thiz->size) {
		fm_memcpy(&(thiz->trace[thiz->in]), new_tra, sizeof(struct fm_trace_t));
		thiz->trace[thiz->in].time = jiffies;
		thiz->in = (thiz->in + 1) % thiz->size;
		thiz->len++;
		/* WCN_DBG(FM_DBG | RDSC, "add a new tra[len=%d]\n", thiz->len); */
	} else {
		WCN_DBG(FM_WAR | RDSC, "tra buf is full\n");
		return -FM_ENOMEM;
	}

	return 0;
}
Exemplo n.º 9
0
struct fm_workthread* fm_workthread_create(const fm_s8* name) 
{
    struct fm_workthread *my_thread;
    struct workqueue_struct *sys_thread;

    if (!(my_thread = fm_zalloc(sizeof(struct fm_workthread)))) {
        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_workthread) -ENOMEM\n");
        return NULL;
    }

    sys_thread = create_singlethread_workqueue(name);

    fm_memcpy(my_thread->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
    my_thread->priv = sys_thread;
    my_thread->add_work = fm_workthread_add_work;

    return my_thread;
}
Exemplo n.º 10
0
struct fm_fifo *fm_fifo_init(struct fm_fifo *fifo, void *buf, const fm_s8 *name, fm_s32 item_size, fm_s32 item_num)
{
	fm_memcpy(fifo->obj.name, name, 20);
	fifo->size = item_num;
	fifo->in = 0;
	fifo->out = 0;
	fifo->len = 0;
	fifo->item_size = item_size;
	fifo->obj.priv = buf;

	fifo->input = fm_fifo_in;
	fifo->output = fm_fifo_out;
	fifo->is_full = fm_fifo_is_full;
	fifo->is_empty = fm_fifo_is_empty;
	fifo->get_total_len = fm_fifo_get_total_len;
	fifo->get_valid_len = fm_fifo_get_valid_len;
	fifo->reset = fm_fifo_reset;

	WCN_DBG(FM_NTC | LINK, "%s inited\n", fifo->obj.name);

	return fifo;
}
Exemplo n.º 11
0
struct fm_work* fm_work_create(const fm_s8 *name) 
{
    struct fm_work *my_work;
    struct work_struct *sys_work;

    if (!(my_work = fm_zalloc(sizeof(struct fm_work)))) {
        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_work) -ENOMEM\n");
        return NULL;
    }

    if (!(sys_work = fm_zalloc(sizeof(struct work_struct)))) {
        WCN_DBG(FM_ALT | MAIN, "fm_zalloc(struct work_struct) -ENOMEM\n");
        fm_free(my_work);
        return NULL;
    }

    fm_memcpy(my_work->name, name, (strlen(name)>FM_NAME_MAX)?(FM_NAME_MAX):(strlen(name)));
    my_work->priv = sys_work;
    my_work->init = fm_work_init;

    return my_work;
}
Exemplo n.º 12
0
struct fm_trace_fifo_t *fm_trace_fifo_create(const fm_s8 *name)
{
	struct fm_trace_fifo_t *tmp;

	if (!(tmp = fm_zalloc(sizeof(struct fm_trace_fifo_t)))) {
		WCN_DBG(FM_ALT | MAIN, "fm_zalloc(fm_trace_fifo) -ENOMEM\n");
		return NULL;
	}

	fm_memcpy(tmp->name, name, (strlen(name)+1));
	tmp->size = FM_TRACE_FIFO_SIZE;
	tmp->in = 0;
	tmp->out = 0;
	tmp->len = 0;
	tmp->trace_in = fm_trace_in;
	tmp->trace_out = fm_trace_out;
	tmp->is_full = fm_trace_is_full;
	tmp->is_empty = fm_trace_is_empty;

	WCN_DBG(FM_NTC | LINK, "%s created\n", tmp->name);

	return tmp;
}
Exemplo n.º 13
0
fm_s32 fm_event_parser(fm_s32(*rds_parser) (struct rds_rx_t *, fm_s32))
{
	fm_s32 len;
	fm_s32 i = 0;
	fm_u8 opcode = 0;
	fm_u16 length = 0;
	fm_u8 ch;
	fm_u8 rx_buf[RX_BUF_SIZE + 10] = { 0 };	/* the 10 bytes are protect gaps */
	static volatile fm_task_parser_state state = FM_TASK_RX_PARSER_PKT_TYPE;
	struct fm_trace_t trace;
	struct task_struct *task = current;

	len = mtk_wcn_stp_receive_data(rx_buf, RX_BUF_SIZE, FM_TASK_INDX);
	WCN_DBG(FM_DBG | LINK, "[len=%d],[CMD=0x%02x 0x%02x 0x%02x 0x%02x]\n", len, rx_buf[0],
		rx_buf[1], rx_buf[2], rx_buf[3]);

	while (i < len) {
		ch = rx_buf[i];

		switch (state) {
		case FM_TASK_RX_PARSER_PKT_TYPE:

			if (ch == FM_TASK_EVENT_PKT_TYPE) {
				if ((i + 5) < RX_BUF_SIZE) {
					WCN_DBG(FM_DBG | LINK,
						"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
						rx_buf[i], rx_buf[i + 1], rx_buf[i + 2],
						rx_buf[i + 3], rx_buf[i + 4], rx_buf[i + 5]);
				} else {
					WCN_DBG(FM_DBG | LINK, "0x%02x 0x%02x\n", rx_buf[i],
						rx_buf[i + 1]);
				}

				state = FM_TASK_RX_PARSER_OPCODE;
			} else {
				WCN_DBG(FM_ALT | LINK,
					"event pkt type error (rx_buf[%d] = 0x%02x)\n", i, ch);
			}

			i++;
			break;

		case FM_TASK_RX_PARSER_OPCODE:
			i++;
			opcode = ch;
			state = FM_TASK_RX_PARSER_PKT_LEN_1;
			break;

		case FM_TASK_RX_PARSER_PKT_LEN_1:
			i++;
			length = ch;
			state = FM_TASK_RX_PARSER_PKT_LEN_2;
			break;

		case FM_TASK_RX_PARSER_PKT_LEN_2:
			i++;
			length |= (fm_u16) (ch << 0x8);

#ifdef FM_TRACE_ENABLE
			trace.type = FM_TASK_EVENT_PKT_TYPE;
			trace.opcode = opcode;
			trace.len = length;
			trace.tid = (fm_s32) task->pid;
			fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
			fm_memcpy(trace.pkt, &rx_buf[i],
				  (length > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : length);

			if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
				FM_TRACE_OUT(cmd_fifo, NULL);
			}
			FM_TRACE_IN(cmd_fifo, &trace);
#endif
			if (length > 0) {
				state = FM_TASK_RX_PARSER_PKT_PAYLOAD;
			} else if (opcode == CSPI_WRITE_OPCODE) {
				state = FM_TASK_RX_PARSER_PKT_TYPE;
				FM_EVENT_SEND(link_event->ln_event, FLAG_CSPI_WRITE);
			} else {
				state = FM_TASK_RX_PARSER_PKT_TYPE;
				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
			}

			break;

		case FM_TASK_RX_PARSER_PKT_PAYLOAD:

			switch (opcode) {
			case FM_TUNE_OPCODE:

				if ((length == 1) && (rx_buf[i] == 1)) {
					FM_EVENT_SEND(link_event->ln_event, FLAG_TUNE_DONE);
				}

				break;

			case FM_SOFT_MUTE_TUNE_OPCODE:

				if (length >= 2) {
					fm_memcpy(link_event->result.cqi, &rx_buf[i],
						  (length >
						   FM_CQI_BUF_SIZE) ? FM_CQI_BUF_SIZE : length);
					FM_EVENT_SEND(link_event->ln_event, FLAG_SM_TUNE);
				}
				break;

			case FM_SEEK_OPCODE:

				if ((i + 1) < RX_BUF_SIZE) {
					link_event->result.seek_result = rx_buf[i] + (rx_buf[i + 1] << 8);	/* 8760 means 87.60Mhz */
				}

				FM_EVENT_SEND(link_event->ln_event, FLAG_SEEK_DONE);
				break;

			case FM_SCAN_OPCODE:

				/* check if the result data is long enough */
				if ((RX_BUF_SIZE - i) < (sizeof(fm_u16) * FM_SCANTBL_SIZE)) {
					WCN_DBG(FM_ALT | LINK,
						"FM_SCAN_OPCODE err, [tblsize=%d],[bufsize=%d]\n",
						(unsigned int)(sizeof(fm_u16) * FM_SCANTBL_SIZE),
						(unsigned int)(RX_BUF_SIZE - i));
					FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
					return 0;
				} else if ((length >= FM_CQI_BUF_SIZE)
					   && ((RX_BUF_SIZE - i) >= FM_CQI_BUF_SIZE)) {
					fm_memcpy(link_event->result.cqi, &rx_buf[i],
						  FM_CQI_BUF_SIZE);
					FM_EVENT_SEND(link_event->ln_event, FLAG_CQI_DONE);
				} else {
					fm_memcpy(link_event->result.scan_result, &rx_buf[i],
						  sizeof(fm_u16) * FM_SCANTBL_SIZE);
					FM_EVENT_SEND(link_event->ln_event, FLAG_SCAN_DONE);
				}

				break;

			case FSPI_READ_OPCODE:

				if ((i + 1) < RX_BUF_SIZE) {
					link_event->result.fspi_rd =
					    (rx_buf[i] + (rx_buf[i + 1] << 8));
				}

				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
				break;
			case CSPI_READ_OPCODE:
				{
					if ((i + 1) < RX_BUF_SIZE) {
						link_event->result.cspi_rd =
						    (rx_buf[i] + (rx_buf[i + 1] << 8) +
						     (rx_buf[i + 2] << 16) + (rx_buf[i + 3] << 24));
					}

					FM_EVENT_SEND(link_event->ln_event, FLAG_CSPI_READ);
					break;
				}
			case FM_HOST_READ_OPCODE:
				{
					if ((i + 1) < RX_BUF_SIZE) {
						link_event->result.cspi_rd =
						    (rx_buf[i] + (rx_buf[i + 1] << 8) +
						     (rx_buf[i + 2] << 16) + (rx_buf[i + 3] << 24));
					}

					FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
					break;
				}

			case RDS_RX_DATA_OPCODE:

				/* check if the rds data is long enough */
				if ((RX_BUF_SIZE - i) < length) {
					WCN_DBG(FM_ALT | LINK,
						"RDS RX err, [rxlen=%d],[bufsize=%d]\n",
						(fm_s32) length, (RX_BUF_SIZE - i));
					FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
					break;
				}
				/* copy rds data to rds buf */
				fm_memcpy(&link_event->result.rds_rx_result, &rx_buf[i], length);

				/*Handle the RDS data that we get */
				if (rds_parser) {
					rds_parser(&link_event->result.rds_rx_result, length);
				} else {
					WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
				}

				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
				break;

			default:
				FM_EVENT_SEND(link_event->ln_event, (1 << opcode));
				break;
			}

			state = FM_TASK_RX_PARSER_PKT_TYPE;
			i += length;
			break;

		default:
			break;
		}
	}

	return 0;
}
Exemplo n.º 14
0
/*
 * fm_cmd_tx() - send cmd to FM firmware and wait event
 * @buf - send buffer
 * @len - the length of cmd
 * @mask - the event flag mask
 * @	cnt - the retry conter
 * @timeout - timeout per cmd
 * Return 0, if success; error code, if failed
 */
fm_s32 fm_cmd_tx(fm_u8 *buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout,
		 fm_s32(*callback) (struct fm_res_ctx *result))
{
	fm_s32 ret_time = 0;
	struct task_struct *task = current;
	struct fm_trace_t trace;

	if ((NULL == buf) || (len < 0) || (0 == mask)
	    || (cnt > SW_RETRY_CNT_MAX) || (timeout > SW_WAIT_TIMEOUT_MAX)) {
		WCN_DBG(FM_ERR | LINK, "cmd tx, invalid para\n");
		return -FM_EPARA;
	}

	FM_EVENT_CLR(link_event->ln_event, mask);

#ifdef FM_TRACE_ENABLE
	trace.type = buf[0];
	trace.opcode = buf[1];
	trace.len = len - 4;
	trace.tid = (fm_s32) task->pid;
	fm_memset(trace.pkt, 0, FM_TRACE_PKT_SIZE);
	fm_memcpy(trace.pkt, &buf[4],
		  (trace.len > FM_TRACE_PKT_SIZE) ? FM_TRACE_PKT_SIZE : trace.len);
#endif

 sw_retry:

#ifdef FM_TRACE_ENABLE
	if (fm_true == FM_TRACE_FULL(cmd_fifo)) {
		FM_TRACE_OUT(cmd_fifo, NULL);
	}
	FM_TRACE_IN(cmd_fifo, &trace);
#endif

	/* send cmd to FM firmware */
	if ((ret_time = mtk_wcn_stp_send_data(buf, len, FM_TASK_INDX)) <= 0) {
		WCN_DBG(FM_EMG | LINK, "send data over stp failed[%d]\n", ret_time);
		return -FM_ELINK;
	}
	/* wait the response form FM firmware */
	ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, mask, timeout);

	if (!ret_time) {
		if (0 < cnt--) {
			WCN_DBG(FM_WAR | LINK, "wait even timeout, [retry_cnt=%d], pid=%d\n", cnt,
				task->pid);
			fm_print_cmd_fifo();
			fm_print_evt_fifo();
			return -FM_EFW;
			goto sw_retry;	/* retry if timeout and retry cnt > 0 */
		} else {
			WCN_DBG(FM_ALT | LINK, "fatal error, SW retry failed, reset HW\n");
			return -FM_EFW;
		}
	}

	FM_EVENT_CLR(link_event->ln_event, mask);

	if (callback) {
		callback(&link_event->result);
	}

	return 0;
}