Beispiel #1
0
static void handle_sqn_state_change_msg(struct sqn_private *priv
	, struct sqn_lsp_packet *lsp)
{
	struct sqn_sdio_card *card = priv->card;
	struct sk_buff *skb_reply = 0;
	unsigned long irq_flags = 0;
	const int card_state = ntohl(lsp->lsp_header.u.fw_state.state);

	sqn_pr_enter();

	switch (card_state) {
	case LSP_SQN_ACTIVE:
		sqn_pr_info("card switched to ACTIVE state (OPT)\n");
		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 0;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		break;
	case LSP_SQN_IDLE:
		sqn_pr_info("card switched to IDLE state (LPM)\n");
		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 1;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		break;
	case LSP_SQN_DROPPED:
		sqn_pr_info("card switched to DROPPED state (LPM)\n");
		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 1;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		break;
	case LSP_SQN_REENTRY:
		sqn_pr_info("card switched to REENTRY state (LPM)\n");
		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 1;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		break;
	default:
		sqn_pr_info("card switched to UNSUPPORTED mode %d/0x%x\n"
			, card_state, card_state);
		spin_lock_irqsave(&priv->drv_lock, irq_flags);
		card->is_card_sleeps = 0;
		spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
		break;
	}
	skb_reply = construct_lsp_packet(THSP_SQN_STATE_CHANGE_REPLY
			, ntohl(lsp->lsp_header.u.thp_avl.tid), 0);
	if (0 != (skb_reply = sqn_sdio_prepare_skb_for_tx(skb_reply)))
		sqn_sdio_tx_skb(card, skb_reply, 0);
	wake_up_interruptible(&g_card_sleep_waitq);

	sqn_pr_leave();
}
Beispiel #2
0
static void handle_thp_avl_msg(struct sqn_private *priv
	, struct sqn_lsp_packet *lsp)
{
	struct sqn_sdio_card *card = priv->card;
	struct sk_buff *skb_reply = 0;
	enum sqn_thp_available_reply thp_rpl; 
	unsigned long irq_flags = 0;

	sqn_pr_enter();

	spin_lock_irqsave(&priv->drv_lock, irq_flags);
	/* if (card->is_card_sleeps) { */
	if (priv->is_tx_queue_empty(priv)) {
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("TX queue empty, thp_rpl=FINISH\n");
		}
		/* sqn_pr_dbg("card was asleep, thp_rpl=FINISH\n"); */
		thp_rpl = LSP_THPA_FINISHED;
		card->is_card_sleeps = 1;
		gHostWakeupFWEvent = 0;
	/* } else if (priv->is_tx_queue_empty(priv)) { */
		/* sqn_pr_dbg("card was not asleep and tx_queue is empty, thp_rpl=FINISHED\n"); */
		/* thp_rpl = LSP_THPA_FINISHED; */
		/* card->is_card_sleeps = 1; */
	} else {
		/* sqn_pr_info("card was not asleep but tx_queue is no empty, thp_rpl=EXIT\n"); */
		if (mmc_wimax_get_sdio_lsp_log()) {
			sqn_pr_info("TX queue not empty, thp_rpl=ACK\n");
		}
		/* sqn_pr_dbg("card was not asleep, thp_rpl=ACK\n"); */
		thp_rpl = LSP_THPA_ACK;
		card->is_card_sleeps = 0;
	}
	spin_unlock_irqrestore(&priv->drv_lock, irq_flags);
	skb_reply = construct_lsp_packet(THSP_THP_AVAILABLE_REPLY
			, ntohl(lsp->lsp_header.u.thp_avl.tid)
			, thp_rpl);
	if (0 != (skb_reply = sqn_sdio_prepare_skb_for_tx(skb_reply)))
		sqn_sdio_tx_skb(card, skb_reply, 0);
	wake_up_interruptible(&g_card_sleep_waitq);
	if (netif_queue_stopped(priv->dev))
		netif_wake_queue(priv->dev);

	if (!card->is_card_sleeps && !gHostWakeupFWEvent) {
		gHostWakeupFWEvent = 1; // Dump next TX packet after LSP ThpAvailableReply(ACK);
	}

	sqn_pr_leave();
}
Beispiel #3
0
static int sqn_set_power_mode_helper(struct sdio_func *func
	, enum sqn_thsp_service command_id, u32 pm)
{
	unsigned long irq_flags = 0;
	struct sqn_sdio_card *card = sdio_get_drvdata(func);

	sqn_pr_enter();

	free_last_request();

	spin_lock(&g_last_request_lock);

	g_last_request_pm = pm;
	g_last_request_skb = construct_lsp_packet(command_id, pm, 0);

	if (0 == g_last_request_skb)
		return 1;

	netif_stop_queue(card->priv->dev);

	/*
	 * We can't call sqn_sdio_tx_skb() from here, because we are not in
	 * process context
	 */
	skb_queue_tail(&card->tx_queue, g_last_request_skb);
	g_last_request_skb = 0;

	spin_unlock(&g_last_request_lock);

	spin_lock_irqsave(&card->priv->drv_lock, irq_flags);
	card->pm_complete = 0;
	spin_unlock_irqrestore(&card->priv->drv_lock, irq_flags);

	wake_up_interruptible(&card->priv->tx_waitq);

	sqn_pr_leave();

	return 0;
}