static void *sqn_dfs_perf_rx_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	u32 *idx = 0;

	sqn_pr_enter();

	++(*pos);

	if (SEQ_START_TOKEN == v) {
		idx = kmalloc(sizeof(u32), GFP_KERNEL);
		if (!idx) {
			sqn_pr_dbg("failed to alloc seq_file iterator\n");
			goto out;
		}
	} else {
		idx = v;
	}

	*idx = *pos - 1;
	sqn_pr_dbg("idx %u, pos %llu\n", *idx, *pos);

	if (*idx >= SQN_DFS_PERF_STAT_SIZE) {
		/* indicate end of sequence */
		sqn_pr_dbg("end of sequence, idx %u\n", *idx);
		idx = 0;
	}
out:
	sqn_pr_leave();
	return idx;
}
static void *sqn_dfs_perf_rx_seq_start(struct seq_file *seq, loff_t *pos)
{
	u32 *idx = 0;

	sqn_pr_enter();

	if (0 == *pos) {
		sqn_pr_dbg("zero pos\n");
		idx = SEQ_START_TOKEN;
		goto out;
	} else if (SQN_DFS_PERF_STAT_SIZE <= *pos) {
		/* indicate beyond end of file position */
		sqn_pr_dbg("beyond end of file position %llu\n", *pos);
		idx = 0;
		goto out;
	}

	idx = kmalloc(sizeof(u32), GFP_KERNEL);

	if (!idx) {
		sqn_pr_dbg("failed to alloc seq_file iterator\n");
		goto out;
	}

	*idx = *pos;
	sqn_pr_dbg("start pos %u\n", *idx);
out:
	sqn_pr_leave();
	return idx;
}
Example #3
0
static int sqn_handle_mac_addr_tag(struct sdio_func *func, u8 *data, u32 length)
{
	int rv = 0;
	struct sqn_private *priv =
		((struct sqn_sdio_card *)sdio_get_drvdata(func))->priv;

	sqn_pr_enter();

	/*
	 * This tag could contain one or two mac addresses in string
	 * form, delimited by some symbol (space or something else).
	 * Each mac address written as a string has constant length.
	 * Thus we can determine the number of mac addresses by the
	 * length of the tag:
	 *
	 * mac addr length in string form: XX:XX:XX:XX:XX:XX = 17 bytes
	 * tag length: 17 bytes [ + 1 byte + 17 bytes ]
	 */

#define MAC_ADDR_STRING_LEN	17

	/*
	 * If we have only one mac addr we should increment it by one
	 * and use it.
	 * If we have two mac addresses we should use a second one.
	 */

	if (MAC_ADDR_STRING_LEN <= length
		&& length < 2 * MAC_ADDR_STRING_LEN + 1)
	{
		sqn_pr_dbg("single mac address\n");
		/* we have only one mac addr */
		get_mac_addr_from_str(data, length, priv->mac_addr);
		++(priv->mac_addr[ETH_ALEN - 1]);
	}
	else if (2 * MAC_ADDR_STRING_LEN + 1 == length) { /* we have two macs */
		sqn_pr_dbg("two mac addresses, using second\n");
		get_mac_addr_from_str(data + MAC_ADDR_STRING_LEN + 1
			, length - (MAC_ADDR_STRING_LEN + 1), priv->mac_addr);
	}
	else { /* incorrect data length */
		sqn_pr_err("can't get mac address from bootloader"
			" - incorrect mac address length\n");
		rv = -1;
		goto out;
	}

	sqn_pr_info("setting MAC address from bootloader: "
		"%02x:%02x:%02x:%02x:%02x:%02x\n", priv->mac_addr[0]
		, priv->mac_addr[1], priv->mac_addr[2], priv->mac_addr[3]
		, priv->mac_addr[4], priv->mac_addr[5]);

out:
	sqn_pr_leave();
	return rv;
}
Example #4
0
/** sqn_load_firmware - loads firmware to card
 *  @func: SDIO function, used to transfer data via SDIO interface,
 *         also used to obtain pointer to device structure.
 *
 *  But now the only work it does - is loading of bootstrapper to card,
 *  because firmware is supposed to be loaded by a userspace program.
 */
int sqn_load_firmware(struct sdio_func *func)
{
	int rv = 0;
	const struct firmware *fw = 0;
//Create a local firmware_name with path to replace original global firmware_name -- Tony Wu.
	const char *firmware_name = "../../../data/wimax/Boot.bin";

	struct sqn_sdio_card *sqn_card = sdio_get_drvdata(func);

	sqn_pr_enter();

	sqn_pr_info("trying to find bootloader image: \"%s\"\n", firmware_name);
	if ((rv = request_firmware(&fw, firmware_name, &func->dev)))
		goto out;

	if (SQN_1130 == sqn_card->version) {
		sdio_claim_host(func);

		/* properly setup registers for firmware loading */
		sqn_pr_dbg("setting up SQN_H_SDRAM_NO_EMR register\n");
		sdio_writeb(func, 0, SQN_H_SDRAM_NO_EMR, &rv);
		if (rv) {
			sdio_release_host(func);
			goto out;
		}

		sqn_pr_dbg("setting up SQN_H_SDRAMCTL_RSTN register\n");
		sdio_writeb(func, 1, SQN_H_SDRAMCTL_RSTN, &rv);
		sdio_release_host(func);
		if (rv)
			goto out;
	}

	sqn_pr_info("loading bootloader to the card...\n");
	if ((rv = sqn_load_bootstrapper(func, (u8*) fw->data, fw->size)))
		goto out;

	/* boot the card */
	sqn_pr_info("bootting the card...\n");
	sdio_claim_host(func); // by daniel
	sdio_writeb(func, 1, SQN_H_CRSTN, &rv);
	sdio_release_host(func); // by daniel
	if (rv)
		goto out;
	sqn_pr_info("  done\n");

out:
	// To avoid kzalloc leakage in /drivers/base/firmware_class.c	
	if (fw) {
		release_firmware(fw);
		fw = NULL;
	}

	sqn_pr_leave();
	return rv;
}
Example #5
0
static int sqn_handle_memcpy_tag(struct sdio_func *func
	, struct sqn_tag_memcpy * mcpy_tag)
{
	int rv = 0;

	sqn_pr_enter();

	/*
	 * Convert values accordingly to platform "endianes"
	 * (big or little endian) because bootstrapper file
	 * data is big endian
	 */
	mcpy_tag->address = be32_to_cpu(mcpy_tag->address);
	mcpy_tag->access_size = be32_to_cpu(mcpy_tag->access_size);
	mcpy_tag->data_size = be32_to_cpu(mcpy_tag->data_size);

	/* sqn_pr_dbg("----------------------------------------\n"); */
	sqn_pr_dbg("address: 0x%02X access_size: %u data_size: %u\n"
			, mcpy_tag->address, mcpy_tag->access_size
			, mcpy_tag->data_size);
	/* sqn_pr_dbg_dump("|", mcpy_tag->data, mcpy_tag->data_size); */

	rv = write_data(func, mcpy_tag->address, mcpy_tag->data
		, mcpy_tag->data_size, mcpy_tag->access_size);

	sqn_pr_leave();
	return rv;
}
Example #6
0
static int get_mac_addr_from_str(u8 *data, u32 length, u8 *result)
{
	int rv = 0;
	int i = 0;

	sqn_pr_enter();

	if (0 == length) {
		rv = -1;
		goto out;
	}

	/*
	 * Check if we have delimiters on appropriate places:
	 *
	 * X X : X X : X X : X X  :  X  X  :  X  X
	 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
	 */

	if ( !( ( ':' == data[2] || '-' == data[2])
		&& ( ':' == data[5] || '-' == data[5])
		&& ( ':' == data[8] || '-' == data[8])
		&& ( ':' == data[11] || '-' == data[11])
		&& ( ':' == data[14] || '-' == data[14]) ))
	{
		sqn_pr_err("can't get mac address from firmware"
			" - incorrect mac address\n");
		rv = -1;
		goto out;
	}

	i = 0;
	while (i < length) {
		int high = 0;
		int low = 0;

		if ((high = char_to_int(data[i])) >= 0
			&& (low = char_to_int(data[i + 1])) >= 0)
		{
			result[i/3] = low;
			result[i/3] |= high << 4;
		} else {
			sqn_pr_err("can't get mac address from firmware"
					" - incorrect mac address\n");
			rv = -1;
			goto out;
		}

		i += 3;
	}

out:
	if (length > 0) {
		data[length - 1] = 0;
		sqn_pr_dbg("mac addr string: %s\n", data);
	}
	sqn_pr_leave();
	return rv;
}
Example #7
0
int thp_handler(struct sk_buff *skb, struct net_device *pDev, struct packet_type *pPt)
#endif
{
	struct sk_buff *skb_thp = 0;
	struct ethhdr *eth = 0;

	sqn_pr_enter();

	/* We need only ETH_P_802_2 protocol packets with THP mac address */
	eth = skb2ethhdr(skb);
	if(ntohs(skb->protocol) != ETH_P_802_2 || !is_thp_packet(eth->h_dest)) {
		//for DDTM, drop all NOT THP packets
		if(drop_packet) {
			sqn_pr_dbg("HTC CODE: drop packet for DDTM\n");
			skb->pkt_type = PACKET_OTHERHOST;
		}
		goto not_thp_out;
	}

	skb_thp = skb_clone(skb, GFP_ATOMIC);
    /* Bugz 22554: strip CRC at the end of packet */
    skb_trim(skb_thp, skb_thp->len - 4);

#if THP_TRACE
	sqn_pr_info("%s: RX packet, len = %d\n", __func__, skb_thp->len);
#endif
	sqn_pr_dbg("RX THP packet, length %d\n", skb_thp->len);
	skb_queue_tail(&to_sqntool_queue, skb_thp);

	if(skb_queue_len(&to_sqntool_queue) == 256){
		skb_thp = skb_dequeue(&to_sqntool_queue);
		kfree_skb(skb_thp);
	}

	wake_up_interruptible(&to_sqntool_wait);	//Wake up wait queue

thp_out:
    dev_kfree_skb_any(skb); 
	sqn_pr_leave();
	return NET_RX_DROP;
not_thp_out:
	dev_kfree_skb_any(skb);
	sqn_pr_leave();
	return NET_RX_SUCCESS;
}
Example #8
0
static int is_good_ahb_address(u32 address, enum sqn_card_version card_version)
{
	u32 sdram_base = 0;
	u32 sdram_end = 0;
	u32 sdram_ctl_base = 0;
	u32 sdram_ctl_end = 0;
	int status = 0;

	sqn_pr_enter();

	if (address % 4)
		return 0;

	if (SQN_1130 == card_version) {
		sqn_pr_dbg("using 1130 AHB address boundaries\n");
		sdram_base	= SQN_1130_SDRAM_BASE;
		sdram_end	= SQN_1130_SDRAM_END;
		sdram_ctl_base	= SQN_1130_SDRAMCTL_BASE;
		sdram_ctl_end	= SQN_1130_SDRAMCTL_END;
	} else if (SQN_1210 == card_version) {
		sqn_pr_dbg("using 1210 AHB address boundaries\n");
		sdram_base	= SQN_1210_SDRAM_BASE;
		sdram_end	= SQN_1210_SDRAM_END;
		sdram_ctl_base	= SQN_1210_SDRAMCTL_BASE;
		sdram_ctl_end	= SQN_1210_SDRAMCTL_END;
	} else {
		sqn_pr_warn("Can't check AHB address because of unknown"
			" card version\n");
		status = 0;
		goto out;
	}

	status = ((sdram_base <= address && address < sdram_end)
			|| (sdram_ctl_base <= address && address < sdram_ctl_end));
out:
	sqn_pr_leave();
	return status;
}
Example #9
0
void signal_card_sleep_completion(struct sqn_private *priv)
{
	struct sqn_sdio_card *card = priv->card;
	unsigned long irq_flags = 0;

	sqn_pr_enter();

	spin_lock_irqsave(&priv->drv_lock, irq_flags);
	card->is_card_sleeps = 0;
	spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
	wake_up_interruptible(&g_card_sleep_waitq);
	sqn_pr_dbg("card sleep completion is signaled\n");

	sqn_pr_leave();
}
Example #10
0
static int sqn_handle_memset_tag(struct sdio_func *func
	, struct sqn_tag_memset * mset_tag)
{
	int rv = 0;
	u8 *buf = 0;
	const u32 buf_size = 1024;
	u32 left_bytes = 0;

	sqn_pr_enter();

	/*
	 * Convert values accordingly to platform "endianes"
	 * (big or little endian) because bootstrapper file
	 * data is big endian
	 */
	mset_tag->address = be32_to_cpu(mset_tag->address);
	mset_tag->access_size = be32_to_cpu(mset_tag->access_size);
	mset_tag->size = be32_to_cpu(mset_tag->size);

	/* sqn_pr_dbg("----------------------------------------\n"); */
	sqn_pr_dbg("address: 0x%02X access_size: %u size: %u pattern 0x%02X\n"
			, mset_tag->address, mset_tag->access_size
			, mset_tag->size, mset_tag->pattern);

	buf = kmalloc(buf_size, GFP_KERNEL);
	if (0 == buf)
		return -ENOMEM;

	memset(buf, mset_tag->pattern, buf_size);

	left_bytes = mset_tag->size;

	while (left_bytes) {
		u32 bytes_to_write = min(buf_size, left_bytes);
		rv = write_data(func, mset_tag->address, buf, bytes_to_write,
			mset_tag->access_size);
		if (rv)
			goto out;
		left_bytes -= bytes_to_write;
	}

out:
	kfree(buf);
	sqn_pr_leave();
	return rv;
}
Example #11
0
int sqn_start_tx_thread(struct sqn_private *priv)
{
	int rv = 0;

	sqn_pr_enter();

	priv->tx_thread = kthread_run(sqn_tx_thread, priv->dev, "sqn_tx");

	if (IS_ERR(priv->tx_thread)) {
		sqn_pr_dbg("error creating TX thread.\n");
		rv = 1;
		goto out;
	}

	sqn_pr_leave();
out:
	return rv;
}
Example #12
0
int sqn_start_card(struct sqn_private *priv)
{
	struct net_device *dev = priv->dev;

	sqn_pr_enter();

	if (register_netdev(dev)) {
		sqn_pr_err("cannot register ethX device\n");
		return -1;
	}

	sqn_pr_dbg("starting TX thread...\n");
	/* TODO: move waitq initializatio to add_card() */
	init_waitqueue_head(&priv->tx_waitq);
	init_waitqueue_head(&priv->rx_waitq);
	if (sqn_start_tx_thread(priv))
		goto err_init_adapter;

	sqn_pr_info("%s: Sequans WiMAX adapter\n", dev->name);

#if IGNORE_CARRIER_STATE
    netif_carrier_on(priv->dev);
#else
	/* In release version this should be uncommented */
	/* netif_carrier_off(priv->dev); */
#endif

done:
	sqn_pr_leave();
	return 0;

err_init_adapter:
	/* TODO: Free allocated resources */
	sqn_pr_err("error while init adapter\n");
	free_netdev(dev);
	priv = NULL;

	goto done;
}
Example #13
0
int sqn_handle_lsp_packet(struct sqn_private *priv
	, struct sk_buff *skb)
{
	struct sqn_sdio_card *card = priv->card;
	unsigned long irq_flags = 0;
	struct sqn_lsp_packet *lsp_response = (struct sqn_lsp_packet*)
		((u8*)skb->data + sizeof(struct sqn_eth_header));

	sqn_pr_enter();

	if (!sqn_is_rx_lsp_packet(skb)) {
		sqn_pr_dbg("not LSP packet\n");
		sqn_pr_leave();
		return 0;
	}

	sqn_pr_dbg("LSP packet\n");

	switch (ntohl(lsp_response->lsp_header.id)) {
	case THSP_GET_MEDIA_CONNECTION_STATE:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: THSP_GET_MEDIA_CONNECTION_STATE state=%xh\n"
				, ntohl(lsp_response->lsp_header.u.media_con_state));
		}
		sqn_pr_warn("THSP_GET_MEDIA_CONNECTION_STATE not implemented\n");
		break;
	case THSP_MEDIA_CONNECTION_STATE_CHANGE:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: THSP_MEDIA_CONNECTION_STATE_CHANGE state=%xh\n"
				, ntohl(lsp_response->lsp_header.u.media_con_state));
		}
		if (THSP_MEDIA_CONNECTION_ATTACHED
			== ntohl(lsp_response->lsp_header.u.media_con_state))
		{

#if IGNORE_CARRIER_STATE
            /* netif_carrier_on(priv->dev); */
            sqn_pr_info("WiMAX carrier PRESENT [ignored]\n");
#else
            netif_carrier_on(priv->dev);
			sqn_pr_info("WiMAX carrier PRESENT\n");
#endif
		} else {
#if IGNORE_CARRIER_STATE
			/* netif_carrier_off(priv->dev); */
			sqn_pr_info("WiMAX carrier LOST [ignored]\n");
#else
			netif_carrier_off(priv->dev);
			sqn_pr_info("WiMAX carrier LOST\n");
#endif
		}
		break;
	case THSP_SET_HOST_POWER_MODE_ACK:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: THSP_SET_HOST_POWER_MODE_ACK tid=0x%x\n"
				, ntohl(lsp_response->lsp_header.u.host_power.tid));
		}
		free_last_request();
		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 1;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		signal_pm_request_completion(priv);
		break;
	case THSP_SET_FW_POWER_MODE_ACK:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: THSP_SET_FW_POWER_MODE_ACK tid=0x%x\n"
				, ntohl(lsp_response->lsp_header.u.fw_power.tid));
		}
		sqn_pr_info("THSP_SET_FW_POWER_MODE_ACK not implemented\n");
		break;
	case THSP_SQN_STATE_CHANGE:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: THSP_SQN_STATE_CHANGE tid=0x%x, state=%xh\n"
				, ntohl(lsp_response->lsp_header.u.fw_state.tid)
				, ntohl(lsp_response->lsp_header.u.fw_state.state));
		}
		handle_sqn_state_change_msg(priv, lsp_response);
		break;
	case THSP_THP_AVAILABLE:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: THSP_THP_AVAILABLE tid=0x%x, reply=%xh\n"
				, ntohl(lsp_response->lsp_header.u.thp_avl.tid)
				, ntohl(lsp_response->lsp_header.u.thp_avl.reply));
		}
		handle_thp_avl_msg(priv, lsp_response);
		break;
	default:
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("RX LSP: UNKNOWN=0x%x\n"
				, ntohl(lsp_response->lsp_header.id));
		}
	}

	dev_kfree_skb_any(skb);
	sqn_pr_leave();

	return 1;
}
Example #14
0
/** sqn_load_bootstrapper - reads a binary boostrapper file, analize it
 *  and loads data to the card.
 *
 *  Bootstrapper is consists of Tag, Length, Value (TLV) sections.
 *  Each section starts with 4 bytes tag. Then goes length of data (4 bytes)
 *  and then the data itself.
 *
 *  All fields of bootstrapper file is in BIG ENDIAN format.
 */
static int sqn_load_bootstrapper(struct sdio_func *func, u8 *data, int size)
{
	struct sqn_tlv *tlv = (struct sqn_tlv*) data;
	int rv = 0;

	sqn_pr_enter();

	while (size > 0) {
		/*
		 * Convert values accordingly to platform "endianes"
		 * (big or little endian) because bootstrapper file
		 * data is big endian
		 */
		tlv->tag = be32_to_cpu(tlv->tag);
		tlv->length = be32_to_cpu(tlv->length);

		switch (tlv->tag) {
		case SWM_INFO_TAG_SQN_ROOT:
		case SWM_INFO_TAG_SQN_BOOTROM_GROUP:
		case SWM_INFO_TAG_SQN_ID_GROUP:
			/*
			 * This tag is a "container" tag - it's value field
			 * contains other tags
			 */

			/* sqn_pr_dbg("========================================\n"); */
			sqn_pr_dbg("tag: CONTAINER %x length: %u\n", tlv->tag
				, tlv->length);
			/* sqn_pr_dbg_dump("|", tlv->value, tlv->length); */

			/*
			 * If this is a buggy tag, adjust length to
			 * the rest of data
			 */
			if (0 == tlv->length)
				tlv->length = size - sizeof(*tlv);

			rv = sqn_load_bootstrapper(func, (u8*) tlv->value
				, tlv->length);
			if (rv)
				goto out;
			break;

		case SWM_INFO_TAG_SQN_MEMCPY:
			/* sqn_pr_dbg("========================================\n"); */
			sqn_pr_dbg("tag: SWM_INFO_TAG_SQN_MEMCPY length: %u\n"
					, tlv->length);
			/* sqn_pr_dbg_dump("|", tlv->value, tlv->length); */
			rv = sqn_handle_memcpy_tag(func
				, (struct sqn_tag_memcpy*) tlv->value);
			if (rv)
				goto out;
			break;

		case SWM_INFO_TAG_SQN_MEMSET:
			/* sqn_pr_dbg("========================================\n"); */
			sqn_pr_dbg("tag: SWM_INFO_TAG_SQN_MEMSET length: %u\n"
					, tlv->length);
			/* sqn_pr_dbg_dump("|", tlv->value, tlv->length); */
			rv = sqn_handle_memset_tag(func
				, (struct sqn_tag_memset*) tlv->value);
			if (rv)
				goto out;
			break;

		case SWM_INFO_TAG_SQN_MAC_ADDRESS:
			/* sqn_pr_dbg("========================================\n"); */
			sqn_pr_dbg("tag: SWM_INFO_TAG_SQN_MAC_ADDRESS length: %u\n"
					, tlv->length);
			/* sqn_pr_dbg_dump("|", tlv->value, tlv->length); */

			rv = sqn_handle_mac_addr_tag(func, tlv->value
				, tlv->length);
			if (rv)
				goto out;
			break;

		default:
			/* skip all other tags */
			/* sqn_pr_dbg("========================================\n"); */
			sqn_pr_dbg("tag: UNKNOWN %x length: %u\n"
					, tlv->tag, tlv->length);
			/* sqn_pr_dbg_dump("|", tlv->value, tlv->length); */
			break;
		}

		/* increment tlv to point it to the beginning of the next
		 * sqn_tlv struct and decrement size accordingly
		 */
		size = (int)(size - (sizeof(*tlv) + tlv->length));
		tlv = (struct sqn_tlv*) ((u8*)tlv + sizeof(*tlv) + tlv->length);
	}

	if (0 != size) {
		/* something wrong with parsing of tlv values */
		rv = -1;
		goto out;
	}

out:
	sqn_pr_leave();
	return rv;
}
Example #15
0
static int sqn_tx_thread(void *data)
{
	struct net_device *dev = (struct net_device *) data;
	struct sqn_private *priv = netdev_priv(dev);
	int rv = 0;
	unsigned long irq_flags = 0;

	sqn_pr_enter();

	/*
	 * Set PF_NOFREEZE to prevent kernel to freeze this thread
	 * when going to suspend. We will manually stop it from
	 * driver's suspend handler.
	 */
	current->flags |= PF_NOFREEZE;

	for (;;) {
		spin_lock_irqsave(&priv->drv_lock, irq_flags);

		if (!(priv->is_tx_queue_empty(priv)) || priv->removed)
			spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		else {
			int rv = 0;
			sqn_pr_dbg("wait for skb\n");
			spin_unlock_irqrestore(&priv->drv_lock, irq_flags);

			rv = wait_event_interruptible(priv->tx_waitq
				, !(priv->is_tx_queue_empty(priv))
				  || kthread_should_stop()
				  || priv->removed);

			/*
			 * If we've been interrupted by a signal, then we
			 * should stop a thread
			 */
			if (0 != rv) {
				sqn_pr_dbg("got a signal from kernel %d\n", rv);
				break;
			}
		}

		sqn_pr_dbg("got skb to send, wake up\n");

		if (kthread_should_stop()) {
			sqn_pr_dbg("break from main thread\n");
			break;
		}

		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		if (priv->removed) {
			sqn_pr_dbg("adapter removed; wait to die...\n");
			spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
			mdelay(1);
			continue;
		}
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);

		rv= priv->hw_host_to_card(priv);
		if (rv)
			sqn_pr_dbg("failed to send PDU: %d\n", rv);
	}

	sqn_pr_leave();
	return 0;
}
Example #16
0
static int write_data(struct sdio_func *func, u32 addr, void *data
	, u32 size, u32 access_size)
{
	int rv = 0;
	struct sqn_sdio_card *sqn_card = sdio_get_drvdata(func);

	sqn_pr_enter();
	sdio_claim_host(func);

	if (is_good_ahb_address(addr, sqn_card->version)
		&& 0 == (size % 4) && 4 == access_size)
	{
		/* write data using AHB */

		u8 *data_cp = 0;
#ifdef DEBUG
		u8 *read_data  = 0;
#endif

		sqn_pr_dbg("write data using AHB\n");
		sdio_writel(func, addr, SQN_SDIO_ADA_ADDR, &rv);
		if (rv) {
			sqn_pr_dbg("can't set SQN_SDIO_ADA_ADDR register\n");
			goto out;
		}
		sqn_pr_dbg("after SQN_SDIO_ADA_ADDR\n");

		data_cp = kmalloc(size, GFP_KERNEL | GFP_DMA);
		memcpy(data_cp, data, size);
		rv = sdio_writesb(func, SQN_SDIO_ADA_RDWR, data_cp, size);
		if (rv) {
			sqn_pr_dbg("can't write to SQN_SDIO_ADA_RDWR register\n");
			goto out;
		}
		kfree(data_cp);

		/*
		 * Workaround when sdio_writesb doesn't work because DMA
		 * alignment
		 */
		/*
		int i = 0;
		for (; i < size/4; ++i) {
			sdio_writel(func, *((u32*)data + i), SQN_SDIO_ADA_RDWR, &rv);
			if (rv) {
				sqn_pr_dbg("can't write to SQN_SDIO_ADA_RDWR register\n");
				goto out;
			}
		}
		*/

		sqn_pr_dbg("after SQN_SDIO_ADA_RDWR\n");

		/* ******** only for debugging ******** */
		/* validate written data */
/* #ifdef DEBUG */
#if 0
		sqn_pr_dbg("reading data using AHB\n");
		sdio_writel(func, addr, SQN_SDIO_ADA_ADDR, &rv);
		if (rv) {
			sqn_pr_dbg("can't set SQN_SDIO_ADA_ADDR register\n");
			goto out;
		}
		sqn_pr_dbg("after SQN_SDIO_ADA_ADDR\n");

		read_data = kmalloc(size, GFP_KERNEL);
		rv = sdio_readsb(func, read_data, SQN_SDIO_ADA_RDWR, size);
		if (rv) {
			sqn_pr_dbg("can't read from SQN_SDIO_ADA_RDWR register\n");
			kfree(read_data);
			goto out;
		}

		if (memcmp(data, read_data, size))
			sqn_pr_dbg("WARNING: written data are __not__ equal\n");
		else
			sqn_pr_dbg("OK: written data are equal\n");

		kfree(read_data);
#endif /* DEBUG */
		/* ******** only for debugging ******** */

	} else if (4 == access_size && size >= 4) {
		/* write data using CMD53 */
		sqn_pr_dbg("write data using CMD53\n");
		rv = sdio_memcpy_toio(func, addr, data , size);
	} else {
		/* write data using CMD52 */
		/* not implemented yet, so we use CMD53 */
		/* rv = sdio_memcpy_toio(func, addr, data , size); */
		int i = 0;
		sqn_pr_dbg("write data using CMD52\n");
		for (i = 0; i < size; ++i) {
			sdio_writeb(func, *((u8*)data + i), addr + i, &rv);
			if (rv) {
				sqn_pr_dbg("can't write 1 byte to %xh addr using CMD52\n"
					, addr + i);
				goto out;
			}
		}
	}

out:
	sdio_release_host(func);
	sqn_pr_leave();
	return rv;
}
Example #17
0
int sqn_wakeup_fw(struct sdio_func *func)
{
	int rv = 0;
	int ver = 0;
	int counter = 0;

	int retry_cnt = 3;
	u32 wakeup_delay = 0;
	unsigned long timeout = msecs_to_jiffies(800);

	unsigned long irq_flags = 0;
	struct sqn_private *priv = ((struct sqn_sdio_card *)sdio_get_drvdata(func))->priv;
	struct sqn_sdio_card *card = priv->card;
	u8 need_to_unlock_wakelock = 0;

	sqn_pr_enter();
	sqn_pr_info("waking up the card...\n");

	if (!wake_lock_active(&card->wakelock_tx)) {
		if (mmc_wimax_get_sdio_wakelock_log()) {
			printk(KERN_INFO "[WIMAX] lock wl_tx2,");
			PRINTRTC;
		}
		wake_lock(&card->wakelock_tx);
		need_to_unlock_wakelock = 1;
	}

retry:
	if (priv->removed)
		goto out;

	sdio_claim_host(func);

#define  SDIO_CCCR_CCCR_SDIO_VERSION_VALUE	0x11

    wakeup_delay = 2;
	counter = 5;
	do {
		sqn_pr_dbg("CMD52 #%d, delay %d msec\n", counter, wakeup_delay);
		ver = sdio_readb(func, SDIO_CCCR_CCCR_SDIO_VERSION, &rv);
		// To avoid FW sutck in PLLOFF, SDIO isn't able to wake up it.
		mdelay(wakeup_delay);
		--counter;
	} while((rv || ver != SDIO_CCCR_CCCR_SDIO_VERSION_VALUE) && counter > 0);

	if (rv) {
		sqn_pr_err("error when reading SDIO_VERSION\n");

		if (mmc_wimax_get_wimax_FW_freeze_WK_TX()) {
			sqn_pr_info("[ste]set is_card_sleeps 0 to avoid TX polling\n");
			card->is_card_sleeps = 0;
		}

		sdio_release_host(func);
		goto out;
	} else
		sqn_pr_dbg("SDIO_VERSION has been read successfully\n");

	sqn_pr_dbg("send wake-up signal to card\n");
	sdio_writeb(func, 1, SQN_SOC_SIGS_LSBS, &rv);

	if (rv)
		sqn_pr_err("error when writing to SQN_SOC_SIGS_LSBS: %d\n", rv);

	sdio_release_host(func);

	sqn_pr_info("wait for completion (timeout %d msec)...\n"
		, jiffies_to_msecs(timeout));

	rv = wait_event_interruptible_timeout(g_card_sleep_waitq
		, 0 == card->is_card_sleeps || priv->removed, timeout);

	if (priv->removed)
		goto out;

	if (-ERESTARTSYS == rv) {
		sqn_pr_warn("got a signal from kernel %d\n", rv);
	} else if (0 == rv) {
		rv = -1;
		sqn_pr_err("can't wake up the card - timeout elapsed\n");

		if (retry_cnt-- > 0 && card->is_card_sleeps) {
			sqn_pr_info("retry wake up\n");
			goto retry;
    	}
		sqn_pr_info("giving up to wake up the card\n");

		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 0;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
	} else {
		rv = 0;
		sqn_pr_info("card is waked up successfully\n");
	}

out:
	if (need_to_unlock_wakelock && wake_lock_active(&card->wakelock_tx)) {
		if (mmc_wimax_get_sdio_wakelock_log()) {
			printk(KERN_INFO "[WIMAX] release wake_lock_tx in %s,", __func__);
			PRINTRTC;
		}
		wake_unlock(&card->wakelock_tx); /* TX */
	}
	sqn_pr_leave();
	return rv;
}
Example #18
0
int sqn_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	unsigned long irq_flags = 0;
	struct ethhdr *eth;
	struct sqn_private *priv = netdev_priv(dev);

#if DRIVER_DEBUG
	printk(KERN_WARNING "sqn_hard_start_xmit \n");
#endif

	sqn_pr_enter();

	sqn_pr_dbg("skb->len = %d\n", skb->len);

#if SKB_DEBUG
	sqn_pr_info("%s: got skb [0x%p] from kernel, users %d\n", __func__, skb, atomic_read(&skb->users)); 
#endif

	spin_lock_irqsave(&priv->drv_lock, irq_flags);

	//HTC code: for DDTM
	if(drop_packet){
		eth = (struct ethhdr*) skb->data;
		if(memcmp(eth->h_dest, ss_macaddr, ETH_ALEN) != 0){
			sqn_pr_dbg("HTC drop_packet enabled: not THP, drop it\n");
#if DRIVER_DEBUG
			printk(KERN_WARNING "sqn_hard_start_xmit: network packet\n");
#endif
			priv->stats.tx_dropped++;
			priv->stats.tx_errors++;
			dev_kfree_skb_any(skb);
			goto out;
		}else{
			sqn_pr_dbg("HTC drop_packet enabled: THP, let it live\n");
#if DRIVER_DEBUG
			printk(KERN_WARNING "sqn_hard_start_xmit: thp packet\n");
#endif
		}
	}

	if (priv->removed)
		goto out;

	if (skb->len < 1 || (skb->len > SQN_MAX_PDU_LEN)) {
		sqn_pr_dbg("skb length %d not in range (1, %d)\n", skb->len,
			   SQN_MAX_PDU_LEN);
		/*
		 * We'll never manage to send this one;
		 * drop it and return 'OK'
		 */
		priv->stats.tx_dropped++;
		priv->stats.tx_errors++;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		goto out;
	}

	/* netif_stop_queue(priv->dev); */

	priv->add_skb_to_tx_queue(priv, skb, 1);

	priv->stats.tx_packets++;
	priv->stats.tx_bytes += skb->len;

	dev->trans_start = jiffies;

	spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
	wake_up_interruptible(&priv->tx_waitq);
out:
	sqn_pr_leave();
	return NETDEV_TX_OK;
}