Esempio n. 1
0
static void ks_sdio_interrupt(struct sdio_func *func)
{
	int ret;
	struct ks_sdio_card *card;
	struct ks_wlan_private *priv;
	unsigned char status, rsize, byte;

	card = sdio_get_drvdata(func);
	priv = card->priv;
	DPRINTK(4, "\n");

	if (priv->dev_state < DEVICE_STATE_BOOT)
		goto queue_delayed_work;

	ret = ks7010_sdio_readb(priv, INT_PENDING, &status);
	if (ret) {
		DPRINTK(1, "error : INT_PENDING\n");
		goto queue_delayed_work;
	}
	DPRINTK(4, "INT_PENDING=%02X\n", status);

	/* schedule task for interrupt status */
	/* bit7 -> Write General Communication B register */
	/* read (General Communication B register) */
	/* bit5 -> Write Status Idle */
	/* bit2 -> Read Status Busy  */
	if (status & INT_GCR_B ||
	    atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
		ret = ks7010_sdio_readb(priv, GCR_B, &byte);
		if (ret) {
			DPRINTK(1, " error : GCR_B\n");
			goto queue_delayed_work;
		}
		if (byte == GCR_B_ACTIVE) {
			if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
				atomic_set(&priv->psstatus.status, PS_WAKEUP);
				priv->wakeup_count = 0;
			}
			complete(&priv->psstatus.wakeup_wait);
		}
	}

	do {
		/* read (WriteStatus/ReadDataSize FN1:00_0014) */
		ret = ks7010_sdio_readb(priv, WSTATUS_RSIZE, &byte);
		if (ret) {
			DPRINTK(1, " error : WSTATUS_RSIZE\n");
			goto queue_delayed_work;
		}
		DPRINTK(4, "WSTATUS_RSIZE=%02X\n", byte);
		rsize = byte & RSIZE_MASK;
		if (rsize != 0)		/* Read schedule */
			ks_wlan_hw_rx(priv, (uint16_t)(rsize << 4));

		if (byte & WSTATUS_MASK) {
			if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
				if (cnt_txqbody(priv)) {
					ks_wlan_hw_wakeup_request(priv);
					queue_delayed_work(priv->wq, &priv->rw_dwork, 1);
					return;
				}
			} else {
				tx_device_task(priv);
			}
		}
	} while (rsize);

queue_delayed_work:
	queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
}
Esempio n. 2
0
static void ks_sdio_interrupt(struct sdio_func *func)
{
	int retval;
	struct ks_sdio_card *card;
	struct ks_wlan_private *priv;
	unsigned char status, rsize, rw_data;

	card = sdio_get_drvdata(func);
	priv = card->priv;
	DPRINTK(4, "\n");

	if (priv->dev_state >= DEVICE_STATE_BOOT) {
		retval =
		    ks7010_sdio_read(priv, INT_PENDING, &status,
				     sizeof(status));
		if (retval) {
			DPRINTK(1, "read INT_PENDING Failed!!(%d)\n", retval);
			goto intr_out;
		}
		DPRINTK(4, "INT_PENDING=%02X\n", rw_data);

		/* schedule task for interrupt status */
		/* bit7 -> Write General Communication B register */
		/* read (General Communication B register) */
		/* bit5 -> Write Status Idle */
		/* bit2 -> Read Status Busy  */
		if (status & INT_GCR_B
		    || atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
			retval =
			    ks7010_sdio_read(priv, GCR_B, &rw_data,
					     sizeof(rw_data));
			if (retval) {
				DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
				goto intr_out;
			}
			/* DPRINTK(1, "GCR_B=%02X\n", rw_data); */
			if (rw_data == GCR_B_ACTIVE) {
				if (atomic_read(&priv->psstatus.status) ==
				    PS_SNOOZE) {
					atomic_set(&priv->psstatus.status,
						   PS_WAKEUP);
					priv->wakeup_count = 0;
				}
				complete(&priv->psstatus.wakeup_wait);
			}

		}

		do {
			/* read (WriteStatus/ReadDataSize FN1:00_0014) */
			retval =
			    ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data,
					     sizeof(rw_data));
			if (retval) {
				DPRINTK(1, " error : WSTATUS_RSIZE=%02X\n",
					rw_data);
				goto intr_out;
			}
			DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);
			rsize = rw_data & RSIZE_MASK;
			if (rsize) {	/* Read schedule */
				ks_wlan_hw_rx((void *)priv,
					      (uint16_t) (((rsize) << 4)));
			}
			if (rw_data & WSTATUS_MASK) {
#if 0
				if (status & INT_WRITE_STATUS
				    && !cnt_txqbody(priv)) {
					/* dummy write for interrupt clear */
					rw_data = 0;
					retval =
					    ks7010_sdio_write(priv, DATA_WINDOW,
							      &rw_data,
							      sizeof(rw_data));
					if (retval) {
						DPRINTK(1,
							"write DATA_WINDOW Failed!!(%d)\n",
							retval);
					}
					status &= ~INT_WRITE_STATUS;
				} else {
#endif
					if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
						if (cnt_txqbody(priv)) {
							ks_wlan_hw_wakeup_request(priv);
							queue_delayed_work
							    (priv->ks_wlan_hw.
							     ks7010sdio_wq,
							     &priv->ks_wlan_hw.
							     rw_wq, 1);
							return;
						}
					} else {
						tx_device_task((void *)priv);
					}
#if 0
				}
#endif
			}
		} while (rsize);
	}

 intr_out:
	queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
			   &priv->ks_wlan_hw.rw_wq, 0);
	return;
}
Esempio n. 3
0
static void ks7010_rw_function(struct work_struct *work)
{
	struct ks_wlan_private *priv;
	unsigned char byte;
	int ret;

	priv = container_of(work, struct ks_wlan_private, rw_dwork.work);

	DPRINTK(4, "\n");

	/* wait after DOZE */
	if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) {
		DPRINTK(4, "wait after DOZE\n");
		queue_delayed_work(priv->wq, &priv->rw_dwork, 1);
		return;
	}

	/* wait after WAKEUP */
	while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) {
		DPRINTK(4, "wait after WAKEUP\n");
		dev_info(&priv->ks_sdio_card->func->dev,
			 "wake: %lu %lu\n",
			 priv->last_wakeup + (30 * HZ) / 1000,
				jiffies);
		msleep(30);
	}

	sdio_claim_host(priv->ks_sdio_card->func);

	/* power save wakeup */
	if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
		if (cnt_txqbody(priv) > 0) {
			ks_wlan_hw_wakeup_request(priv);
			queue_delayed_work(priv->wq, &priv->rw_dwork, 1);
		}
		goto release_host;
	}

	/* sleep mode doze */
	if (atomic_read(&priv->sleepstatus.doze_request) == 1) {
		ks_wlan_hw_sleep_doze_request(priv);
		goto release_host;
	}
	/* sleep mode wakeup */
	if (atomic_read(&priv->sleepstatus.wakeup_request) == 1) {
		ks_wlan_hw_sleep_wakeup_request(priv);
		goto release_host;
	}

	/* read (WriteStatus/ReadDataSize FN1:00_0014) */
	ret = ks7010_sdio_readb(priv, WSTATUS_RSIZE, &byte);
	if (ret) {
		DPRINTK(1, " error : WSTATUS_RSIZE psstatus=%d\n",
			atomic_read(&priv->psstatus.status));
		goto release_host;
	}
	DPRINTK(4, "WSTATUS_RSIZE=%02X\n", byte);

	if (byte & RSIZE_MASK) {	/* Read schedule */
		ks_wlan_hw_rx(priv, (uint16_t)((byte & RSIZE_MASK) << 4));
	}
	if ((byte & WSTATUS_MASK))
		tx_device_task(priv);

	_ks_wlan_hw_power_save(priv);

release_host:
	sdio_release_host(priv->ks_sdio_card->func);
}
Esempio n. 4
0
static void ks7010_rw_function(struct work_struct *work)
{
	struct hw_info_t *hw;
	struct ks_wlan_private *priv;
	unsigned char rw_data;
	int retval;

	hw = container_of(work, struct hw_info_t, rw_wq.work);
	priv = container_of(hw, struct ks_wlan_private, ks_wlan_hw);

	DPRINTK(4, "\n");

	/* wiat after DOZE */
	if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) {
		DPRINTK(4, "wait after DOZE \n");
		queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
				   &priv->ks_wlan_hw.rw_wq, 1);
		return;
	}

	/* wiat after WAKEUP */
	while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) {
		DPRINTK(4, "wait after WAKEUP \n");
/*		queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq,
		(priv->last_wakeup + ((30*HZ)/1000) - jiffies));*/
		printk("wake: %lu %lu\n", priv->last_wakeup + (30 * HZ) / 1000,
		       jiffies);
		msleep(30);
	}

	sdio_claim_host(priv->ks_wlan_hw.sdio_card->func);

	/* power save wakeup */
	if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
		if (cnt_txqbody(priv) > 0) {
			ks_wlan_hw_wakeup_request(priv);
			queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
					   &priv->ks_wlan_hw.rw_wq, 1);
		}
		goto err_out;
	}

	/* sleep mode doze */
	if (atomic_read(&priv->sleepstatus.doze_request) == 1) {
		ks_wlan_hw_sleep_doze_request(priv);
		goto err_out;
	}
	/* sleep mode wakeup */
	if (atomic_read(&priv->sleepstatus.wakeup_request) == 1) {
		ks_wlan_hw_sleep_wakeup_request(priv);
		goto err_out;
	}

	/* read (WriteStatus/ReadDataSize FN1:00_0014) */
	retval =
	    ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data));
	if (retval) {
		DPRINTK(1, " error : WSTATUS_RSIZE=%02X psstatus=%d\n", rw_data,
			atomic_read(&priv->psstatus.status));
		goto err_out;
	}
	DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);

	if (rw_data & RSIZE_MASK) {	/* Read schedule */
		ks_wlan_hw_rx((void *)priv,
			      (uint16_t) (((rw_data & RSIZE_MASK) << 4)));
	}
	if ((rw_data & WSTATUS_MASK)) {
		tx_device_task((void *)priv);
	}
	_ks_wlan_hw_power_save(priv);

 err_out:
	sdio_release_host(priv->ks_wlan_hw.sdio_card->func);

	return;
}