/* WMI Event handler register API */
int wmi_unified_get_event_handler_ix(wmi_unified_t wmi_handle,
					WMI_EVT_ID event_id)
{
	u_int32_t idx = 0;
	for (idx = 0; (idx < wmi_handle->max_event_idx &&
		idx < WMI_UNIFIED_MAX_EVENT); ++idx) {
		if (wmi_handle->event_id[idx] == event_id &&
			wmi_handle->event_handler[idx] != NULL ) {
			return idx;
		}
	}
	return  -1;
}

int wmi_unified_register_event_handler(wmi_unified_t wmi_handle,
                                       WMI_EVT_ID event_id,
				       wmi_unified_event_handler handler_func)
{
	u_int32_t idx=0;

    if ( wmi_unified_get_event_handler_ix( wmi_handle, event_id) != -1) {
	printk("%s : event handler already registered 0x%x \n",
		__func__, event_id);
        return -1;
    }
    if ( wmi_handle->max_event_idx == WMI_UNIFIED_MAX_EVENT ) {
	printk("%s : no more event handlers 0x%x \n",
                __func__, event_id);
        return -1;
    }
    idx=wmi_handle->max_event_idx;
    wmi_handle->event_handler[idx] = handler_func;
    wmi_handle->event_id[idx] = event_id;
    wmi_handle->max_event_idx++;

    return 0;
}

int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,
                                       WMI_EVT_ID event_id)
{
    u_int32_t idx=0;
    if ( (idx = wmi_unified_get_event_handler_ix( wmi_handle, event_id)) == -1) {
        printk("%s : event handler is not registered: event id 0x%x \n",
                __func__, event_id);
        return -1;
    }
    wmi_handle->event_handler[idx] = NULL;
    wmi_handle->event_id[idx] = 0;
    --wmi_handle->max_event_idx;
    wmi_handle->event_handler[idx] = wmi_handle->event_handler[wmi_handle->max_event_idx];
    wmi_handle->event_id[idx]  = wmi_handle->event_id[wmi_handle->max_event_idx] ;
    return 0;
}

#if 0 /* currently not used */
static int wmi_unified_event_rx(struct wmi_unified *wmi_handle,
				wmi_buf_t evt_buf)
{
	u_int32_t id;
	u_int8_t *event;
	u_int16_t len;
	int status = -1;
	u_int32_t idx = 0;

	ASSERT(evt_buf != NULL);

	id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);

	if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
		goto end;

	idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
	if (idx == -1) {
		pr_err("%s : event handler is not registered: event id: 0x%x\n",
		       __func__, id);
		goto end;
	}

	event = adf_nbuf_data(evt_buf);
	len = adf_nbuf_len(evt_buf);

	/* Call the WMI registered event handler */
	status = wmi_handle->event_handler[idx](wmi_handle->scn_handle,
						event, len);

end:
	adf_nbuf_free(evt_buf);
	return status;
}
int wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle,
                                       WMI_EVT_ID event_id)
{
    u_int32_t idx=0;
    if ( (idx = wmi_unified_get_event_handler_ix( wmi_handle, event_id)) == -1) {
        printk("%s : event handler is not registered: event id 0x%x \n",
                __func__, event_id);
        return -1;
    }
    wmi_handle->event_handler[idx] = NULL;
    wmi_handle->event_id[idx] = 0;
    --wmi_handle->max_event_idx;
    wmi_handle->event_handler[idx] = wmi_handle->event_handler[wmi_handle->max_event_idx];
    wmi_handle->event_id[idx]  = wmi_handle->event_id[wmi_handle->max_event_idx] ;
    return 0;
}
Exemple #3
0
int wmi_unified_register_event_handler(wmi_unified_t wmi_handle,
				       WMI_EVT_ID event_id,
				       wmi_unified_event_handler handler_func)
{
	uint32_t idx = 0;

	if (wmi_unified_get_event_handler_ix(wmi_handle, event_id) != -1) {
		printk("%s : event handler already registered 0x%x \n",
		       __func__, event_id);
		return -1;
	}
	if (wmi_handle->max_event_idx == WMI_UNIFIED_MAX_EVENT) {
		printk("%s : no more event handlers 0x%x \n",
		       __func__, event_id);
		return -1;
	}
	idx = wmi_handle->max_event_idx;
	wmi_handle->event_handler[idx] = handler_func;
	wmi_handle->event_id[idx] = event_id;
	wmi_handle->max_event_idx++;
	return 0;
}
void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
{
	u_int32_t id;
	u_int8_t *data;
	u_int32_t len;
	void *wmi_cmd_struct_ptr = NULL;
	int tlv_ok_status = 0;

	id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);

	if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
		goto end;

	data = adf_nbuf_data(evt_buf);
	len = adf_nbuf_len(evt_buf);

	/* Validate and pad(if necessary) the TLVs */
	tlv_ok_status = wmitlv_check_and_pad_event_tlvs(wmi_handle->scn_handle,
							data, len, id,
							&wmi_cmd_struct_ptr);
	if (tlv_ok_status != 0) {
			pr_err("%s: Error: id=0x%d, wmitlv_check_and_pad_tlvs ret=%d\n",
				__func__, id, tlv_ok_status);
			goto end;
	}

#ifdef FEATURE_WLAN_D0WOW
	if (wmi_get_d0wow_flag(wmi_handle))
		pr_debug("%s: WMI event ID is 0x%x\n", __func__, id);
#endif

	if (id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) {
		u_int32_t idx = 0;

		idx = wmi_unified_get_event_handler_ix(wmi_handle, id) ;
		if (idx == -1) {
			pr_err("%s : event handler is not registered: event id 0x%x\n",
			       __func__, id);
			goto end;
		}

#ifdef WMI_INTERFACE_EVENT_LOGGING
		adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock);
		/* Exclude 4 bytes of TLV header */
		WMI_EVENT_RECORD(id, ((u_int8_t *)data + 4));
		adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock);
#endif
		/* Call the WMI registered event handler */
		wmi_handle->event_handler[idx](wmi_handle->scn_handle,
					       wmi_cmd_struct_ptr, len);
		goto end;
	}

	switch (id) {
	default:
		pr_info("%s: Unhandled WMI event %d\n", __func__, id);
		break;
	case WMI_SERVICE_READY_EVENTID:
		pr_info("%s: WMI UNIFIED SERVICE READY event\n", __func__);
		wma_rx_service_ready_event(wmi_handle->scn_handle,
					   wmi_cmd_struct_ptr);
		break;
	case WMI_READY_EVENTID:
		pr_info("%s:  WMI UNIFIED READY event\n", __func__);
		wma_rx_ready_event(wmi_handle->scn_handle, wmi_cmd_struct_ptr);
		break;
	}
end:
	wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
	adf_nbuf_free(evt_buf);
}
/*
 * Temporarily added to support older WMI events. We should move all events to unified
 * when the target is ready to support it.
 */
void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
{
	struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx;
	wmi_buf_t evt_buf;
	u_int32_t len;
	void *wmi_cmd_struct_ptr = NULL;
	u_int32_t idx = 0;
	int tlv_ok_status = 0;

#if  defined(WMI_INTERFACE_EVENT_LOGGING) || !defined(QCA_CONFIG_SMP)
	u_int32_t id;
	u_int8_t *data;
#endif

	evt_buf = (wmi_buf_t) htc_packet->pPktContext;
	id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
	/* TX_PAUSE EVENT should be handled with tasklet context */
	if ((WMI_TX_PAUSE_EVENTID == id) ||
		(WMI_WOW_WAKEUP_HOST_EVENTID == id)) {
		if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
			return;

		data = adf_nbuf_data(evt_buf);
		len = adf_nbuf_len(evt_buf);
		tlv_ok_status = wmitlv_check_and_pad_event_tlvs(
					wmi_handle->scn_handle,
					data, len, id,
					&wmi_cmd_struct_ptr);
		if (tlv_ok_status != 0) {
			if (tlv_ok_status == 1) {
				wmi_cmd_struct_ptr = data;
			} else {
				return;
			}
		}

		idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
		if (idx == -1) {
			wmitlv_free_allocated_event_tlvs(id,
				&wmi_cmd_struct_ptr);
			adf_nbuf_free(evt_buf);
			return;
		}
		wmi_handle->event_handler[idx](wmi_handle->scn_handle,
			       wmi_cmd_struct_ptr, len);
		wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
		adf_nbuf_free(evt_buf);
		return;
	}

#ifdef WMI_INTERFACE_EVENT_LOGGING
	id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
	data = adf_nbuf_data(evt_buf);

	adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock);
	/* Exclude 4 bytes of TLV header */
	WMI_RX_EVENT_RECORD(id, ((u_int8_t *)data + 4));
	adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock);
#endif
	adf_os_spin_lock_bh(&wmi_handle->eventq_lock);
	adf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf);
	adf_os_spin_unlock_bh(&wmi_handle->eventq_lock);
	schedule_work(&wmi_handle->rx_event_work);
}
Exemple #6
0
void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
{
	uint32_t id;
	uint8_t *data;
	uint32_t len;
	void *wmi_cmd_struct_ptr = NULL;
	int tlv_ok_status = 0;

	id = WMI_GET_FIELD(cdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);

	if (cdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
		goto end;

	data = cdf_nbuf_data(evt_buf);
	len = cdf_nbuf_len(evt_buf);

	/* Validate and pad(if necessary) the TLVs */
	tlv_ok_status = wmitlv_check_and_pad_event_tlvs(wmi_handle->scn_handle,
							data, len, id,
							&wmi_cmd_struct_ptr);
	if (tlv_ok_status != 0) {
		pr_err("%s: Error: id=0x%d, wmitlv_check_and_pad_tlvs ret=%d\n",
		       __func__, id, tlv_ok_status);
		goto end;
	}

	if ((id >= WMI_EVT_GRP_START_ID(WMI_GRP_START)) &&
		/* WMI_SERVICE_READY_EXT_EVENTID is supposed to be part of the
		 * WMI_GRP_START group. Since the group is out of space, FW
		 * has accomodated this in WMI_GRP_VDEV.
		 * WMI_SERVICE_READY_EXT_EVENTID does not have any specific
		 * event handler registered. So, we do not want to go through
		 * the WMI registered event handler path for this event.
		 */
		(id != WMI_SERVICE_READY_EXT_EVENTID)) {
		uint32_t idx = 0;

		idx = wmi_unified_get_event_handler_ix(wmi_handle, id);
		if (idx == -1) {
			pr_err
				("%s : event handler is not registered: event id 0x%x\n",
				__func__, id);
			goto end;
		}
#ifdef WMI_INTERFACE_EVENT_LOGGING
		cdf_spin_lock_bh(&wmi_handle->wmi_record_lock);
		/* Exclude 4 bytes of TLV header */
		if (id == WMI_MGMT_TX_COMPLETION_EVENTID) {
			WMI_MGMT_EVENT_RECORD(id, ((uint8_t *) data + 4));
		} else {
			WMI_EVENT_RECORD(id, ((uint8_t *) data + 4));
		}
		cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock);
#endif
		/* Call the WMI registered event handler */
		wmi_handle->event_handler[idx] (wmi_handle->scn_handle,
						wmi_cmd_struct_ptr, len);
		goto end;
	}

	switch (id) {
	default:
		pr_info("%s: Unhandled WMI event %d\n", __func__, id);
		break;
	case WMI_SERVICE_READY_EVENTID:
		pr_info("%s: WMI UNIFIED SERVICE READY event\n", __func__);
		wma_rx_service_ready_event(wmi_handle->scn_handle,
					   wmi_cmd_struct_ptr);
		break;
	case WMI_SERVICE_READY_EXT_EVENTID:
		WMA_LOGA("%s: WMI UNIFIED SERVICE READY Extended event",
			__func__);
		wma_rx_service_ready_ext_event(wmi_handle->scn_handle,
						wmi_cmd_struct_ptr);
		break;
	case WMI_READY_EVENTID:
		pr_info("%s:  WMI UNIFIED READY event\n", __func__);
		wma_rx_ready_event(wmi_handle->scn_handle, wmi_cmd_struct_ptr);
		break;
	}
end:
	wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
	cdf_nbuf_free(evt_buf);
}