diff options
Diffstat (limited to 'drivers/staging/wilc1000/wilc_wlan.c')
-rw-r--r-- | drivers/staging/wilc1000/wilc_wlan.c | 501 |
1 files changed, 262 insertions, 239 deletions
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index acaeafc2c350..bcbb92323a0a 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -173,11 +173,13 @@ static inline int update_tcp_session(u32 index, u32 ack) static inline int add_tcp_pending_ack(u32 ack, u32 session_index, struct txq_entry_t *txqe) { - if (pending_base + pending_acks < MAX_PENDING_ACKS) { - pending_acks_info[pending_base + pending_acks].ack_num = ack; - pending_acks_info[pending_base + pending_acks].txqe = txqe; - pending_acks_info[pending_base + pending_acks].session_index = session_index; - txqe->tcp_pending_ack_idx = pending_base + pending_acks; + u32 i = pending_base + pending_acks; + + if (i < MAX_PENDING_ACKS) { + pending_acks_info[i].ack_num = ack; + pending_acks_info[i].txqe = txqe; + pending_acks_info[i].session_index = session_index; + txqe->tcp_pending_ack_idx = i; pending_acks++; } return 0; @@ -230,8 +232,10 @@ static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe) (u32)tcp_hdr_ptr[11]; for (i = 0; i < tcp_session; i++) { + u32 j = ack_session_info[i].seq_num; + if (i < 2 * MAX_TCP_SESSION && - ack_session_info[i].seq_num == seq_no) { + j == seq_no) { update_tcp_session(i, ack_no); break; } @@ -258,10 +262,20 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags); for (i = pending_base; i < (pending_base + pending_acks); i++) { - if (i >= MAX_PENDING_ACKS || - pending_acks_info[i].session_index >= 2 * MAX_TCP_SESSION) + u32 session_index; + u32 bigger_ack_num; + + if (i >= MAX_PENDING_ACKS) break; - if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) { + + session_index = pending_acks_info[i].session_index; + + if (session_index >= 2 * MAX_TCP_SESSION) + break; + + bigger_ack_num = ack_session_info[session_index].bigger_ack_num; + + if (pending_acks_info[i].ack_num < bigger_ack_num) { struct txq_entry_t *tqe; tqe = pending_acks_info[i].txqe; @@ -562,197 +576,196 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) u32 vmm_table[WILC_VMM_TBL_SIZE]; struct wilc_vif *vif; struct wilc *wilc; + const struct wilc_hif_func *func; vif = netdev_priv(dev); wilc = vif->wilc; txb = wilc->tx_buffer; wilc->txq_exit = 0; + + if (wilc->quit) + goto out; + + mutex_lock(&wilc->txq_add_to_head_cs); + wilc_wlan_txq_filter_dup_tcp_ack(dev); + tqe = wilc_wlan_txq_get_first(wilc); + i = 0; + sum = 0; do { - if (wilc->quit) - break; + if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) { + if (tqe->type == WILC_CFG_PKT) + vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET; - mutex_lock(&wilc->txq_add_to_head_cs); - wilc_wlan_txq_filter_dup_tcp_ack(dev); - tqe = wilc_wlan_txq_get_first(wilc); - i = 0; - sum = 0; - do { - if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) { - if (tqe->type == WILC_CFG_PKT) - vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET; + else if (tqe->type == WILC_NET_PKT) + vmm_sz = ETH_ETHERNET_HDR_OFFSET; + + else + vmm_sz = HOST_HDR_OFFSET; + + vmm_sz += tqe->buffer_size; + + if (vmm_sz & 0x3) + vmm_sz = (vmm_sz + 4) & ~0x3; - else if (tqe->type == WILC_NET_PKT) - vmm_sz = ETH_ETHERNET_HDR_OFFSET; + if ((sum + vmm_sz) > LINUX_TX_SIZE) + break; - else - vmm_sz = HOST_HDR_OFFSET; + vmm_table[i] = vmm_sz / 4; + if (tqe->type == WILC_CFG_PKT) + vmm_table[i] |= BIT(10); + vmm_table[i] = cpu_to_le32(vmm_table[i]); - vmm_sz += tqe->buffer_size; + i++; + sum += vmm_sz; + tqe = wilc_wlan_txq_get_next(wilc, tqe); + } else { + break; + } + } while (1); + + if (i == 0) + goto out; + vmm_table[i] = 0x0; + + acquire_bus(wilc, ACQUIRE_AND_WAKEUP); + counter = 0; + func = wilc->hif_func; + do { + ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); + if (!ret) + break; - if (vmm_sz & 0x3) - vmm_sz = (vmm_sz + 4) & ~0x3; + if ((reg & 0x1) == 0) + break; - if ((sum + vmm_sz) > LINUX_TX_SIZE) - break; + counter++; + if (counter > 200) { + counter = 0; + ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); + break; + } + } while (!wilc->quit); - vmm_table[i] = vmm_sz / 4; - if (tqe->type == WILC_CFG_PKT) - vmm_table[i] |= BIT(10); - vmm_table[i] = cpu_to_le32(vmm_table[i]); + if (!ret) + goto out_release_bus; - i++; - sum += vmm_sz; - tqe = wilc_wlan_txq_get_next(wilc, tqe); - } else { - break; - } - } while (1); + timeout = 200; + do { + ret = func->hif_block_tx(wilc, + WILC_VMM_TBL_RX_SHADOW_BASE, + (u8 *)vmm_table, + ((i + 1) * 4)); + if (!ret) + break; - if (i == 0) + ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2); + if (!ret) break; - vmm_table[i] = 0x0; - acquire_bus(wilc, ACQUIRE_AND_WAKEUP); - counter = 0; do { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_HOST_TX_CTRL, - ®); + ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); if (!ret) break; - - if ((reg & 0x1) == 0) - break; - - counter++; - if (counter > 200) { - counter = 0; - ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); + if ((reg >> 2) & 0x1) { + entries = ((reg >> 3) & 0x3f); break; } - } while (!wilc->quit); + release_bus(wilc, RELEASE_ALLOW_SLEEP); + } while (--timeout); + if (timeout <= 0) { + ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0); + break; + } if (!ret) - goto _end_; + break; - timeout = 200; - do { - ret = wilc->hif_func->hif_block_tx(wilc, WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4)); + if (entries == 0) { + ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); if (!ret) break; - - ret = wilc->hif_func->hif_write_reg(wilc, - WILC_HOST_VMM_CTL, - 0x2); + reg &= ~BIT(0); + ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); if (!ret) break; + break; + } + break; + } while (1); - do { - ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); - if (!ret) - break; - if ((reg >> 2) & 0x1) { - entries = ((reg >> 3) & 0x3f); - break; - } - release_bus(wilc, RELEASE_ALLOW_SLEEP); - } while (--timeout); - if (timeout <= 0) { - ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0); - break; - } + if (!ret) + goto out_release_bus; - if (!ret) - break; + if (entries == 0) { + ret = WILC_TX_ERR_NO_BUF; + goto out_release_bus; + } - if (entries == 0) { - ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) - break; - reg &= ~BIT(0); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); - if (!ret) - break; - break; - } + release_bus(wilc, RELEASE_ALLOW_SLEEP); + + offset = 0; + i = 0; + do { + u32 header, buffer_offset; + char *bssid; + + tqe = wilc_wlan_txq_remove_from_head(dev); + if (!tqe) break; - } while (1); - if (!ret) - goto _end_; + if (vmm_table[i] == 0) + break; - if (entries == 0) { - ret = WILC_TX_ERR_NO_BUF; - goto _end_; - } + vmm_table[i] = cpu_to_le32(vmm_table[i]); + vmm_sz = (vmm_table[i] & 0x3ff); + vmm_sz *= 4; + header = (tqe->type << 31) | + (tqe->buffer_size << 15) | + vmm_sz; + if (tqe->type == WILC_MGMT_PKT) + header |= BIT(30); + else + header &= ~BIT(30); - release_bus(wilc, RELEASE_ALLOW_SLEEP); + header = cpu_to_le32(header); + memcpy(&txb[offset], &header, 4); + if (tqe->type == WILC_CFG_PKT) { + buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; + } else if (tqe->type == WILC_NET_PKT) { + bssid = ((struct tx_complete_data *)(tqe->priv))->bssid; - offset = 0; - i = 0; - do { - tqe = wilc_wlan_txq_remove_from_head(dev); - if (tqe && vmm_table[i] != 0) { - u32 header, buffer_offset; - - vmm_table[i] = cpu_to_le32(vmm_table[i]); - vmm_sz = (vmm_table[i] & 0x3ff); - vmm_sz *= 4; - header = (tqe->type << 31) | - (tqe->buffer_size << 15) | - vmm_sz; - if (tqe->type == WILC_MGMT_PKT) - header |= BIT(30); - else - header &= ~BIT(30); - - header = cpu_to_le32(header); - memcpy(&txb[offset], &header, 4); - if (tqe->type == WILC_CFG_PKT) { - buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; - } else if (tqe->type == WILC_NET_PKT) { - char *bssid = ((struct tx_complete_data *)(tqe->priv))->bssid; - - buffer_offset = ETH_ETHERNET_HDR_OFFSET; - memcpy(&txb[offset + 8], bssid, 6); - } else { - buffer_offset = HOST_HDR_OFFSET; - } + buffer_offset = ETH_ETHERNET_HDR_OFFSET; + memcpy(&txb[offset + 8], bssid, 6); + } else { + buffer_offset = HOST_HDR_OFFSET; + } - memcpy(&txb[offset + buffer_offset], - tqe->buffer, tqe->buffer_size); - offset += vmm_sz; - i++; - tqe->status = 1; - if (tqe->tx_complete_func) - tqe->tx_complete_func(tqe->priv, - tqe->status); - if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK && - tqe->tcp_pending_ack_idx < MAX_PENDING_ACKS) - pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL; - kfree(tqe); - } else { - break; - } - } while (--entries); + memcpy(&txb[offset + buffer_offset], + tqe->buffer, tqe->buffer_size); + offset += vmm_sz; + i++; + tqe->status = 1; + if (tqe->tx_complete_func) + tqe->tx_complete_func(tqe->priv, tqe->status); + if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK && + tqe->tcp_pending_ack_idx < MAX_PENDING_ACKS) + pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL; + kfree(tqe); + } while (--entries); - acquire_bus(wilc, ACQUIRE_AND_WAKEUP); + acquire_bus(wilc, ACQUIRE_AND_WAKEUP); - ret = wilc->hif_func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); - if (!ret) - goto _end_; + ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); + if (!ret) + goto out_release_bus; - ret = wilc->hif_func->hif_block_tx_ext(wilc, 0, txb, offset); - if (!ret) - goto _end_; + ret = func->hif_block_tx_ext(wilc, 0, txb, offset); -_end_: +out_release_bus: + release_bus(wilc, RELEASE_ALLOW_SLEEP); - release_bus(wilc, RELEASE_ALLOW_SLEEP); - if (ret != 1) - break; - } while (0); +out: mutex_unlock(&wilc->txq_add_to_head_cs); wilc->txq_exit = 1; @@ -760,9 +773,70 @@ _end_: return ret; } +static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) +{ + int offset = 0; + u32 header; + u32 pkt_len, pkt_offset, tp_len; + int is_cfg_packet; + u8 *buff_ptr; + + do { + buff_ptr = buffer + offset; + memcpy(&header, buff_ptr, 4); + header = cpu_to_le32(header); + + is_cfg_packet = (header >> 31) & 0x1; + pkt_offset = (header >> 22) & 0x1ff; + tp_len = (header >> 11) & 0x7ff; + pkt_len = header & 0x7ff; + + if (pkt_len == 0 || tp_len == 0) + break; + + if (pkt_offset & IS_MANAGMEMENT) { + pkt_offset &= ~(IS_MANAGMEMENT | + IS_MANAGMEMENT_CALLBACK | + IS_MGMT_STATUS_SUCCES); + buff_ptr += HOST_HDR_OFFSET; + wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len); + } else { + if (!is_cfg_packet) { + if (pkt_len > 0) { + wilc_frmw_to_linux(wilc, buff_ptr, + pkt_len, + pkt_offset); + } + } else { + struct wilc_cfg_rsp rsp; + + buff_ptr += pkt_offset; + + wilc_wlan_cfg_indicate_rx(wilc, buff_ptr, + pkt_len, + &rsp); + if (rsp.type == WILC_CFG_RSP) { + if (wilc->cfg_seq_no == rsp.seq_no) + complete(&wilc->cfg_event); + } else if (rsp.type == WILC_CFG_RSP_STATUS) { + wilc_mac_indicate(wilc, + WILC_MAC_INDICATE_STATUS); + + } else if (rsp.type == WILC_CFG_RSP_SCAN) { + wilc_mac_indicate(wilc, + WILC_MAC_INDICATE_SCAN); + } + } + } + offset += tp_len; + if (offset >= size) + break; + } while (1); +} + static void wilc_wlan_handle_rxq(struct wilc *wilc) { - int offset = 0, size; + int size; u8 *buffer; struct rxq_entry_t *rqe; @@ -779,61 +853,8 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) buffer = rqe->buffer; size = rqe->buffer_size; - offset = 0; - - do { - u32 header; - u32 pkt_len, pkt_offset, tp_len; - int is_cfg_packet; + wilc_wlan_handle_rx_buff(wilc, buffer, size); - memcpy(&header, &buffer[offset], 4); - header = cpu_to_le32(header); - - is_cfg_packet = (header >> 31) & 0x1; - pkt_offset = (header >> 22) & 0x1ff; - tp_len = (header >> 11) & 0x7ff; - pkt_len = header & 0x7ff; - - if (pkt_len == 0 || tp_len == 0) - break; - - #define IS_MANAGMEMENT 0x100 - #define IS_MANAGMEMENT_CALLBACK 0x080 - #define IS_MGMT_STATUS_SUCCES 0x040 - - if (pkt_offset & IS_MANAGMEMENT) { - pkt_offset &= ~(IS_MANAGMEMENT | - IS_MANAGMEMENT_CALLBACK | - IS_MGMT_STATUS_SUCCES); - - WILC_WFI_mgmt_rx(wilc, &buffer[offset + HOST_HDR_OFFSET], pkt_len); - } else { - if (!is_cfg_packet) { - if (pkt_len > 0) { - wilc_frmw_to_linux(wilc, - &buffer[offset], - pkt_len, - pkt_offset); - } - } else { - struct wilc_cfg_rsp rsp; - - wilc_wlan_cfg_indicate_rx(wilc, &buffer[pkt_offset + offset], pkt_len, &rsp); - if (rsp.type == WILC_CFG_RSP) { - if (wilc->cfg_seq_no == rsp.seq_no) - complete(&wilc->cfg_event); - } else if (rsp.type == WILC_CFG_RSP_STATUS) { - wilc_mac_indicate(wilc, WILC_MAC_INDICATE_STATUS); - - } else if (rsp.type == WILC_CFG_RSP_SCAN) { - wilc_mac_indicate(wilc, WILC_MAC_INDICATE_SCAN); - } - } - } - offset += tp_len; - if (offset >= size) - break; - } while (1); kfree(rqe); } while (1); @@ -1216,27 +1237,28 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, offset += ret_size; wilc->cfg_frame_offset = offset; - if (commit) { - netdev_dbg(vif->ndev, - "[WILC]PACKET Commit with sequence number %d\n", - wilc->cfg_seq_no); - netdev_dbg(vif->ndev, "Processing cfg_set()\n"); - wilc->cfg_frame_in_use = 1; + if (!commit) + return ret_size; - if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler)) - ret_size = 0; + netdev_dbg(vif->ndev, + "[WILC]PACKET Commit with sequence number %d\n", + wilc->cfg_seq_no); + netdev_dbg(vif->ndev, "Processing cfg_set()\n"); + wilc->cfg_frame_in_use = 1; - if (!wait_for_completion_timeout(&wilc->cfg_event, - msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { - netdev_dbg(vif->ndev, "Set Timed Out\n"); - ret_size = 0; - } + if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler)) + ret_size = 0; - wilc->cfg_frame_in_use = 0; - wilc->cfg_frame_offset = 0; - wilc->cfg_seq_no += 1; + if (!wait_for_completion_timeout(&wilc->cfg_event, + msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { + netdev_dbg(vif->ndev, "Set Timed Out\n"); + ret_size = 0; } + wilc->cfg_frame_in_use = 0; + wilc->cfg_frame_offset = 0; + wilc->cfg_seq_no += 1; + return ret_size; } @@ -1258,21 +1280,22 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, offset += ret_size; wilc->cfg_frame_offset = offset; - if (commit) { - wilc->cfg_frame_in_use = 1; + if (!commit) + return ret_size; - if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler)) - ret_size = 0; + wilc->cfg_frame_in_use = 1; - if (!wait_for_completion_timeout(&wilc->cfg_event, - msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { - netdev_dbg(vif->ndev, "Get Timed Out\n"); - ret_size = 0; - } - wilc->cfg_frame_in_use = 0; - wilc->cfg_frame_offset = 0; - wilc->cfg_seq_no += 1; + if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler)) + ret_size = 0; + + if (!wait_for_completion_timeout(&wilc->cfg_event, + msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { + netdev_dbg(vif->ndev, "Get Timed Out\n"); + ret_size = 0; } + wilc->cfg_frame_in_use = 0; + wilc->cfg_frame_offset = 0; + wilc->cfg_seq_no += 1; return ret_size; } |