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); }
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; }
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); }
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; }
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; }
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; }
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); }
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; }
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; }
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); }
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); }
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; }
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; }
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; }