diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2008-05-15 01:54:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:00 -0400 |
commit | fd4abac54a7a7f1c0acad5ddc1fbf4af22f92569 (patch) | |
tree | 78e95821800cfa2b2a8ded7ecc1e51227e194e1a /drivers/net/wireless/iwlwifi/iwl4965-base.c | |
parent | 54dbb525e7b8580b86af352cf60b27cc889c2ae4 (diff) |
iwlwifi: move TX code into iwl-tx.c
This patch moves the sending part of the TX code into iwl-tx.c
including sending host commands.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl4965-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 581 |
1 files changed, 1 insertions, 580 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index e3f872e3381d..dd2fd4055306 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -53,8 +53,6 @@ | |||
53 | #include "iwl-sta.h" | 53 | #include "iwl-sta.h" |
54 | #include "iwl-calib.h" | 54 | #include "iwl-calib.h" |
55 | 55 | ||
56 | static int iwl_txq_update_write_ptr(struct iwl_priv *priv, | ||
57 | struct iwl_tx_queue *txq); | ||
58 | 56 | ||
59 | /****************************************************************************** | 57 | /****************************************************************************** |
60 | * | 58 | * |
@@ -135,69 +133,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len) | |||
135 | return escaped; | 133 | return escaped; |
136 | } | 134 | } |
137 | 135 | ||
138 | |||
139 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** | ||
140 | * DMA services | ||
141 | * | ||
142 | * Theory of operation | ||
143 | * | ||
144 | * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer | ||
145 | * of buffer descriptors, each of which points to one or more data buffers for | ||
146 | * the device to read from or fill. Driver and device exchange status of each | ||
147 | * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty | ||
148 | * entries in each circular buffer, to protect against confusing empty and full | ||
149 | * queue states. | ||
150 | * | ||
151 | * The device reads or writes the data in the queues via the device's several | ||
152 | * DMA/FIFO channels. Each queue is mapped to a single DMA channel. | ||
153 | * | ||
154 | * For Tx queue, there are low mark and high mark limits. If, after queuing | ||
155 | * the packet for Tx, free space become < low mark, Tx queue stopped. When | ||
156 | * reclaiming packets (on 'tx done IRQ), if free space become > high mark, | ||
157 | * Tx queue resumed. | ||
158 | * | ||
159 | * The 4965 operates with up to 17 queues: One receive queue, one transmit | ||
160 | * queue (#4) for sending commands to the device firmware, and 15 other | ||
161 | * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels. | ||
162 | * | ||
163 | * See more detailed info in iwl-4965-hw.h. | ||
164 | ***************************************************/ | ||
165 | |||
166 | int iwl_queue_space(const struct iwl_queue *q) | ||
167 | { | ||
168 | int s = q->read_ptr - q->write_ptr; | ||
169 | |||
170 | if (q->read_ptr > q->write_ptr) | ||
171 | s -= q->n_bd; | ||
172 | |||
173 | if (s <= 0) | ||
174 | s += q->n_window; | ||
175 | /* keep some reserve to not confuse empty and full situations */ | ||
176 | s -= 2; | ||
177 | if (s < 0) | ||
178 | s = 0; | ||
179 | return s; | ||
180 | } | ||
181 | |||
182 | |||
183 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) | ||
184 | { | ||
185 | return q->write_ptr > q->read_ptr ? | ||
186 | (i >= q->read_ptr && i < q->write_ptr) : | ||
187 | !(i < q->read_ptr && i >= q->write_ptr); | ||
188 | } | ||
189 | |||
190 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | ||
191 | { | ||
192 | /* This is for scan command, the big buffer at end of command array */ | ||
193 | if (is_huge) | ||
194 | return q->n_window; /* must be power of 2 */ | ||
195 | |||
196 | /* Otherwise, use normal size buffers */ | ||
197 | return index & (q->n_window - 1); | ||
198 | } | ||
199 | |||
200 | |||
201 | /*************** STATION TABLE MANAGEMENT **** | 136 | /*************** STATION TABLE MANAGEMENT **** |
202 | * mac80211 should be examined to determine if sta_info is duplicating | 137 | * mac80211 should be examined to determine if sta_info is duplicating |
203 | * the functionality provided here | 138 | * the functionality provided here |
@@ -250,95 +185,6 @@ out: | |||
250 | 185 | ||
251 | 186 | ||
252 | 187 | ||
253 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | ||
254 | |||
255 | /** | ||
256 | * iwl4965_enqueue_hcmd - enqueue a uCode command | ||
257 | * @priv: device private data point | ||
258 | * @cmd: a point to the ucode command structure | ||
259 | * | ||
260 | * The function returns < 0 values to indicate the operation is | ||
261 | * failed. On success, it turns the index (> 0) of command in the | ||
262 | * command queue. | ||
263 | */ | ||
264 | int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | ||
265 | { | ||
266 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | ||
267 | struct iwl_queue *q = &txq->q; | ||
268 | struct iwl_tfd_frame *tfd; | ||
269 | u32 *control_flags; | ||
270 | struct iwl_cmd *out_cmd; | ||
271 | u32 idx; | ||
272 | u16 fix_size; | ||
273 | dma_addr_t phys_addr; | ||
274 | int ret; | ||
275 | unsigned long flags; | ||
276 | |||
277 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); | ||
278 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); | ||
279 | |||
280 | /* If any of the command structures end up being larger than | ||
281 | * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then | ||
282 | * we will need to increase the size of the TFD entries */ | ||
283 | BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && | ||
284 | !(cmd->meta.flags & CMD_SIZE_HUGE)); | ||
285 | |||
286 | if (iwl_is_rfkill(priv)) { | ||
287 | IWL_DEBUG_INFO("Not sending command - RF KILL"); | ||
288 | return -EIO; | ||
289 | } | ||
290 | |||
291 | if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { | ||
292 | IWL_ERROR("No space for Tx\n"); | ||
293 | return -ENOSPC; | ||
294 | } | ||
295 | |||
296 | spin_lock_irqsave(&priv->hcmd_lock, flags); | ||
297 | |||
298 | tfd = &txq->bd[q->write_ptr]; | ||
299 | memset(tfd, 0, sizeof(*tfd)); | ||
300 | |||
301 | control_flags = (u32 *) tfd; | ||
302 | |||
303 | idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); | ||
304 | out_cmd = &txq->cmd[idx]; | ||
305 | |||
306 | out_cmd->hdr.cmd = cmd->id; | ||
307 | memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); | ||
308 | memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); | ||
309 | |||
310 | /* At this point, the out_cmd now has all of the incoming cmd | ||
311 | * information */ | ||
312 | |||
313 | out_cmd->hdr.flags = 0; | ||
314 | out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | | ||
315 | INDEX_TO_SEQ(q->write_ptr)); | ||
316 | if (out_cmd->meta.flags & CMD_SIZE_HUGE) | ||
317 | out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); | ||
318 | |||
319 | phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + | ||
320 | offsetof(struct iwl_cmd, hdr); | ||
321 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); | ||
322 | |||
323 | IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " | ||
324 | "%d bytes at %d[%d]:%d\n", | ||
325 | get_cmd_string(out_cmd->hdr.cmd), | ||
326 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), | ||
327 | fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM); | ||
328 | |||
329 | txq->need_update = 1; | ||
330 | |||
331 | /* Set up entry in queue's byte count circular buffer */ | ||
332 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); | ||
333 | |||
334 | /* Increment and update queue's write index */ | ||
335 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
336 | ret = iwl_txq_update_write_ptr(priv, txq); | ||
337 | |||
338 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | ||
339 | return ret ? ret : idx; | ||
340 | } | ||
341 | |||
342 | static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | 188 | static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) |
343 | { | 189 | { |
344 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 190 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
@@ -1453,385 +1299,6 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) | |||
1453 | return 0; | 1299 | return 0; |
1454 | } | 1300 | } |
1455 | 1301 | ||
1456 | static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | ||
1457 | struct ieee80211_tx_control *ctl, | ||
1458 | struct iwl_cmd *cmd, | ||
1459 | struct sk_buff *skb_frag, | ||
1460 | int sta_id) | ||
1461 | { | ||
1462 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | ||
1463 | struct iwl_wep_key *wepkey; | ||
1464 | int keyidx = 0; | ||
1465 | |||
1466 | BUG_ON(ctl->hw_key->hw_key_idx > 3); | ||
1467 | |||
1468 | switch (keyinfo->alg) { | ||
1469 | case ALG_CCMP: | ||
1470 | cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM; | ||
1471 | memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen); | ||
1472 | if (ctl->flags & IEEE80211_TXCTL_AMPDU) | ||
1473 | cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
1474 | IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n"); | ||
1475 | break; | ||
1476 | |||
1477 | case ALG_TKIP: | ||
1478 | cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP; | ||
1479 | ieee80211_get_tkip_key(keyinfo->conf, skb_frag, | ||
1480 | IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key); | ||
1481 | IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n"); | ||
1482 | break; | ||
1483 | |||
1484 | case ALG_WEP: | ||
1485 | wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx]; | ||
1486 | cmd->cmd.tx.sec_ctl = 0; | ||
1487 | if (priv->default_wep_key) { | ||
1488 | /* the WEP key was sent as static */ | ||
1489 | keyidx = ctl->hw_key->hw_key_idx; | ||
1490 | memcpy(&cmd->cmd.tx.key[3], wepkey->key, | ||
1491 | wepkey->key_size); | ||
1492 | if (wepkey->key_size == WEP_KEY_LEN_128) | ||
1493 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | ||
1494 | } else { | ||
1495 | /* the WEP key was sent as dynamic */ | ||
1496 | keyidx = keyinfo->keyidx; | ||
1497 | memcpy(&cmd->cmd.tx.key[3], keyinfo->key, | ||
1498 | keyinfo->keylen); | ||
1499 | if (keyinfo->keylen == WEP_KEY_LEN_128) | ||
1500 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | ||
1501 | } | ||
1502 | |||
1503 | cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP | | ||
1504 | (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
1505 | |||
1506 | IWL_DEBUG_TX("Configuring packet for WEP encryption " | ||
1507 | "with key %d\n", keyidx); | ||
1508 | break; | ||
1509 | |||
1510 | default: | ||
1511 | printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg); | ||
1512 | break; | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | /* | ||
1517 | * handle build REPLY_TX command notification. | ||
1518 | */ | ||
1519 | static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv, | ||
1520 | struct iwl_cmd *cmd, | ||
1521 | struct ieee80211_tx_control *ctrl, | ||
1522 | struct ieee80211_hdr *hdr, | ||
1523 | int is_unicast, u8 std_id) | ||
1524 | { | ||
1525 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
1526 | __le32 tx_flags = cmd->cmd.tx.tx_flags; | ||
1527 | |||
1528 | cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
1529 | if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) { | ||
1530 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
1531 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) | ||
1532 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
1533 | if (ieee80211_is_probe_response(fc) && | ||
1534 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
1535 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
1536 | } else { | ||
1537 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
1538 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
1539 | } | ||
1540 | |||
1541 | if (ieee80211_is_back_request(fc)) | ||
1542 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
1543 | |||
1544 | |||
1545 | cmd->cmd.tx.sta_id = std_id; | ||
1546 | if (ieee80211_get_morefrag(hdr)) | ||
1547 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
1548 | |||
1549 | if (ieee80211_is_qos_data(fc)) { | ||
1550 | u8 *qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc)); | ||
1551 | cmd->cmd.tx.tid_tspec = qc[0] & 0xf; | ||
1552 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
1553 | } else { | ||
1554 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
1555 | } | ||
1556 | |||
1557 | if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) { | ||
1558 | tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
1559 | tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
1560 | } else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { | ||
1561 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
1562 | tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
1563 | } | ||
1564 | |||
1565 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
1566 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
1567 | |||
1568 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
1569 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { | ||
1570 | if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ || | ||
1571 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) | ||
1572 | cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); | ||
1573 | else | ||
1574 | cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); | ||
1575 | } else { | ||
1576 | cmd->cmd.tx.timeout.pm_frame_timeout = 0; | ||
1577 | } | ||
1578 | |||
1579 | cmd->cmd.tx.driver_txop = 0; | ||
1580 | cmd->cmd.tx.tx_flags = tx_flags; | ||
1581 | cmd->cmd.tx.next_frame_len = 0; | ||
1582 | } | ||
1583 | static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len) | ||
1584 | { | ||
1585 | /* 0 - mgmt, 1 - cnt, 2 - data */ | ||
1586 | int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2; | ||
1587 | priv->tx_stats[idx].cnt++; | ||
1588 | priv->tx_stats[idx].bytes += len; | ||
1589 | } | ||
1590 | /* | ||
1591 | * start REPLY_TX command process | ||
1592 | */ | ||
1593 | static int iwl4965_tx_skb(struct iwl_priv *priv, | ||
1594 | struct sk_buff *skb, struct ieee80211_tx_control *ctl) | ||
1595 | { | ||
1596 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1597 | struct iwl_tfd_frame *tfd; | ||
1598 | u32 *control_flags; | ||
1599 | int txq_id = ctl->queue; | ||
1600 | struct iwl_tx_queue *txq = NULL; | ||
1601 | struct iwl_queue *q = NULL; | ||
1602 | dma_addr_t phys_addr; | ||
1603 | dma_addr_t txcmd_phys; | ||
1604 | dma_addr_t scratch_phys; | ||
1605 | struct iwl_cmd *out_cmd = NULL; | ||
1606 | u16 len, idx, len_org; | ||
1607 | u8 hdr_len; | ||
1608 | u8 id; | ||
1609 | u8 unicast; | ||
1610 | u8 sta_id; | ||
1611 | u8 tid = 0; | ||
1612 | u8 wait_write_ptr = 0; | ||
1613 | u16 seq_number = 0; | ||
1614 | u16 fc; | ||
1615 | u8 *qc = NULL; | ||
1616 | unsigned long flags; | ||
1617 | int rc; | ||
1618 | |||
1619 | spin_lock_irqsave(&priv->lock, flags); | ||
1620 | if (iwl_is_rfkill(priv)) { | ||
1621 | IWL_DEBUG_DROP("Dropping - RF KILL\n"); | ||
1622 | goto drop_unlock; | ||
1623 | } | ||
1624 | |||
1625 | if (!priv->vif) { | ||
1626 | IWL_DEBUG_DROP("Dropping - !priv->vif\n"); | ||
1627 | goto drop_unlock; | ||
1628 | } | ||
1629 | |||
1630 | if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { | ||
1631 | IWL_ERROR("ERROR: No TX rate available.\n"); | ||
1632 | goto drop_unlock; | ||
1633 | } | ||
1634 | |||
1635 | unicast = !is_multicast_ether_addr(hdr->addr1); | ||
1636 | id = 0; | ||
1637 | |||
1638 | fc = le16_to_cpu(hdr->frame_control); | ||
1639 | |||
1640 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1641 | if (ieee80211_is_auth(fc)) | ||
1642 | IWL_DEBUG_TX("Sending AUTH frame\n"); | ||
1643 | else if (ieee80211_is_assoc_request(fc)) | ||
1644 | IWL_DEBUG_TX("Sending ASSOC frame\n"); | ||
1645 | else if (ieee80211_is_reassoc_request(fc)) | ||
1646 | IWL_DEBUG_TX("Sending REASSOC frame\n"); | ||
1647 | #endif | ||
1648 | |||
1649 | /* drop all data frame if we are not associated */ | ||
1650 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | ||
1651 | (!iwl_is_associated(priv) || | ||
1652 | ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || | ||
1653 | !priv->assoc_station_added)) { | ||
1654 | IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); | ||
1655 | goto drop_unlock; | ||
1656 | } | ||
1657 | |||
1658 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1659 | |||
1660 | hdr_len = ieee80211_get_hdrlen(fc); | ||
1661 | |||
1662 | /* Find (or create) index into station table for destination station */ | ||
1663 | sta_id = iwl_get_sta_id(priv, hdr); | ||
1664 | if (sta_id == IWL_INVALID_STATION) { | ||
1665 | DECLARE_MAC_BUF(mac); | ||
1666 | |||
1667 | IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n", | ||
1668 | print_mac(mac, hdr->addr1)); | ||
1669 | goto drop; | ||
1670 | } | ||
1671 | |||
1672 | IWL_DEBUG_TX("station Id %d\n", sta_id); | ||
1673 | |||
1674 | if (ieee80211_is_qos_data(fc)) { | ||
1675 | qc = ieee80211_get_qos_ctrl(hdr, hdr_len); | ||
1676 | tid = qc[0] & 0xf; | ||
1677 | seq_number = priv->stations[sta_id].tid[tid].seq_number & | ||
1678 | IEEE80211_SCTL_SEQ; | ||
1679 | hdr->seq_ctrl = cpu_to_le16(seq_number) | | ||
1680 | (hdr->seq_ctrl & | ||
1681 | __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); | ||
1682 | seq_number += 0x10; | ||
1683 | #ifdef CONFIG_IWL4965_HT | ||
1684 | /* aggregation is on for this <sta,tid> */ | ||
1685 | if (ctl->flags & IEEE80211_TXCTL_AMPDU) | ||
1686 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
1687 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
1688 | #endif /* CONFIG_IWL4965_HT */ | ||
1689 | } | ||
1690 | |||
1691 | /* Descriptor for chosen Tx queue */ | ||
1692 | txq = &priv->txq[txq_id]; | ||
1693 | q = &txq->q; | ||
1694 | |||
1695 | spin_lock_irqsave(&priv->lock, flags); | ||
1696 | |||
1697 | /* Set up first empty TFD within this queue's circular TFD buffer */ | ||
1698 | tfd = &txq->bd[q->write_ptr]; | ||
1699 | memset(tfd, 0, sizeof(*tfd)); | ||
1700 | control_flags = (u32 *) tfd; | ||
1701 | idx = get_cmd_index(q, q->write_ptr, 0); | ||
1702 | |||
1703 | /* Set up driver data for this TFD */ | ||
1704 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
1705 | txq->txb[q->write_ptr].skb[0] = skb; | ||
1706 | memcpy(&(txq->txb[q->write_ptr].status.control), | ||
1707 | ctl, sizeof(struct ieee80211_tx_control)); | ||
1708 | |||
1709 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
1710 | out_cmd = &txq->cmd[idx]; | ||
1711 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
1712 | memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx)); | ||
1713 | |||
1714 | /* | ||
1715 | * Set up the Tx-command (not MAC!) header. | ||
1716 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
1717 | * after Tx, uCode's Tx response will return this value so driver can | ||
1718 | * locate the frame within the tx queue and do post-tx processing. | ||
1719 | */ | ||
1720 | out_cmd->hdr.cmd = REPLY_TX; | ||
1721 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
1722 | INDEX_TO_SEQ(q->write_ptr))); | ||
1723 | |||
1724 | /* Copy MAC header from skb into command buffer */ | ||
1725 | memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len); | ||
1726 | |||
1727 | /* | ||
1728 | * Use the first empty entry in this queue's command buffer array | ||
1729 | * to contain the Tx command and MAC header concatenated together | ||
1730 | * (payload data will be in another buffer). | ||
1731 | * Size of this varies, due to varying MAC header length. | ||
1732 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
1733 | * of the MAC header (device reads on dword boundaries). | ||
1734 | * We'll tell device about this padding later. | ||
1735 | */ | ||
1736 | len = sizeof(struct iwl_tx_cmd) + | ||
1737 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
1738 | |||
1739 | len_org = len; | ||
1740 | len = (len + 3) & ~3; | ||
1741 | |||
1742 | if (len_org != len) | ||
1743 | len_org = 1; | ||
1744 | else | ||
1745 | len_org = 0; | ||
1746 | |||
1747 | /* Physical address of this Tx command's header (not MAC header!), | ||
1748 | * within command buffer array. */ | ||
1749 | txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + | ||
1750 | offsetof(struct iwl_cmd, hdr); | ||
1751 | |||
1752 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
1753 | * first entry */ | ||
1754 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); | ||
1755 | |||
1756 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) | ||
1757 | iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id); | ||
1758 | |||
1759 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
1760 | * if any (802.11 null frames have no payload). */ | ||
1761 | len = skb->len - hdr_len; | ||
1762 | if (len) { | ||
1763 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
1764 | len, PCI_DMA_TODEVICE); | ||
1765 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len); | ||
1766 | } | ||
1767 | |||
1768 | /* Tell 4965 about any 2-byte padding after MAC header */ | ||
1769 | if (len_org) | ||
1770 | out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
1771 | |||
1772 | /* Total # bytes to be transmitted */ | ||
1773 | len = (u16)skb->len; | ||
1774 | out_cmd->cmd.tx.len = cpu_to_le16(len); | ||
1775 | |||
1776 | /* TODO need this for burst mode later on */ | ||
1777 | iwl4965_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id); | ||
1778 | |||
1779 | /* set is_hcca to 0; it probably will never be implemented */ | ||
1780 | iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0); | ||
1781 | |||
1782 | iwl_update_tx_stats(priv, fc, len); | ||
1783 | |||
1784 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
1785 | offsetof(struct iwl_tx_cmd, scratch); | ||
1786 | out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1787 | out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys); | ||
1788 | |||
1789 | if (!ieee80211_get_morefrag(hdr)) { | ||
1790 | txq->need_update = 1; | ||
1791 | if (qc) | ||
1792 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
1793 | } else { | ||
1794 | wait_write_ptr = 1; | ||
1795 | txq->need_update = 0; | ||
1796 | } | ||
1797 | |||
1798 | iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload, | ||
1799 | sizeof(out_cmd->cmd.tx)); | ||
1800 | |||
1801 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, | ||
1802 | ieee80211_get_hdrlen(fc)); | ||
1803 | |||
1804 | /* Set up entry for this TFD in Tx byte-count array */ | ||
1805 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len); | ||
1806 | |||
1807 | /* Tell device the write index *just past* this latest filled TFD */ | ||
1808 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
1809 | rc = iwl_txq_update_write_ptr(priv, txq); | ||
1810 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1811 | |||
1812 | if (rc) | ||
1813 | return rc; | ||
1814 | |||
1815 | if ((iwl_queue_space(q) < q->high_mark) | ||
1816 | && priv->mac80211_registered) { | ||
1817 | if (wait_write_ptr) { | ||
1818 | spin_lock_irqsave(&priv->lock, flags); | ||
1819 | txq->need_update = 1; | ||
1820 | iwl_txq_update_write_ptr(priv, txq); | ||
1821 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1822 | } | ||
1823 | |||
1824 | ieee80211_stop_queue(priv->hw, ctl->queue); | ||
1825 | } | ||
1826 | |||
1827 | return 0; | ||
1828 | |||
1829 | drop_unlock: | ||
1830 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1831 | drop: | ||
1832 | return -1; | ||
1833 | } | ||
1834 | |||
1835 | static void iwl4965_set_rate(struct iwl_priv *priv) | 1302 | static void iwl4965_set_rate(struct iwl_priv *priv) |
1836 | { | 1303 | { |
1837 | const struct ieee80211_supported_band *hw = NULL; | 1304 | const struct ieee80211_supported_band *hw = NULL; |
@@ -3101,52 +2568,6 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm) | |||
3101 | return sig_qual; | 2568 | return sig_qual; |
3102 | } | 2569 | } |
3103 | 2570 | ||
3104 | /** | ||
3105 | * iwl_txq_update_write_ptr - Send new write index to hardware | ||
3106 | */ | ||
3107 | static int iwl_txq_update_write_ptr(struct iwl_priv *priv, | ||
3108 | struct iwl_tx_queue *txq) | ||
3109 | { | ||
3110 | u32 reg = 0; | ||
3111 | int ret = 0; | ||
3112 | int txq_id = txq->q.id; | ||
3113 | |||
3114 | if (txq->need_update == 0) | ||
3115 | return ret; | ||
3116 | |||
3117 | /* if we're trying to save power */ | ||
3118 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
3119 | /* wake up nic if it's powered down ... | ||
3120 | * uCode will wake up, and interrupt us again, so next | ||
3121 | * time we'll skip this part. */ | ||
3122 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
3123 | |||
3124 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | ||
3125 | IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg); | ||
3126 | iwl_set_bit(priv, CSR_GP_CNTRL, | ||
3127 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
3128 | return ret; | ||
3129 | } | ||
3130 | |||
3131 | /* restore this queue's parameters in nic hardware. */ | ||
3132 | ret = iwl_grab_nic_access(priv); | ||
3133 | if (ret) | ||
3134 | return ret; | ||
3135 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
3136 | txq->q.write_ptr | (txq_id << 8)); | ||
3137 | iwl_release_nic_access(priv); | ||
3138 | |||
3139 | /* else not in power-save mode, uCode will never sleep when we're | ||
3140 | * trying to tx (during RFKILL, we're not trying to tx). */ | ||
3141 | } else | ||
3142 | iwl_write32(priv, HBUS_TARG_WRPTR, | ||
3143 | txq->q.write_ptr | (txq_id << 8)); | ||
3144 | |||
3145 | txq->need_update = 0; | ||
3146 | |||
3147 | return ret; | ||
3148 | } | ||
3149 | |||
3150 | #ifdef CONFIG_IWLWIFI_DEBUG | 2571 | #ifdef CONFIG_IWLWIFI_DEBUG |
3151 | static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv) | 2572 | static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv) |
3152 | { | 2573 | { |
@@ -4956,7 +4377,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
4956 | IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | 4377 | IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, |
4957 | ctl->tx_rate->bitrate); | 4378 | ctl->tx_rate->bitrate); |
4958 | 4379 | ||
4959 | if (iwl4965_tx_skb(priv, skb, ctl)) | 4380 | if (iwl_tx_skb(priv, skb, ctl)) |
4960 | dev_kfree_skb_any(skb); | 4381 | dev_kfree_skb_any(skb); |
4961 | 4382 | ||
4962 | IWL_DEBUG_MAC80211("leave\n"); | 4383 | IWL_DEBUG_MAC80211("leave\n"); |