示例#1
0
static void tx_device_task(struct ks_wlan_private *priv)
{
	struct tx_device_buffer *sp;
	int ret;

	DPRINTK(4, "\n");
	if (cnt_txqbody(priv) <= 0 ||
	    atomic_read(&priv->psstatus.status) == PS_SNOOZE)
		return;

	sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
	if (priv->dev_state >= DEVICE_STATE_BOOT) {
		ret = write_to_device(priv, sp->sendp, sp->size);
		if (ret) {
			DPRINTK(1, "write_to_device error !!(%d)\n", ret);
			queue_delayed_work(priv->wq, &priv->rw_dwork, 1);
			return;
		}
	}
	kfree(sp->sendp);
	if (sp->complete_handler)	/* TX Complete */
		(*sp->complete_handler)(priv, sp->skb);
	inc_txqhead(priv);

	if (cnt_txqbody(priv) > 0)
		queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
}
示例#2
0
static void tx_device_task(void *dev)
{
	struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
	struct tx_device_buffer *sp;
	int rc = 0;

	DPRINTK(4, "\n");
	if (cnt_txqbody(priv) > 0
	    && atomic_read(&priv->psstatus.status) != PS_SNOOZE) {
		sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
		if (priv->dev_state >= DEVICE_STATE_BOOT) {
			rc = write_to_device(priv, sp->sendp, sp->size);
			if (rc) {
				DPRINTK(1, "write_to_device error !!(%d)\n",
					rc);
				queue_delayed_work(priv->ks_wlan_hw.
						   ks7010sdio_wq,
						   &priv->ks_wlan_hw.rw_wq, 1);
				return;
			}

		}
		kfree(sp->sendp);	/* allocated memory free */
		if (sp->complete_handler != NULL)	/* TX Complete */
			(*sp->complete_handler) (sp->arg1, sp->arg2);
		inc_txqhead(priv);

		if (cnt_txqbody(priv) > 0) {
			queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
					   &priv->ks_wlan_hw.rw_wq, 0);
		}
	}
	return;
}
示例#3
0
static void _ks_wlan_hw_power_save(struct ks_wlan_private *priv)
{
	unsigned char byte;
	int ret;

	if (priv->reg.power_mgmt == POWER_MGMT_ACTIVE)
		return;

	if (priv->reg.operation_mode != MODE_INFRASTRUCTURE)
		return;

	if (!is_connect_status(priv->connect_status))
		return;

	if (priv->dev_state != DEVICE_STATE_SLEEP)
		return;

	if (atomic_read(&priv->psstatus.status) == PS_SNOOZE)
		return;

	DPRINTK(5, "\npsstatus.status=%d\npsstatus.confirm_wait=%d\npsstatus.snooze_guard=%d\ncnt_txqbody=%d\n",
		atomic_read(&priv->psstatus.status),
		atomic_read(&priv->psstatus.confirm_wait),
		atomic_read(&priv->psstatus.snooze_guard),
		cnt_txqbody(priv));

	if (atomic_read(&priv->psstatus.confirm_wait) ||
	    atomic_read(&priv->psstatus.snooze_guard) ||
	    cnt_txqbody(priv)) {
		queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
		return;
	}

	ret = ks7010_sdio_readb(priv, INT_PENDING, &byte);
	if (ret) {
		DPRINTK(1, " error : INT_PENDING\n");
		goto queue_delayed_work;
	}
	if (byte)
		goto queue_delayed_work;

	ret = ks7010_sdio_writeb(priv, GCR_B, GCR_B_DOZE);
	if (ret) {
		DPRINTK(1, " error : GCR_B\n");
		goto queue_delayed_work;
	}
	atomic_set(&priv->psstatus.status, PS_SNOOZE);
	DPRINTK(3, "psstatus.status=PS_SNOOZE\n");

	return;

queue_delayed_work:
	queue_delayed_work(priv->wq, &priv->rw_dwork, 1);
}
示例#4
0
int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
		  void (*complete_handler)(struct ks_wlan_private *priv,
					   struct sk_buff *skb),
		  struct sk_buff *skb)
{
	int result = 0;
	struct hostif_hdr *hdr;

	hdr = (struct hostif_hdr *)p;

	if (le16_to_cpu(hdr->event) < HIF_DATA_REQ ||
	    le16_to_cpu(hdr->event) > HIF_REQ_MAX) {
		DPRINTK(1, "unknown event=%04X\n", hdr->event);
		return 0;
	}

	/* add event to hostt buffer */
	priv->hostt.buff[priv->hostt.qtail] = le16_to_cpu(hdr->event);
	priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;

	DPRINTK(4, "event=%04X\n", hdr->event);
	spin_lock(&priv->tx_dev.tx_dev_lock);
	result = enqueue_txdev(priv, p, size, complete_handler, skb);
	spin_unlock(&priv->tx_dev.tx_dev_lock);

	if (cnt_txqbody(priv) > 0)
		queue_delayed_work(priv->wq, &priv->rw_dwork, 0);

	return result;
}
示例#5
0
int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
		  void (*complete_handler) (void *arg1, void *arg2),
		  void *arg1, void *arg2)
{
	int result = 0;
	struct hostif_hdr *hdr;
	hdr = (struct hostif_hdr *)p;

	if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
		DPRINTK(1, "unknown event=%04X\n", hdr->event);
		return 0;
	}

	/* add event to hostt buffer */
	priv->hostt.buff[priv->hostt.qtail] = hdr->event;
	priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;

	DPRINTK(4, "event=%04X\n", hdr->event);
	spin_lock(&priv->tx_dev.tx_dev_lock);
	result = enqueue_txdev(priv, p, size, complete_handler, arg1, arg2);
	spin_unlock(&priv->tx_dev.tx_dev_lock);

	if (cnt_txqbody(priv) > 0) {
		queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
				   &priv->ks_wlan_hw.rw_wq, 0);
	}
	return result;
}
示例#6
0
static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p,
			 unsigned long size,
			 void (*complete_handler) (void *arg1, void *arg2),
			 void *arg1, void *arg2)
{
	struct tx_device_buffer *sp;

	if (priv->dev_state < DEVICE_STATE_BOOT) {
		kfree(p);
		if (complete_handler != NULL)
			(*complete_handler) (arg1, arg2);
		return 1;
	}

	if ((TX_DEVICE_BUFF_SIZE - 1) <= cnt_txqbody(priv)) {
		/* in case of buffer overflow */
		DPRINTK(1, "tx buffer overflow\n");
		kfree(p);
		if (complete_handler != NULL)
			(*complete_handler) (arg1, arg2);
		return 1;
	}

	sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qtail];
	sp->sendp = p;
	sp->size = size;
	sp->complete_handler = complete_handler;
	sp->arg1 = arg1;
	sp->arg2 = arg2;
	inc_txqtail(priv);

	return 0;
}
示例#7
0
static void trx_device_exit(struct ks_wlan_private *priv)
{
	struct tx_device_buffer *sp;

	/* tx buffer clear */
	while (cnt_txqbody(priv) > 0) {
		sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
		kfree(sp->sendp);
		if (sp->complete_handler)	/* TX Complete */
			(*sp->complete_handler)(priv, sp->skb);
		inc_txqhead(priv);
	}

	tasklet_kill(&priv->rx_bh_task);
}
示例#8
0
static void trx_device_exit(struct ks_wlan_private *priv)
{
	struct tx_device_buffer *sp;

	/* tx buffer clear */
	while (cnt_txqbody(priv) > 0) {
		sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
		kfree(sp->sendp);	/* allocated memory free */
		if (sp->complete_handler != NULL)	/* TX Complete */
			(*sp->complete_handler) (sp->arg1, sp->arg2);
		inc_txqhead(priv);
	}

	tasklet_kill(&priv->ks_wlan_hw.rx_bh_task);

	return;
}
示例#9
0
static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p,
			 unsigned long size,
			 void (*complete_handler)(struct ks_wlan_private *priv,
						  struct sk_buff *skb),
			 struct sk_buff *skb)
{
	struct tx_device_buffer *sp;
	int ret;

	if (priv->dev_state < DEVICE_STATE_BOOT) {
		ret = -EPERM;
		goto err_complete;
	}

	if ((TX_DEVICE_BUFF_SIZE - 1) <= cnt_txqbody(priv)) {
		DPRINTK(1, "tx buffer overflow\n");
		ret = -EOVERFLOW;
		goto err_complete;
	}

	sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qtail];
	sp->sendp = p;
	sp->size = size;
	sp->complete_handler = complete_handler;
	sp->skb = skb;
	inc_txqtail(priv);

	return 0;

err_complete:
	kfree(p);
	if (complete_handler)
		(*complete_handler)(priv, skb);

	return ret;
}
示例#10
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);
}
示例#11
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);
}
示例#12
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;
}
示例#13
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;
}
示例#14
0
int _ks_wlan_hw_power_save(struct ks_wlan_private *priv)
{
	int rc = 0;
	unsigned char rw_data;
	int retval;

	if (priv->reg.powermgt == POWMGT_ACTIVE_MODE)
		return rc;

	if (priv->reg.operation_mode == MODE_INFRASTRUCTURE &&
	    (priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {

		//DPRINTK(1,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status));
		if (priv->dev_state == DEVICE_STATE_SLEEP) {
			switch (atomic_read(&priv->psstatus.status)) {
			case PS_SNOOZE:	/* 4 */
				break;
			default:
				DPRINTK(5, "\npsstatus.status=%d\npsstatus.confirm_wait=%d\npsstatus.snooze_guard=%d\ncnt_txqbody=%d\n",
					atomic_read(&priv->psstatus.status),
					atomic_read(&priv->psstatus.confirm_wait),
					atomic_read(&priv->psstatus.snooze_guard),
					cnt_txqbody(priv));

				if (!atomic_read(&priv->psstatus.confirm_wait)
				    && !atomic_read(&priv->psstatus.snooze_guard)
				    && !cnt_txqbody(priv)) {
					retval =
					    ks7010_sdio_read(priv, INT_PENDING,
							     &rw_data,
							     sizeof(rw_data));
					if (retval) {
						DPRINTK(1,
							" error : INT_PENDING=%02X\n",
							rw_data);
						queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
								   &priv->ks_wlan_hw.rw_wq, 1);
						break;
					}
					if (!rw_data) {
						rw_data = GCR_B_DOZE;
						retval =
						    ks7010_sdio_write(priv,
								      GCR_B,
								      &rw_data,
								      sizeof(rw_data));
						if (retval) {
							DPRINTK(1,
								" error : GCR_B=%02X\n",
								rw_data);
							queue_delayed_work
							    (priv->ks_wlan_hw.ks7010sdio_wq,
							     &priv->ks_wlan_hw.rw_wq, 1);
							break;
						}
						DPRINTK(4,
							"PMG SET!! : GCR_B=%02X\n",
							rw_data);
						atomic_set(&priv->psstatus.
							   status, PS_SNOOZE);
						DPRINTK(3,
							"psstatus.status=PS_SNOOZE\n");
					} else {
						queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
								   &priv->ks_wlan_hw.rw_wq, 1);
					}
				} else {
					queue_delayed_work(priv->ks_wlan_hw.
							   ks7010sdio_wq,
							   &priv->ks_wlan_hw.rw_wq,
							   0);
				}
				break;
			}
		}

	}

	return rc;
}