diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 89 |
1 files changed, 61 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7d614c4d3c62..55a1b31fd09a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -233,6 +233,7 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
233 | { | 233 | { |
234 | unsigned long flags; | 234 | unsigned long flags; |
235 | u16 ra_tid; | 235 | u16 ra_tid; |
236 | int ret; | ||
236 | 237 | ||
237 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | 238 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || |
238 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 239 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
@@ -248,7 +249,9 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
248 | ra_tid = BUILD_RAxTID(sta_id, tid); | 249 | ra_tid = BUILD_RAxTID(sta_id, tid); |
249 | 250 | ||
250 | /* Modify device's station table to Tx this TID */ | 251 | /* Modify device's station table to Tx this TID */ |
251 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | 252 | ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); |
253 | if (ret) | ||
254 | return ret; | ||
252 | 255 | ||
253 | spin_lock_irqsave(&priv->lock, flags); | 256 | spin_lock_irqsave(&priv->lock, flags); |
254 | 257 | ||
@@ -469,7 +472,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
469 | } | 472 | } |
470 | 473 | ||
471 | /* Set up antennas */ | 474 | /* Set up antennas */ |
472 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | 475 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
476 | priv->hw_params.valid_tx_ant); | ||
473 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 477 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
474 | 478 | ||
475 | /* Set the rate in the TX cmd */ | 479 | /* Set the rate in the TX cmd */ |
@@ -567,10 +571,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
567 | hdr_len = ieee80211_hdrlen(fc); | 571 | hdr_len = ieee80211_hdrlen(fc); |
568 | 572 | ||
569 | /* Find index into station table for destination station */ | 573 | /* Find index into station table for destination station */ |
570 | if (!info->control.sta) | 574 | sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); |
571 | sta_id = priv->hw_params.bcast_sta_id; | ||
572 | else | ||
573 | sta_id = iwl_sta_id(info->control.sta); | ||
574 | if (sta_id == IWL_INVALID_STATION) { | 575 | if (sta_id == IWL_INVALID_STATION) { |
575 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 576 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
576 | hdr->addr1); | 577 | hdr->addr1); |
@@ -598,11 +599,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
598 | } | 599 | } |
599 | 600 | ||
600 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | 601 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); |
602 | |||
603 | /* irqs already disabled/saved above when locking priv->lock */ | ||
604 | spin_lock(&priv->sta_lock); | ||
605 | |||
601 | if (ieee80211_is_data_qos(fc)) { | 606 | if (ieee80211_is_data_qos(fc)) { |
602 | qc = ieee80211_get_qos_ctl(hdr); | 607 | qc = ieee80211_get_qos_ctl(hdr); |
603 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 608 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
604 | if (unlikely(tid >= MAX_TID_COUNT)) | 609 | if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) { |
610 | spin_unlock(&priv->sta_lock); | ||
605 | goto drop_unlock; | 611 | goto drop_unlock; |
612 | } | ||
606 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | 613 | seq_number = priv->stations[sta_id].tid[tid].seq_number; |
607 | seq_number &= IEEE80211_SCTL_SEQ; | 614 | seq_number &= IEEE80211_SCTL_SEQ; |
608 | hdr->seq_ctrl = hdr->seq_ctrl & | 615 | hdr->seq_ctrl = hdr->seq_ctrl & |
@@ -620,15 +627,22 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
620 | swq_id = txq->swq_id; | 627 | swq_id = txq->swq_id; |
621 | q = &txq->q; | 628 | q = &txq->q; |
622 | 629 | ||
623 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | 630 | if (unlikely(iwl_queue_space(q) < q->high_mark)) { |
631 | spin_unlock(&priv->sta_lock); | ||
624 | goto drop_unlock; | 632 | goto drop_unlock; |
633 | } | ||
625 | 634 | ||
626 | if (ieee80211_is_data_qos(fc)) | 635 | if (ieee80211_is_data_qos(fc)) { |
627 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | 636 | priv->stations[sta_id].tid[tid].tfds_in_queue++; |
637 | if (!ieee80211_has_morefrags(fc)) | ||
638 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
639 | } | ||
640 | |||
641 | spin_unlock(&priv->sta_lock); | ||
628 | 642 | ||
629 | /* Set up driver data for this TFD */ | 643 | /* Set up driver data for this TFD */ |
630 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 644 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
631 | txq->txb[q->write_ptr].skb[0] = skb; | 645 | txq->txb[q->write_ptr].skb = skb; |
632 | 646 | ||
633 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 647 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
634 | out_cmd = txq->cmd[q->write_ptr]; | 648 | out_cmd = txq->cmd[q->write_ptr]; |
@@ -694,8 +708,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
694 | txcmd_phys = pci_map_single(priv->pci_dev, | 708 | txcmd_phys = pci_map_single(priv->pci_dev, |
695 | &out_cmd->hdr, len, | 709 | &out_cmd->hdr, len, |
696 | PCI_DMA_BIDIRECTIONAL); | 710 | PCI_DMA_BIDIRECTIONAL); |
697 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | 711 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
698 | pci_unmap_len_set(out_meta, len, len); | 712 | dma_unmap_len_set(out_meta, len, len); |
699 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 713 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
700 | * first entry */ | 714 | * first entry */ |
701 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 715 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
@@ -703,8 +717,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
703 | 717 | ||
704 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 718 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
705 | txq->need_update = 1; | 719 | txq->need_update = 1; |
706 | if (qc) | ||
707 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
708 | } else { | 720 | } else { |
709 | wait_write_ptr = 1; | 721 | wait_write_ptr = 1; |
710 | txq->need_update = 0; | 722 | txq->need_update = 0; |
@@ -938,9 +950,12 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | |||
938 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 950 | /* Stop each Tx DMA channel, and wait for it to be idle */ |
939 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | 951 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { |
940 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | 952 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); |
941 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | 953 | if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, |
942 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | 954 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), |
943 | 1000); | 955 | 1000)) |
956 | IWL_ERR(priv, "Failing on timeout while stopping" | ||
957 | " DMA channel %d [0x%08x]", ch, | ||
958 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); | ||
944 | } | 959 | } |
945 | spin_unlock_irqrestore(&priv->lock, flags); | 960 | spin_unlock_irqrestore(&priv->lock, flags); |
946 | } | 961 | } |
@@ -1009,6 +1024,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1009 | if (ret) | 1024 | if (ret) |
1010 | return ret; | 1025 | return ret; |
1011 | 1026 | ||
1027 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1028 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1012 | if (tid_data->tfds_in_queue == 0) { | 1029 | if (tid_data->tfds_in_queue == 0) { |
1013 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1030 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1014 | tid_data->agg.state = IWL_AGG_ON; | 1031 | tid_data->agg.state = IWL_AGG_ON; |
@@ -1018,6 +1035,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1018 | tid_data->tfds_in_queue); | 1035 | tid_data->tfds_in_queue); |
1019 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | 1036 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; |
1020 | } | 1037 | } |
1038 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1021 | return ret; | 1039 | return ret; |
1022 | } | 1040 | } |
1023 | 1041 | ||
@@ -1040,11 +1058,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1040 | return -ENXIO; | 1058 | return -ENXIO; |
1041 | } | 1059 | } |
1042 | 1060 | ||
1061 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1062 | |||
1043 | if (priv->stations[sta_id].tid[tid].agg.state == | 1063 | if (priv->stations[sta_id].tid[tid].agg.state == |
1044 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | 1064 | IWL_EMPTYING_HW_QUEUE_ADDBA) { |
1045 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | 1065 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); |
1046 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1066 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1047 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1067 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1068 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1048 | return 0; | 1069 | return 0; |
1049 | } | 1070 | } |
1050 | 1071 | ||
@@ -1062,13 +1083,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1062 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | 1083 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); |
1063 | priv->stations[sta_id].tid[tid].agg.state = | 1084 | priv->stations[sta_id].tid[tid].agg.state = |
1064 | IWL_EMPTYING_HW_QUEUE_DELBA; | 1085 | IWL_EMPTYING_HW_QUEUE_DELBA; |
1086 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1065 | return 0; | 1087 | return 0; |
1066 | } | 1088 | } |
1067 | 1089 | ||
1068 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1090 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1069 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1091 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1070 | 1092 | ||
1071 | spin_lock_irqsave(&priv->lock, flags); | 1093 | /* do not restore/save irqs */ |
1094 | spin_unlock(&priv->sta_lock); | ||
1095 | spin_lock(&priv->lock); | ||
1096 | |||
1072 | /* | 1097 | /* |
1073 | * the only reason this call can fail is queue number out of range, | 1098 | * the only reason this call can fail is queue number out of range, |
1074 | * which can happen if uCode is reloaded and all the station | 1099 | * which can happen if uCode is reloaded and all the station |
@@ -1092,6 +1117,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1092 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | 1117 | u8 *addr = priv->stations[sta_id].sta.sta.addr; |
1093 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | 1118 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; |
1094 | 1119 | ||
1120 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | ||
1121 | |||
1095 | switch (priv->stations[sta_id].tid[tid].agg.state) { | 1122 | switch (priv->stations[sta_id].tid[tid].agg.state) { |
1096 | case IWL_EMPTYING_HW_QUEUE_DELBA: | 1123 | case IWL_EMPTYING_HW_QUEUE_DELBA: |
1097 | /* We are reclaiming the last packet of the */ | 1124 | /* We are reclaiming the last packet of the */ |
@@ -1116,6 +1143,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1116 | } | 1143 | } |
1117 | break; | 1144 | break; |
1118 | } | 1145 | } |
1146 | |||
1119 | return 0; | 1147 | return 0; |
1120 | } | 1148 | } |
1121 | 1149 | ||
@@ -1159,12 +1187,12 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1159 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1187 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1160 | 1188 | ||
1161 | tx_info = &txq->txb[txq->q.read_ptr]; | 1189 | tx_info = &txq->txb[txq->q.read_ptr]; |
1162 | iwlagn_tx_status(priv, tx_info->skb[0]); | 1190 | iwlagn_tx_status(priv, tx_info->skb); |
1163 | 1191 | ||
1164 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | 1192 | hdr = (struct ieee80211_hdr *)tx_info->skb->data; |
1165 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | 1193 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) |
1166 | nfreed++; | 1194 | nfreed++; |
1167 | tx_info->skb[0] = NULL; | 1195 | tx_info->skb = NULL; |
1168 | 1196 | ||
1169 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | 1197 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) |
1170 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | 1198 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); |
@@ -1188,7 +1216,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1188 | int i, sh, ack; | 1216 | int i, sh, ack; |
1189 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | 1217 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); |
1190 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 1218 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
1191 | u64 bitmap; | 1219 | u64 bitmap, sent_bitmap; |
1192 | int successes = 0; | 1220 | int successes = 0; |
1193 | struct ieee80211_tx_info *info; | 1221 | struct ieee80211_tx_info *info; |
1194 | 1222 | ||
@@ -1216,24 +1244,26 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1216 | 1244 | ||
1217 | /* check for success or failure according to the | 1245 | /* check for success or failure according to the |
1218 | * transmitted bitmap and block-ack bitmap */ | 1246 | * transmitted bitmap and block-ack bitmap */ |
1219 | bitmap &= agg->bitmap; | 1247 | sent_bitmap = bitmap & agg->bitmap; |
1220 | 1248 | ||
1221 | /* For each frame attempted in aggregation, | 1249 | /* For each frame attempted in aggregation, |
1222 | * update driver's record of tx frame's status. */ | 1250 | * update driver's record of tx frame's status. */ |
1223 | for (i = 0; i < agg->frame_count ; i++) { | 1251 | i = 0; |
1224 | ack = bitmap & (1ULL << i); | 1252 | while (sent_bitmap) { |
1225 | successes += !!ack; | 1253 | ack = sent_bitmap & 1ULL; |
1254 | successes += ack; | ||
1226 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | 1255 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", |
1227 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | 1256 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, |
1228 | agg->start_idx + i); | 1257 | agg->start_idx + i); |
1258 | sent_bitmap >>= 1; | ||
1259 | ++i; | ||
1229 | } | 1260 | } |
1230 | 1261 | ||
1231 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | 1262 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); |
1232 | memset(&info->status, 0, sizeof(info->status)); | 1263 | memset(&info->status, 0, sizeof(info->status)); |
1233 | info->flags |= IEEE80211_TX_STAT_ACK; | 1264 | info->flags |= IEEE80211_TX_STAT_ACK; |
1234 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 1265 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
1235 | info->status.ampdu_ack_len = successes; | 1266 | info->status.ampdu_ack_len = successes; |
1236 | info->status.ampdu_ack_map = bitmap; | ||
1237 | info->status.ampdu_len = agg->frame_count; | 1267 | info->status.ampdu_len = agg->frame_count; |
1238 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | 1268 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); |
1239 | 1269 | ||
@@ -1281,6 +1311,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1281 | int index; | 1311 | int index; |
1282 | int sta_id; | 1312 | int sta_id; |
1283 | int tid; | 1313 | int tid; |
1314 | unsigned long flags; | ||
1284 | 1315 | ||
1285 | /* "flow" corresponds to Tx queue */ | 1316 | /* "flow" corresponds to Tx queue */ |
1286 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 1317 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
@@ -1308,7 +1339,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1308 | /* Find index just before block-ack window */ | 1339 | /* Find index just before block-ack window */ |
1309 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | 1340 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); |
1310 | 1341 | ||
1311 | /* TODO: Need to get this copy more safely - now good for debug */ | 1342 | spin_lock_irqsave(&priv->sta_lock, flags); |
1312 | 1343 | ||
1313 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | 1344 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " |
1314 | "sta_id = %d\n", | 1345 | "sta_id = %d\n", |
@@ -1344,4 +1375,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1344 | 1375 | ||
1345 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); | 1376 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); |
1346 | } | 1377 | } |
1378 | |||
1379 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1347 | } | 1380 | } |