Exemplo n.º 1
0
static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
{
	u32 total = 0;
	int i;

	

	wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));

	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
		     "drv_rx_counter = %d, tx_results_counter = %d)",
		     status->intr,
		     status->fw_rx_counter,
		     status->drv_rx_counter,
		     status->tx_results_counter);

	
	for (i = 0; i < NUM_TX_QUEUES; i++) {
		u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i];
		wl->tx_blocks_freed[i] = status->tx_released_blks[i];
		wl->tx_blocks_available += cnt;
		total += cnt;
	}

	
	if (total && !skb_queue_empty(&wl->tx_queue))
		schedule_work(&wl->tx_work);

	
	wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
}
Exemplo n.º 2
0
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
{
	struct acx_header *acx = buf;
	int ret;

	wl1271_debug(DEBUG_CMD, "cmd interrogate");

	acx->id = id;

	
	acx->len = len - sizeof(*acx);

	ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
	if (ret < 0) {
		wl1271_error("INTERROGATE command failed");
		goto out;
	}

	
	wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len);

	acx = buf;
	if (acx->cmd.status != CMD_STATUS_SUCCESS)
		wl1271_error("INTERROGATE command error: %d",
			     acx->cmd.status);

out:
	return ret;
}
Exemplo n.º 3
0
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
{
	int ret;

	wl1271_debug(DEBUG_CMD, "cmd test");

	ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len);

	if (ret < 0) {
		wl1271_warning("TEST command failed");
		return ret;
	}

	if (answer) {
		struct wl1271_command *cmd_answer;

		
		wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);

		cmd_answer = buf;

		if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
			wl1271_error("TEST command answer error: %d",
				     cmd_answer->header.status);
	}

	return 0;
}
Exemplo n.º 4
0
/**
 * send test command to firmware
 *
 * @wl: wl struct
 * @buf: buffer containing the command, with all headers, must work with dma
 * @len: length of the buffer
 * @answer: is answer needed
 */
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
{
	int ret;

	wl1271_debug(DEBUG_CMD, "cmd test");

	ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len);

	if (ret < 0) {
		wl1271_warning("TEST command failed");
		return ret;
	}

	if (answer) {
		struct wl1271_command *cmd_answer;

		/*
		 * The test command got in, we can read the answer.
		 * The answer would be a wl1271_command, where the
		 * parameter array contains the actual answer.
		 */
		wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);

		cmd_answer = buf;

		if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
			wl1271_error("TEST command answer error: %d",
				     cmd_answer->header.status);
	}

	return 0;
}
Exemplo n.º 5
0
static void wl1271_boot_fw_version(struct wl1271 *wl)
{
    struct wl1271_static_data static_data;

    wl1271_spi_mem_read(wl, wl->cmd_box_addr,
                        &static_data, sizeof(static_data));

    strncpy(wl->chip.fw_ver, static_data.fw_version,
            sizeof(wl->chip.fw_ver));

    /* make sure the string is NULL-terminated */
    wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
}
Exemplo n.º 6
0
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
			   size_t len)
{
	struct cmd_read_write_memory *cmd;
	int ret = 0;

	wl1271_debug(DEBUG_CMD, "cmd read memory");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd) {
		ret = -ENOMEM;
		goto out;
	}

	WARN_ON(len > MAX_READ_SIZE);
	len = min_t(size_t, len, MAX_READ_SIZE);

	cmd->addr = addr;
	cmd->size = len;

	ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
	if (ret < 0) {
		wl1271_error("read memory command failed: %d", ret);
		goto out;
	}

	
	wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));

	if (cmd->header.status != CMD_STATUS_SUCCESS)
		wl1271_error("error in read command result: %d",
			     cmd->header.status);

	memcpy(answer, cmd->value, len);

out:
	kfree(cmd);
	return ret;
}
static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
{
	u32 total = 0;
	int i;

	/*
	 * FIXME: Reading the FW status directly from the registers seems to
	 * be the right thing to do, but it doesn't work.  And in the
	 * reference driver, there is a workaround called
	 * USE_SDIO_24M_WORKAROUND, which reads the status from memory
	 * instead, so we do the same here.
	 */

	wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));

	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
		     "drv_rx_counter = %d, tx_results_counter = %d)",
		     status->intr,
		     status->fw_rx_counter,
		     status->drv_rx_counter,
		     status->tx_results_counter);

	/* update number of available TX blocks */
	for (i = 0; i < NUM_TX_QUEUES; i++) {
		u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i];
		wl->tx_blocks_freed[i] = status->tx_released_blks[i];
		wl->tx_blocks_available += cnt;
		total += cnt;
	}

	/* if more blocks are available now, schedule some tx work */
	if (total && !skb_queue_empty(&wl->tx_queue))
		schedule_work(&wl->tx_work);

	/* update the host-chipset time offset */
	wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
}
Exemplo n.º 8
0
int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
{
	struct event_mailbox mbox;
	int ret;

	wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);

	if (mbox_num > 1)
		return -EINVAL;

	/* first we read the mbox descriptor */
	wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
			    sizeof(struct event_mailbox));

	/* process the descriptor */
	ret = wl1271_event_process(wl, &mbox);
	if (ret < 0)
		return ret;

	/* then we let the firmware know it can go on...*/
	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);

	return 0;
}
Exemplo n.º 9
0
/* Called upon reception of a TX complete interrupt */
void wl1271_tx_complete(struct wl1271 *wl, u32 count)
{
	struct wl1271_acx_mem_map *memmap =
		(struct wl1271_acx_mem_map *)wl->target_mem_map;
	u32 i;

	wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);

	/* read the tx results from the chipset */
	wl1271_spi_mem_read(wl, memmap->tx_result,
			    wl->tx_res_if, sizeof(*wl->tx_res_if));

	/* verify that the result buffer is not getting overrun */
	if (count > TX_HW_RESULT_QUEUE_LEN) {
		wl1271_warning("TX result overflow from chipset: %d", count);
		count = TX_HW_RESULT_QUEUE_LEN;
	}

	/* process the results */
	for (i = 0; i < count; i++) {
		struct wl1271_tx_hw_res_descr *result;
		u8 offset = wl->tx_results_count & TX_HW_RESULT_QUEUE_LEN_MASK;

		/* process the packet */
		result =  &(wl->tx_res_if->tx_results_queue[offset]);
		wl1271_tx_complete_packet(wl, result);

		wl->tx_results_count++;
	}

	/* write host counter to chipset (to ack) */
	wl1271_mem_write32(wl, memmap->tx_result +
			   offsetof(struct wl1271_tx_hw_res_if,
				    tx_result_host_counter),
			   wl->tx_res_if->tx_result_fw_counter);
}
Exemplo n.º 10
0
int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
{
	struct event_mailbox mbox;
	int ret;

	wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);

	if (mbox_num > 1)
		return -EINVAL;

	
	wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
			    sizeof(struct event_mailbox));

	
	ret = wl1271_event_process(wl, &mbox);
	if (ret < 0)
		return ret;

	
	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);

	return 0;
}
Exemplo n.º 11
0
int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
		    u8 active_scan, u8 high_prio, u8 num_channels,
		    u8 probe_requests)
{

	struct wl1271_cmd_trigger_scan_to *trigger = NULL;
	struct wl1271_cmd_scan *params = NULL;
	int i, ret;
	u16 scan_options = 0;

	if (wl->scanning)
		return -EINVAL;

	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params)
		return -ENOMEM;

	params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
	params->params.rx_filter_options =
		cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);

	if (!active_scan)
		scan_options |= WL1271_SCAN_OPT_PASSIVE;
	if (high_prio)
		scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH;
	params->params.scan_options = scan_options;

	params->params.num_channels = num_channels;
	params->params.num_probe_requests = probe_requests;
	params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS);
	params->params.tid_trigger = 0;
	params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;

	for (i = 0; i < num_channels; i++) {
		params->channels[i].min_duration =
			cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
		params->channels[i].max_duration =
			cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
		memset(&params->channels[i].bssid_lsb, 0xff, 4);
		memset(&params->channels[i].bssid_msb, 0xff, 2);
		params->channels[i].early_termination = 0;
		params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR;
		params->channels[i].channel = i + 1;
	}

	if (len && ssid) {
		params->params.ssid_len = len;
		memcpy(params->params.ssid, ssid, len);
	}

	ret = wl1271_cmd_build_probe_req(wl, ssid, len);
	if (ret < 0) {
		wl1271_error("PROBE request template failed");
		goto out;
	}

	trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
	if (!trigger) {
		ret = -ENOMEM;
		goto out;
	}

	
	trigger->timeout = 0;

	ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
			      sizeof(*trigger));
	if (ret < 0) {
		wl1271_error("trigger scan to failed for hw scan");
		goto out;
	}

	wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));

	wl->scanning = true;

	ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
	if (ret < 0) {
		wl1271_error("SCAN failed");
		goto out;
	}

	wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));

	if (params->header.status != CMD_STATUS_SUCCESS) {
		wl1271_error("Scan command error: %d",
			     params->header.status);
		wl->scanning = false;
		ret = -EIO;
		goto out;
	}

out:
	kfree(params);
	return ret;
}