summaryrefslogtreecommitdiff
path: root/drivers/staging/wilc1000/wilc_wlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/wilc1000/wilc_wlan.c')
-rw-r--r--drivers/staging/wilc1000/wilc_wlan.c501
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, &reg);
+ 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,
- &reg);
+ ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, &reg);
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, &reg);
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, &reg);
- 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, &reg);
- 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;
}