diff options
Diffstat (limited to 'drivers')
193 files changed, 12880 insertions, 11723 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 293f9c16e786..3d52538df6c4 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -150,9 +150,8 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev, | |||
150 | unsigned long offset, | 150 | unsigned long offset, |
151 | enum dma_data_direction dir) | 151 | enum dma_data_direction dir) |
152 | { | 152 | { |
153 | ssb_dma_sync_single_range_for_device(sdev, dma_base, | 153 | dma_sync_single_for_device(sdev->dma_dev, dma_base + offset, |
154 | offset & dma_desc_align_mask, | 154 | dma_desc_sync_size, dir); |
155 | dma_desc_sync_size, dir); | ||
156 | } | 155 | } |
157 | 156 | ||
158 | static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, | 157 | static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, |
@@ -160,9 +159,8 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, | |||
160 | unsigned long offset, | 159 | unsigned long offset, |
161 | enum dma_data_direction dir) | 160 | enum dma_data_direction dir) |
162 | { | 161 | { |
163 | ssb_dma_sync_single_range_for_cpu(sdev, dma_base, | 162 | dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset, |
164 | offset & dma_desc_align_mask, | 163 | dma_desc_sync_size, dir); |
165 | dma_desc_sync_size, dir); | ||
166 | } | 164 | } |
167 | 165 | ||
168 | static inline unsigned long br32(const struct b44 *bp, unsigned long reg) | 166 | static inline unsigned long br32(const struct b44 *bp, unsigned long reg) |
@@ -608,10 +606,10 @@ static void b44_tx(struct b44 *bp) | |||
608 | 606 | ||
609 | BUG_ON(skb == NULL); | 607 | BUG_ON(skb == NULL); |
610 | 608 | ||
611 | ssb_dma_unmap_single(bp->sdev, | 609 | dma_unmap_single(bp->sdev->dma_dev, |
612 | rp->mapping, | 610 | rp->mapping, |
613 | skb->len, | 611 | skb->len, |
614 | DMA_TO_DEVICE); | 612 | DMA_TO_DEVICE); |
615 | rp->skb = NULL; | 613 | rp->skb = NULL; |
616 | dev_kfree_skb_irq(skb); | 614 | dev_kfree_skb_irq(skb); |
617 | } | 615 | } |
@@ -648,29 +646,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) | |||
648 | if (skb == NULL) | 646 | if (skb == NULL) |
649 | return -ENOMEM; | 647 | return -ENOMEM; |
650 | 648 | ||
651 | mapping = ssb_dma_map_single(bp->sdev, skb->data, | 649 | mapping = dma_map_single(bp->sdev->dma_dev, skb->data, |
652 | RX_PKT_BUF_SZ, | 650 | RX_PKT_BUF_SZ, |
653 | DMA_FROM_DEVICE); | 651 | DMA_FROM_DEVICE); |
654 | 652 | ||
655 | /* Hardware bug work-around, the chip is unable to do PCI DMA | 653 | /* Hardware bug work-around, the chip is unable to do PCI DMA |
656 | to/from anything above 1GB :-( */ | 654 | to/from anything above 1GB :-( */ |
657 | if (ssb_dma_mapping_error(bp->sdev, mapping) || | 655 | if (dma_mapping_error(bp->sdev->dma_dev, mapping) || |
658 | mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { | 656 | mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { |
659 | /* Sigh... */ | 657 | /* Sigh... */ |
660 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) | 658 | if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) |
661 | ssb_dma_unmap_single(bp->sdev, mapping, | 659 | dma_unmap_single(bp->sdev->dma_dev, mapping, |
662 | RX_PKT_BUF_SZ, DMA_FROM_DEVICE); | 660 | RX_PKT_BUF_SZ, DMA_FROM_DEVICE); |
663 | dev_kfree_skb_any(skb); | 661 | dev_kfree_skb_any(skb); |
664 | skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); | 662 | skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); |
665 | if (skb == NULL) | 663 | if (skb == NULL) |
666 | return -ENOMEM; | 664 | return -ENOMEM; |
667 | mapping = ssb_dma_map_single(bp->sdev, skb->data, | 665 | mapping = dma_map_single(bp->sdev->dma_dev, skb->data, |
668 | RX_PKT_BUF_SZ, | 666 | RX_PKT_BUF_SZ, |
669 | DMA_FROM_DEVICE); | 667 | DMA_FROM_DEVICE); |
670 | if (ssb_dma_mapping_error(bp->sdev, mapping) || | 668 | if (dma_mapping_error(bp->sdev->dma_dev, mapping) || |
671 | mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { | 669 | mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) { |
672 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) | 670 | if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) |
673 | ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); | 671 | dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); |
674 | dev_kfree_skb_any(skb); | 672 | dev_kfree_skb_any(skb); |
675 | return -ENOMEM; | 673 | return -ENOMEM; |
676 | } | 674 | } |
@@ -745,9 +743,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) | |||
745 | dest_idx * sizeof(*dest_desc), | 743 | dest_idx * sizeof(*dest_desc), |
746 | DMA_BIDIRECTIONAL); | 744 | DMA_BIDIRECTIONAL); |
747 | 745 | ||
748 | ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping, | 746 | dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping, |
749 | RX_PKT_BUF_SZ, | 747 | RX_PKT_BUF_SZ, |
750 | DMA_FROM_DEVICE); | 748 | DMA_FROM_DEVICE); |
751 | } | 749 | } |
752 | 750 | ||
753 | static int b44_rx(struct b44 *bp, int budget) | 751 | static int b44_rx(struct b44 *bp, int budget) |
@@ -767,9 +765,9 @@ static int b44_rx(struct b44 *bp, int budget) | |||
767 | struct rx_header *rh; | 765 | struct rx_header *rh; |
768 | u16 len; | 766 | u16 len; |
769 | 767 | ||
770 | ssb_dma_sync_single_for_cpu(bp->sdev, map, | 768 | dma_sync_single_for_cpu(bp->sdev->dma_dev, map, |
771 | RX_PKT_BUF_SZ, | 769 | RX_PKT_BUF_SZ, |
772 | DMA_FROM_DEVICE); | 770 | DMA_FROM_DEVICE); |
773 | rh = (struct rx_header *) skb->data; | 771 | rh = (struct rx_header *) skb->data; |
774 | len = le16_to_cpu(rh->len); | 772 | len = le16_to_cpu(rh->len); |
775 | if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) || | 773 | if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) || |
@@ -801,8 +799,8 @@ static int b44_rx(struct b44 *bp, int budget) | |||
801 | skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); | 799 | skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); |
802 | if (skb_size < 0) | 800 | if (skb_size < 0) |
803 | goto drop_it; | 801 | goto drop_it; |
804 | ssb_dma_unmap_single(bp->sdev, map, | 802 | dma_unmap_single(bp->sdev->dma_dev, map, |
805 | skb_size, DMA_FROM_DEVICE); | 803 | skb_size, DMA_FROM_DEVICE); |
806 | /* Leave out rx_header */ | 804 | /* Leave out rx_header */ |
807 | skb_put(skb, len + RX_PKT_OFFSET); | 805 | skb_put(skb, len + RX_PKT_OFFSET); |
808 | skb_pull(skb, RX_PKT_OFFSET); | 806 | skb_pull(skb, RX_PKT_OFFSET); |
@@ -954,24 +952,24 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
954 | goto err_out; | 952 | goto err_out; |
955 | } | 953 | } |
956 | 954 | ||
957 | mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE); | 955 | mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE); |
958 | if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) { | 956 | if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) { |
959 | struct sk_buff *bounce_skb; | 957 | struct sk_buff *bounce_skb; |
960 | 958 | ||
961 | /* Chip can't handle DMA to/from >1GB, use bounce buffer */ | 959 | /* Chip can't handle DMA to/from >1GB, use bounce buffer */ |
962 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) | 960 | if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) |
963 | ssb_dma_unmap_single(bp->sdev, mapping, len, | 961 | dma_unmap_single(bp->sdev->dma_dev, mapping, len, |
964 | DMA_TO_DEVICE); | 962 | DMA_TO_DEVICE); |
965 | 963 | ||
966 | bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA); | 964 | bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA); |
967 | if (!bounce_skb) | 965 | if (!bounce_skb) |
968 | goto err_out; | 966 | goto err_out; |
969 | 967 | ||
970 | mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data, | 968 | mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data, |
971 | len, DMA_TO_DEVICE); | 969 | len, DMA_TO_DEVICE); |
972 | if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) { | 970 | if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) { |
973 | if (!ssb_dma_mapping_error(bp->sdev, mapping)) | 971 | if (!dma_mapping_error(bp->sdev->dma_dev, mapping)) |
974 | ssb_dma_unmap_single(bp->sdev, mapping, | 972 | dma_unmap_single(bp->sdev->dma_dev, mapping, |
975 | len, DMA_TO_DEVICE); | 973 | len, DMA_TO_DEVICE); |
976 | dev_kfree_skb_any(bounce_skb); | 974 | dev_kfree_skb_any(bounce_skb); |
977 | goto err_out; | 975 | goto err_out; |
@@ -1068,8 +1066,8 @@ static void b44_free_rings(struct b44 *bp) | |||
1068 | 1066 | ||
1069 | if (rp->skb == NULL) | 1067 | if (rp->skb == NULL) |
1070 | continue; | 1068 | continue; |
1071 | ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ, | 1069 | dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ, |
1072 | DMA_FROM_DEVICE); | 1070 | DMA_FROM_DEVICE); |
1073 | dev_kfree_skb_any(rp->skb); | 1071 | dev_kfree_skb_any(rp->skb); |
1074 | rp->skb = NULL; | 1072 | rp->skb = NULL; |
1075 | } | 1073 | } |
@@ -1080,8 +1078,8 @@ static void b44_free_rings(struct b44 *bp) | |||
1080 | 1078 | ||
1081 | if (rp->skb == NULL) | 1079 | if (rp->skb == NULL) |
1082 | continue; | 1080 | continue; |
1083 | ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len, | 1081 | dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len, |
1084 | DMA_TO_DEVICE); | 1082 | DMA_TO_DEVICE); |
1085 | dev_kfree_skb_any(rp->skb); | 1083 | dev_kfree_skb_any(rp->skb); |
1086 | rp->skb = NULL; | 1084 | rp->skb = NULL; |
1087 | } | 1085 | } |
@@ -1103,14 +1101,12 @@ static void b44_init_rings(struct b44 *bp) | |||
1103 | memset(bp->tx_ring, 0, B44_TX_RING_BYTES); | 1101 | memset(bp->tx_ring, 0, B44_TX_RING_BYTES); |
1104 | 1102 | ||
1105 | if (bp->flags & B44_FLAG_RX_RING_HACK) | 1103 | if (bp->flags & B44_FLAG_RX_RING_HACK) |
1106 | ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma, | 1104 | dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma, |
1107 | DMA_TABLE_BYTES, | 1105 | DMA_TABLE_BYTES, DMA_BIDIRECTIONAL); |
1108 | DMA_BIDIRECTIONAL); | ||
1109 | 1106 | ||
1110 | if (bp->flags & B44_FLAG_TX_RING_HACK) | 1107 | if (bp->flags & B44_FLAG_TX_RING_HACK) |
1111 | ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma, | 1108 | dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma, |
1112 | DMA_TABLE_BYTES, | 1109 | DMA_TABLE_BYTES, DMA_TO_DEVICE); |
1113 | DMA_TO_DEVICE); | ||
1114 | 1110 | ||
1115 | for (i = 0; i < bp->rx_pending; i++) { | 1111 | for (i = 0; i < bp->rx_pending; i++) { |
1116 | if (b44_alloc_rx_skb(bp, -1, i) < 0) | 1112 | if (b44_alloc_rx_skb(bp, -1, i) < 0) |
@@ -1130,27 +1126,23 @@ static void b44_free_consistent(struct b44 *bp) | |||
1130 | bp->tx_buffers = NULL; | 1126 | bp->tx_buffers = NULL; |
1131 | if (bp->rx_ring) { | 1127 | if (bp->rx_ring) { |
1132 | if (bp->flags & B44_FLAG_RX_RING_HACK) { | 1128 | if (bp->flags & B44_FLAG_RX_RING_HACK) { |
1133 | ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma, | 1129 | dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma, |
1134 | DMA_TABLE_BYTES, | 1130 | DMA_TABLE_BYTES, DMA_BIDIRECTIONAL); |
1135 | DMA_BIDIRECTIONAL); | ||
1136 | kfree(bp->rx_ring); | 1131 | kfree(bp->rx_ring); |
1137 | } else | 1132 | } else |
1138 | ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, | 1133 | dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, |
1139 | bp->rx_ring, bp->rx_ring_dma, | 1134 | bp->rx_ring, bp->rx_ring_dma); |
1140 | GFP_KERNEL); | ||
1141 | bp->rx_ring = NULL; | 1135 | bp->rx_ring = NULL; |
1142 | bp->flags &= ~B44_FLAG_RX_RING_HACK; | 1136 | bp->flags &= ~B44_FLAG_RX_RING_HACK; |
1143 | } | 1137 | } |
1144 | if (bp->tx_ring) { | 1138 | if (bp->tx_ring) { |
1145 | if (bp->flags & B44_FLAG_TX_RING_HACK) { | 1139 | if (bp->flags & B44_FLAG_TX_RING_HACK) { |
1146 | ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma, | 1140 | dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma, |
1147 | DMA_TABLE_BYTES, | 1141 | DMA_TABLE_BYTES, DMA_TO_DEVICE); |
1148 | DMA_TO_DEVICE); | ||
1149 | kfree(bp->tx_ring); | 1142 | kfree(bp->tx_ring); |
1150 | } else | 1143 | } else |
1151 | ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, | 1144 | dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, |
1152 | bp->tx_ring, bp->tx_ring_dma, | 1145 | bp->tx_ring, bp->tx_ring_dma); |
1153 | GFP_KERNEL); | ||
1154 | bp->tx_ring = NULL; | 1146 | bp->tx_ring = NULL; |
1155 | bp->flags &= ~B44_FLAG_TX_RING_HACK; | 1147 | bp->flags &= ~B44_FLAG_TX_RING_HACK; |
1156 | } | 1148 | } |
@@ -1175,7 +1167,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1175 | goto out_err; | 1167 | goto out_err; |
1176 | 1168 | ||
1177 | size = DMA_TABLE_BYTES; | 1169 | size = DMA_TABLE_BYTES; |
1178 | bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp); | 1170 | bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, |
1171 | &bp->rx_ring_dma, gfp); | ||
1179 | if (!bp->rx_ring) { | 1172 | if (!bp->rx_ring) { |
1180 | /* Allocation may have failed due to pci_alloc_consistent | 1173 | /* Allocation may have failed due to pci_alloc_consistent |
1181 | insisting on use of GFP_DMA, which is more restrictive | 1174 | insisting on use of GFP_DMA, which is more restrictive |
@@ -1187,11 +1180,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1187 | if (!rx_ring) | 1180 | if (!rx_ring) |
1188 | goto out_err; | 1181 | goto out_err; |
1189 | 1182 | ||
1190 | rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring, | 1183 | rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring, |
1191 | DMA_TABLE_BYTES, | 1184 | DMA_TABLE_BYTES, |
1192 | DMA_BIDIRECTIONAL); | 1185 | DMA_BIDIRECTIONAL); |
1193 | 1186 | ||
1194 | if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) || | 1187 | if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) || |
1195 | rx_ring_dma + size > DMA_BIT_MASK(30)) { | 1188 | rx_ring_dma + size > DMA_BIT_MASK(30)) { |
1196 | kfree(rx_ring); | 1189 | kfree(rx_ring); |
1197 | goto out_err; | 1190 | goto out_err; |
@@ -1202,7 +1195,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1202 | bp->flags |= B44_FLAG_RX_RING_HACK; | 1195 | bp->flags |= B44_FLAG_RX_RING_HACK; |
1203 | } | 1196 | } |
1204 | 1197 | ||
1205 | bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp); | 1198 | bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, |
1199 | &bp->tx_ring_dma, gfp); | ||
1206 | if (!bp->tx_ring) { | 1200 | if (!bp->tx_ring) { |
1207 | /* Allocation may have failed due to ssb_dma_alloc_consistent | 1201 | /* Allocation may have failed due to ssb_dma_alloc_consistent |
1208 | insisting on use of GFP_DMA, which is more restrictive | 1202 | insisting on use of GFP_DMA, which is more restrictive |
@@ -1214,11 +1208,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) | |||
1214 | if (!tx_ring) | 1208 | if (!tx_ring) |
1215 | goto out_err; | 1209 | goto out_err; |
1216 | 1210 | ||
1217 | tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring, | 1211 | tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring, |
1218 | DMA_TABLE_BYTES, | 1212 | DMA_TABLE_BYTES, |
1219 | DMA_TO_DEVICE); | 1213 | DMA_TO_DEVICE); |
1220 | 1214 | ||
1221 | if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) || | 1215 | if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) || |
1222 | tx_ring_dma + size > DMA_BIT_MASK(30)) { | 1216 | tx_ring_dma + size > DMA_BIT_MASK(30)) { |
1223 | kfree(tx_ring); | 1217 | kfree(tx_ring); |
1224 | goto out_err; | 1218 | goto out_err; |
@@ -2176,12 +2170,14 @@ static int __devinit b44_init_one(struct ssb_device *sdev, | |||
2176 | "Failed to powerup the bus\n"); | 2170 | "Failed to powerup the bus\n"); |
2177 | goto err_out_free_dev; | 2171 | goto err_out_free_dev; |
2178 | } | 2172 | } |
2179 | err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30)); | 2173 | |
2180 | if (err) { | 2174 | if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) || |
2175 | dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) { | ||
2181 | dev_err(sdev->dev, | 2176 | dev_err(sdev->dev, |
2182 | "Required 30BIT DMA mask unsupported by the system\n"); | 2177 | "Required 30BIT DMA mask unsupported by the system\n"); |
2183 | goto err_out_powerdown; | 2178 | goto err_out_powerdown; |
2184 | } | 2179 | } |
2180 | |||
2185 | err = b44_get_invariants(bp); | 2181 | err = b44_get_invariants(bp); |
2186 | if (err) { | 2182 | if (err) { |
2187 | dev_err(sdev->dev, | 2183 | dev_err(sdev->dev, |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 8a2d4afc74f8..98328b7f8332 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com> | 7 | * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com> |
8 | * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org> | 8 | * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org> |
9 | * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi> | 9 | * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi> |
10 | * Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net> | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License as | 13 | * modify it under the terms of the GNU General Public License as |
@@ -1649,6 +1650,58 @@ exit: | |||
1649 | return NULL; | 1650 | return NULL; |
1650 | } | 1651 | } |
1651 | 1652 | ||
1653 | static int at76_join(struct at76_priv *priv) | ||
1654 | { | ||
1655 | struct at76_req_join join; | ||
1656 | int ret; | ||
1657 | |||
1658 | memset(&join, 0, sizeof(struct at76_req_join)); | ||
1659 | memcpy(join.essid, priv->essid, priv->essid_size); | ||
1660 | join.essid_size = priv->essid_size; | ||
1661 | memcpy(join.bssid, priv->bssid, ETH_ALEN); | ||
1662 | join.bss_type = INFRASTRUCTURE_MODE; | ||
1663 | join.channel = priv->channel; | ||
1664 | join.timeout = cpu_to_le16(2000); | ||
1665 | |||
1666 | at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__); | ||
1667 | ret = at76_set_card_command(priv->udev, CMD_JOIN, &join, | ||
1668 | sizeof(struct at76_req_join)); | ||
1669 | |||
1670 | if (ret < 0) { | ||
1671 | printk(KERN_ERR "%s: at76_set_card_command failed: %d\n", | ||
1672 | wiphy_name(priv->hw->wiphy), ret); | ||
1673 | return 0; | ||
1674 | } | ||
1675 | |||
1676 | ret = at76_wait_completion(priv, CMD_JOIN); | ||
1677 | at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret); | ||
1678 | if (ret != CMD_STATUS_COMPLETE) { | ||
1679 | printk(KERN_ERR "%s: at76_wait_completion failed: %d\n", | ||
1680 | wiphy_name(priv->hw->wiphy), ret); | ||
1681 | return 0; | ||
1682 | } | ||
1683 | |||
1684 | at76_set_pm_mode(priv); | ||
1685 | |||
1686 | return 0; | ||
1687 | } | ||
1688 | |||
1689 | static void at76_work_join_bssid(struct work_struct *work) | ||
1690 | { | ||
1691 | struct at76_priv *priv = container_of(work, struct at76_priv, | ||
1692 | work_join_bssid); | ||
1693 | |||
1694 | if (priv->device_unplugged) | ||
1695 | return; | ||
1696 | |||
1697 | mutex_lock(&priv->mtx); | ||
1698 | |||
1699 | if (is_valid_ether_addr(priv->bssid)) | ||
1700 | at76_join(priv); | ||
1701 | |||
1702 | mutex_unlock(&priv->mtx); | ||
1703 | } | ||
1704 | |||
1652 | static void at76_mac80211_tx_callback(struct urb *urb) | 1705 | static void at76_mac80211_tx_callback(struct urb *urb) |
1653 | { | 1706 | { |
1654 | struct at76_priv *priv = urb->context; | 1707 | struct at76_priv *priv = urb->context; |
@@ -1686,6 +1739,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1686 | struct at76_priv *priv = hw->priv; | 1739 | struct at76_priv *priv = hw->priv; |
1687 | struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer; | 1740 | struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer; |
1688 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1741 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1742 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | ||
1689 | int padding, submit_len, ret; | 1743 | int padding, submit_len, ret; |
1690 | 1744 | ||
1691 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1745 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
@@ -1696,6 +1750,21 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1696 | return NETDEV_TX_BUSY; | 1750 | return NETDEV_TX_BUSY; |
1697 | } | 1751 | } |
1698 | 1752 | ||
1753 | /* The following code lines are important when the device is going to | ||
1754 | * authenticate with a new bssid. The driver must send CMD_JOIN before | ||
1755 | * an authentication frame is transmitted. For this to succeed, the | ||
1756 | * correct bssid of the AP must be known. As mac80211 does not inform | ||
1757 | * drivers about the bssid prior to the authentication process the | ||
1758 | * following workaround is necessary. If the TX frame is an | ||
1759 | * authentication frame extract the bssid and send the CMD_JOIN. */ | ||
1760 | if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) { | ||
1761 | if (compare_ether_addr(priv->bssid, mgmt->bssid)) { | ||
1762 | memcpy(priv->bssid, mgmt->bssid, ETH_ALEN); | ||
1763 | ieee80211_queue_work(hw, &priv->work_join_bssid); | ||
1764 | return NETDEV_TX_BUSY; | ||
1765 | } | ||
1766 | } | ||
1767 | |||
1699 | ieee80211_stop_queues(hw); | 1768 | ieee80211_stop_queues(hw); |
1700 | 1769 | ||
1701 | at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */ | 1770 | at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */ |
@@ -1770,6 +1839,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) | |||
1770 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1839 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
1771 | 1840 | ||
1772 | cancel_delayed_work(&priv->dwork_hw_scan); | 1841 | cancel_delayed_work(&priv->dwork_hw_scan); |
1842 | cancel_work_sync(&priv->work_join_bssid); | ||
1773 | cancel_work_sync(&priv->work_set_promisc); | 1843 | cancel_work_sync(&priv->work_set_promisc); |
1774 | 1844 | ||
1775 | mutex_lock(&priv->mtx); | 1845 | mutex_lock(&priv->mtx); |
@@ -1818,42 +1888,6 @@ static void at76_remove_interface(struct ieee80211_hw *hw, | |||
1818 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1888 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
1819 | } | 1889 | } |
1820 | 1890 | ||
1821 | static int at76_join(struct at76_priv *priv) | ||
1822 | { | ||
1823 | struct at76_req_join join; | ||
1824 | int ret; | ||
1825 | |||
1826 | memset(&join, 0, sizeof(struct at76_req_join)); | ||
1827 | memcpy(join.essid, priv->essid, priv->essid_size); | ||
1828 | join.essid_size = priv->essid_size; | ||
1829 | memcpy(join.bssid, priv->bssid, ETH_ALEN); | ||
1830 | join.bss_type = INFRASTRUCTURE_MODE; | ||
1831 | join.channel = priv->channel; | ||
1832 | join.timeout = cpu_to_le16(2000); | ||
1833 | |||
1834 | at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__); | ||
1835 | ret = at76_set_card_command(priv->udev, CMD_JOIN, &join, | ||
1836 | sizeof(struct at76_req_join)); | ||
1837 | |||
1838 | if (ret < 0) { | ||
1839 | printk(KERN_ERR "%s: at76_set_card_command failed: %d\n", | ||
1840 | wiphy_name(priv->hw->wiphy), ret); | ||
1841 | return 0; | ||
1842 | } | ||
1843 | |||
1844 | ret = at76_wait_completion(priv, CMD_JOIN); | ||
1845 | at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret); | ||
1846 | if (ret != CMD_STATUS_COMPLETE) { | ||
1847 | printk(KERN_ERR "%s: at76_wait_completion failed: %d\n", | ||
1848 | wiphy_name(priv->hw->wiphy), ret); | ||
1849 | return 0; | ||
1850 | } | ||
1851 | |||
1852 | at76_set_pm_mode(priv); | ||
1853 | |||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static void at76_dwork_hw_scan(struct work_struct *work) | 1891 | static void at76_dwork_hw_scan(struct work_struct *work) |
1858 | { | 1892 | { |
1859 | struct at76_priv *priv = container_of(work, struct at76_priv, | 1893 | struct at76_priv *priv = container_of(work, struct at76_priv, |
@@ -2107,6 +2141,7 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev) | |||
2107 | mutex_init(&priv->mtx); | 2141 | mutex_init(&priv->mtx); |
2108 | INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc); | 2142 | INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc); |
2109 | INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx); | 2143 | INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx); |
2144 | INIT_WORK(&priv->work_join_bssid, at76_work_join_bssid); | ||
2110 | INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan); | 2145 | INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan); |
2111 | 2146 | ||
2112 | tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0); | 2147 | tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0); |
@@ -2508,5 +2543,6 @@ MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>"); | |||
2508 | MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"); | 2543 | MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"); |
2509 | MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>"); | 2544 | MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>"); |
2510 | MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>"); | 2545 | MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>"); |
2546 | MODULE_AUTHOR("Sebastian Smolorz <sesmo@gmx.net>"); | ||
2511 | MODULE_DESCRIPTION(DRIVER_DESC); | 2547 | MODULE_DESCRIPTION(DRIVER_DESC); |
2512 | MODULE_LICENSE("GPL"); | 2548 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/wireless/at76c50x-usb.h b/drivers/net/wireless/at76c50x-usb.h index 1ec5ccffdbc0..db89d72df4f3 100644 --- a/drivers/net/wireless/at76c50x-usb.h +++ b/drivers/net/wireless/at76c50x-usb.h | |||
@@ -387,6 +387,7 @@ struct at76_priv { | |||
387 | /* work queues */ | 387 | /* work queues */ |
388 | struct work_struct work_set_promisc; | 388 | struct work_struct work_set_promisc; |
389 | struct work_struct work_submit_rx; | 389 | struct work_struct work_submit_rx; |
390 | struct work_struct work_join_bssid; | ||
390 | struct delayed_work dwork_hw_scan; | 391 | struct delayed_work dwork_hw_scan; |
391 | 392 | ||
392 | struct tasklet_struct rx_tasklet; | 393 | struct tasklet_struct rx_tasklet; |
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index cc09595b781a..2242a140e4fe 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -13,5 +13,6 @@ ath5k-y += base.o | |||
13 | ath5k-y += led.o | 13 | ath5k-y += led.o |
14 | ath5k-y += rfkill.o | 14 | ath5k-y += rfkill.o |
15 | ath5k-y += ani.o | 15 | ath5k-y += ani.o |
16 | ath5k-y += sysfs.o | ||
16 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 17 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
17 | obj-$(CONFIG_ATH5K) += ath5k.o | 18 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index f2311ab35504..26dbe65fedb0 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -74,8 +74,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | |||
74 | const s8 fr[] = { -78, -80 }; | 74 | const s8 fr[] = { -78, -80 }; |
75 | #endif | 75 | #endif |
76 | if (level < 0 || level >= ARRAY_SIZE(sz)) { | 76 | if (level < 0 || level >= ARRAY_SIZE(sz)) { |
77 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | 77 | ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", |
78 | "level out of range %d", level); | 78 | level); |
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | 81 | ||
@@ -106,8 +106,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | |||
106 | 106 | ||
107 | if (level < 0 || level >= ARRAY_SIZE(val) || | 107 | if (level < 0 || level >= ARRAY_SIZE(val) || |
108 | level > ah->ah_sc->ani_state.max_spur_level) { | 108 | level > ah->ah_sc->ani_state.max_spur_level) { |
109 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | 109 | ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range", |
110 | "level out of range %d", level); | 110 | level); |
111 | return; | 111 | return; |
112 | } | 112 | } |
113 | 113 | ||
@@ -130,8 +130,7 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | |||
130 | const int val[] = { 0, 4, 8 }; | 130 | const int val[] = { 0, 4, 8 }; |
131 | 131 | ||
132 | if (level < 0 || level >= ARRAY_SIZE(val)) { | 132 | if (level < 0 || level >= ARRAY_SIZE(val)) { |
133 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | 133 | ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); |
134 | "level out of range %d", level); | ||
135 | return; | 134 | return; |
136 | } | 135 | } |
137 | 136 | ||
@@ -481,14 +480,15 @@ ath5k_ani_calibration(struct ath5k_hw *ah) | |||
481 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | 480 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; |
482 | int listen, ofdm_high, ofdm_low, cck_high, cck_low; | 481 | int listen, ofdm_high, ofdm_low, cck_high, cck_low; |
483 | 482 | ||
484 | if (as->ani_mode != ATH5K_ANI_MODE_AUTO) | ||
485 | return; | ||
486 | |||
487 | /* get listen time since last call and add it to the counter because we | 483 | /* get listen time since last call and add it to the counter because we |
488 | * might not have restarted the "ani period" last time */ | 484 | * might not have restarted the "ani period" last time. |
485 | * always do this to calculate the busy time also in manual mode */ | ||
489 | listen = ath5k_hw_ani_get_listen_time(ah, as); | 486 | listen = ath5k_hw_ani_get_listen_time(ah, as); |
490 | as->listen_time += listen; | 487 | as->listen_time += listen; |
491 | 488 | ||
489 | if (as->ani_mode != ATH5K_ANI_MODE_AUTO) | ||
490 | return; | ||
491 | |||
492 | ath5k_ani_save_and_clear_phy_errors(ah, as); | 492 | ath5k_ani_save_and_clear_phy_errors(ah, as); |
493 | 493 | ||
494 | ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; | 494 | ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 2785946f659a..ea6362a8988d 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -204,6 +204,7 @@ | |||
204 | #define AR5K_TUNE_TPC_TXPOWER false | 204 | #define AR5K_TUNE_TPC_TXPOWER false |
205 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ | 205 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ |
206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | 206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ |
207 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ | ||
207 | 208 | ||
208 | #define AR5K_INIT_CARR_SENSE_EN 1 | 209 | #define AR5K_INIT_CARR_SENSE_EN 1 |
209 | 210 | ||
@@ -565,7 +566,7 @@ enum ath5k_pkt_type { | |||
565 | ) | 566 | ) |
566 | 567 | ||
567 | /* | 568 | /* |
568 | * DMA size definitions (2^n+2) | 569 | * DMA size definitions (2^(n+2)) |
569 | */ | 570 | */ |
570 | enum ath5k_dmasize { | 571 | enum ath5k_dmasize { |
571 | AR5K_DMASIZE_4B = 0, | 572 | AR5K_DMASIZE_4B = 0, |
@@ -1118,6 +1119,7 @@ struct ath5k_hw { | |||
1118 | /* Calibration timestamp */ | 1119 | /* Calibration timestamp */ |
1119 | unsigned long ah_cal_next_full; | 1120 | unsigned long ah_cal_next_full; |
1120 | unsigned long ah_cal_next_ani; | 1121 | unsigned long ah_cal_next_ani; |
1122 | unsigned long ah_cal_next_nf; | ||
1121 | 1123 | ||
1122 | /* Calibration mask */ | 1124 | /* Calibration mask */ |
1123 | u8 ah_cal_mask; | 1125 | u8 ah_cal_mask; |
@@ -1125,15 +1127,10 @@ struct ath5k_hw { | |||
1125 | /* | 1127 | /* |
1126 | * Function pointers | 1128 | * Function pointers |
1127 | */ | 1129 | */ |
1128 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1129 | u32 size, unsigned int flags); | ||
1130 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1130 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1131 | unsigned int, unsigned int, int, enum ath5k_pkt_type, | 1131 | unsigned int, unsigned int, int, enum ath5k_pkt_type, |
1132 | unsigned int, unsigned int, unsigned int, unsigned int, | 1132 | unsigned int, unsigned int, unsigned int, unsigned int, |
1133 | unsigned int, unsigned int, unsigned int, unsigned int); | 1133 | unsigned int, unsigned int, unsigned int, unsigned int); |
1134 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | ||
1135 | unsigned int, unsigned int, unsigned int, unsigned int, | ||
1136 | unsigned int, unsigned int); | ||
1137 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1134 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1138 | struct ath5k_tx_status *); | 1135 | struct ath5k_tx_status *); |
1139 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1136 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
@@ -1148,6 +1145,9 @@ struct ath5k_hw { | |||
1148 | int ath5k_hw_attach(struct ath5k_softc *sc); | 1145 | int ath5k_hw_attach(struct ath5k_softc *sc); |
1149 | void ath5k_hw_detach(struct ath5k_hw *ah); | 1146 | void ath5k_hw_detach(struct ath5k_hw *ah); |
1150 | 1147 | ||
1148 | int ath5k_sysfs_register(struct ath5k_softc *sc); | ||
1149 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); | ||
1150 | |||
1151 | /* LED functions */ | 1151 | /* LED functions */ |
1152 | int ath5k_init_leds(struct ath5k_softc *sc); | 1152 | int ath5k_init_leds(struct ath5k_softc *sc); |
1153 | void ath5k_led_enable(struct ath5k_softc *sc); | 1153 | void ath5k_led_enable(struct ath5k_softc *sc); |
@@ -1231,6 +1231,11 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | |||
1231 | 1231 | ||
1232 | /* Hardware Descriptor Functions */ | 1232 | /* Hardware Descriptor Functions */ |
1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); | 1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
1234 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1235 | u32 size, unsigned int flags); | ||
1236 | int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1237 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | ||
1238 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); | ||
1234 | 1239 | ||
1235 | /* GPIO Functions */ | 1240 | /* GPIO Functions */ |
1236 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1241 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
@@ -1270,6 +1275,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | |||
1270 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | 1275 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); |
1271 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | 1276 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, |
1272 | struct ieee80211_channel *channel); | 1277 | struct ieee80211_channel *channel); |
1278 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah); | ||
1273 | /* Spur mitigation */ | 1279 | /* Spur mitigation */ |
1274 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1280 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
1275 | struct ieee80211_channel *channel); | 1281 | struct ieee80211_channel *channel); |
@@ -1280,6 +1286,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | |||
1280 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); | 1286 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1281 | /* Antenna control */ | 1287 | /* Antenna control */ |
1282 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); | 1288 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); |
1289 | void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); | ||
1283 | /* TX power setup */ | 1290 | /* TX power setup */ |
1284 | int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 1291 | int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
1285 | u8 ee_mode, u8 txpower); | 1292 | u8 ee_mode, u8 txpower); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 31c008042bfe..b32e28caeee2 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -352,8 +352,6 @@ err_free: | |||
352 | */ | 352 | */ |
353 | void ath5k_hw_detach(struct ath5k_hw *ah) | 353 | void ath5k_hw_detach(struct ath5k_hw *ah) |
354 | { | 354 | { |
355 | ATH5K_TRACE(ah->ah_sc); | ||
356 | |||
357 | __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); | 355 | __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); |
358 | 356 | ||
359 | if (ah->ah_rf_banks != NULL) | 357 | if (ah->ah_rf_banks != NULL) |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 648972df369d..20328bdd138b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -311,7 +311,8 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | |||
311 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 311 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
312 | struct ath5k_buf *bf, | 312 | struct ath5k_buf *bf, |
313 | struct ath5k_txq *txq, int padsize); | 313 | struct ath5k_txq *txq, int padsize); |
314 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 314 | |
315 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, | ||
315 | struct ath5k_buf *bf) | 316 | struct ath5k_buf *bf) |
316 | { | 317 | { |
317 | BUG_ON(!bf); | 318 | BUG_ON(!bf); |
@@ -321,9 +322,11 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | |||
321 | PCI_DMA_TODEVICE); | 322 | PCI_DMA_TODEVICE); |
322 | dev_kfree_skb_any(bf->skb); | 323 | dev_kfree_skb_any(bf->skb); |
323 | bf->skb = NULL; | 324 | bf->skb = NULL; |
325 | bf->skbaddr = 0; | ||
326 | bf->desc->ds_data = 0; | ||
324 | } | 327 | } |
325 | 328 | ||
326 | static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, | 329 | static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, |
327 | struct ath5k_buf *bf) | 330 | struct ath5k_buf *bf) |
328 | { | 331 | { |
329 | struct ath5k_hw *ah = sc->ah; | 332 | struct ath5k_hw *ah = sc->ah; |
@@ -336,6 +339,8 @@ static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, | |||
336 | PCI_DMA_FROMDEVICE); | 339 | PCI_DMA_FROMDEVICE); |
337 | dev_kfree_skb_any(bf->skb); | 340 | dev_kfree_skb_any(bf->skb); |
338 | bf->skb = NULL; | 341 | bf->skb = NULL; |
342 | bf->skbaddr = 0; | ||
343 | bf->desc->ds_data = 0; | ||
339 | } | 344 | } |
340 | 345 | ||
341 | 346 | ||
@@ -352,7 +357,6 @@ static void ath5k_txq_release(struct ath5k_softc *sc); | |||
352 | static int ath5k_rx_start(struct ath5k_softc *sc); | 357 | static int ath5k_rx_start(struct ath5k_softc *sc); |
353 | static void ath5k_rx_stop(struct ath5k_softc *sc); | 358 | static void ath5k_rx_stop(struct ath5k_softc *sc); |
354 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, | 359 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, |
355 | struct ath5k_desc *ds, | ||
356 | struct sk_buff *skb, | 360 | struct sk_buff *skb, |
357 | struct ath5k_rx_status *rs); | 361 | struct ath5k_rx_status *rs); |
358 | static void ath5k_tasklet_rx(unsigned long data); | 362 | static void ath5k_tasklet_rx(unsigned long data); |
@@ -578,7 +582,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
578 | spin_lock_init(&sc->block); | 582 | spin_lock_init(&sc->block); |
579 | 583 | ||
580 | /* Set private data */ | 584 | /* Set private data */ |
581 | pci_set_drvdata(pdev, hw); | 585 | pci_set_drvdata(pdev, sc); |
582 | 586 | ||
583 | /* Setup interrupt handler */ | 587 | /* Setup interrupt handler */ |
584 | ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | 588 | ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); |
@@ -694,25 +698,23 @@ err: | |||
694 | static void __devexit | 698 | static void __devexit |
695 | ath5k_pci_remove(struct pci_dev *pdev) | 699 | ath5k_pci_remove(struct pci_dev *pdev) |
696 | { | 700 | { |
697 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 701 | struct ath5k_softc *sc = pci_get_drvdata(pdev); |
698 | struct ath5k_softc *sc = hw->priv; | ||
699 | 702 | ||
700 | ath5k_debug_finish_device(sc); | 703 | ath5k_debug_finish_device(sc); |
701 | ath5k_detach(pdev, hw); | 704 | ath5k_detach(pdev, sc->hw); |
702 | ath5k_hw_detach(sc->ah); | 705 | ath5k_hw_detach(sc->ah); |
703 | kfree(sc->ah); | 706 | kfree(sc->ah); |
704 | free_irq(pdev->irq, sc); | 707 | free_irq(pdev->irq, sc); |
705 | pci_iounmap(pdev, sc->iobase); | 708 | pci_iounmap(pdev, sc->iobase); |
706 | pci_release_region(pdev, 0); | 709 | pci_release_region(pdev, 0); |
707 | pci_disable_device(pdev); | 710 | pci_disable_device(pdev); |
708 | ieee80211_free_hw(hw); | 711 | ieee80211_free_hw(sc->hw); |
709 | } | 712 | } |
710 | 713 | ||
711 | #ifdef CONFIG_PM_SLEEP | 714 | #ifdef CONFIG_PM_SLEEP |
712 | static int ath5k_pci_suspend(struct device *dev) | 715 | static int ath5k_pci_suspend(struct device *dev) |
713 | { | 716 | { |
714 | struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); | 717 | struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); |
715 | struct ath5k_softc *sc = hw->priv; | ||
716 | 718 | ||
717 | ath5k_led_off(sc); | 719 | ath5k_led_off(sc); |
718 | return 0; | 720 | return 0; |
@@ -721,8 +723,7 @@ static int ath5k_pci_suspend(struct device *dev) | |||
721 | static int ath5k_pci_resume(struct device *dev) | 723 | static int ath5k_pci_resume(struct device *dev) |
722 | { | 724 | { |
723 | struct pci_dev *pdev = to_pci_dev(dev); | 725 | struct pci_dev *pdev = to_pci_dev(dev); |
724 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 726 | struct ath5k_softc *sc = pci_get_drvdata(pdev); |
725 | struct ath5k_softc *sc = hw->priv; | ||
726 | 727 | ||
727 | /* | 728 | /* |
728 | * Suspend/Resume resets the PCI configuration space, so we have to | 729 | * Suspend/Resume resets the PCI configuration space, so we have to |
@@ -768,7 +769,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
768 | * return false w/o doing anything. MAC's that do | 769 | * return false w/o doing anything. MAC's that do |
769 | * support it will return true w/o doing anything. | 770 | * support it will return true w/o doing anything. |
770 | */ | 771 | */ |
771 | ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | 772 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); |
773 | |||
772 | if (ret < 0) | 774 | if (ret < 0) |
773 | goto err; | 775 | goto err; |
774 | if (ret > 0) | 776 | if (ret > 0) |
@@ -864,6 +866,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
864 | 866 | ||
865 | ath5k_init_leds(sc); | 867 | ath5k_init_leds(sc); |
866 | 868 | ||
869 | ath5k_sysfs_register(sc); | ||
870 | |||
867 | return 0; | 871 | return 0; |
868 | err_queues: | 872 | err_queues: |
869 | ath5k_txq_release(sc); | 873 | ath5k_txq_release(sc); |
@@ -899,6 +903,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
899 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | 903 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); |
900 | ath5k_unregister_leds(sc); | 904 | ath5k_unregister_leds(sc); |
901 | 905 | ||
906 | ath5k_sysfs_unregister(sc); | ||
902 | /* | 907 | /* |
903 | * NB: can't reclaim these until after ieee80211_ifdetach | 908 | * NB: can't reclaim these until after ieee80211_ifdetach |
904 | * returns because we'll get called back to reclaim node | 909 | * returns because we'll get called back to reclaim node |
@@ -1111,8 +1116,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1111 | static int | 1116 | static int |
1112 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | 1117 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) |
1113 | { | 1118 | { |
1114 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", | 1119 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
1115 | sc->curchan->center_freq, chan->center_freq); | 1120 | "channel set, resetting (%u -> %u MHz)\n", |
1121 | sc->curchan->center_freq, chan->center_freq); | ||
1116 | 1122 | ||
1117 | /* | 1123 | /* |
1118 | * To switch channels clear any pending DMA operations; | 1124 | * To switch channels clear any pending DMA operations; |
@@ -1228,21 +1234,23 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1228 | * not get overrun under high load (as can happen with a | 1234 | * not get overrun under high load (as can happen with a |
1229 | * 5212 when ANI processing enables PHY error frames). | 1235 | * 5212 when ANI processing enables PHY error frames). |
1230 | * | 1236 | * |
1231 | * To insure the last descriptor is self-linked we create | 1237 | * To ensure the last descriptor is self-linked we create |
1232 | * each descriptor as self-linked and add it to the end. As | 1238 | * each descriptor as self-linked and add it to the end. As |
1233 | * each additional descriptor is added the previous self-linked | 1239 | * each additional descriptor is added the previous self-linked |
1234 | * entry is ``fixed'' naturally. This should be safe even | 1240 | * entry is "fixed" naturally. This should be safe even |
1235 | * if DMA is happening. When processing RX interrupts we | 1241 | * if DMA is happening. When processing RX interrupts we |
1236 | * never remove/process the last, self-linked, entry on the | 1242 | * never remove/process the last, self-linked, entry on the |
1237 | * descriptor list. This insures the hardware always has | 1243 | * descriptor list. This ensures the hardware always has |
1238 | * someplace to write a new frame. | 1244 | * someplace to write a new frame. |
1239 | */ | 1245 | */ |
1240 | ds = bf->desc; | 1246 | ds = bf->desc; |
1241 | ds->ds_link = bf->daddr; /* link to self */ | 1247 | ds->ds_link = bf->daddr; /* link to self */ |
1242 | ds->ds_data = bf->skbaddr; | 1248 | ds->ds_data = bf->skbaddr; |
1243 | ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); | 1249 | ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); |
1244 | if (ret) | 1250 | if (ret) { |
1251 | ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__); | ||
1245 | return ret; | 1252 | return ret; |
1253 | } | ||
1246 | 1254 | ||
1247 | if (sc->rxlink != NULL) | 1255 | if (sc->rxlink != NULL) |
1248 | *sc->rxlink = bf->daddr; | 1256 | *sc->rxlink = bf->daddr; |
@@ -1347,7 +1355,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1347 | mrr_tries[i] = info->control.rates[i + 1].count; | 1355 | mrr_tries[i] = info->control.rates[i + 1].count; |
1348 | } | 1356 | } |
1349 | 1357 | ||
1350 | ah->ah_setup_mrr_tx_desc(ah, ds, | 1358 | ath5k_hw_setup_mrr_tx_desc(ah, ds, |
1351 | mrr_rate[0], mrr_tries[0], | 1359 | mrr_rate[0], mrr_tries[0], |
1352 | mrr_rate[1], mrr_tries[1], | 1360 | mrr_rate[1], mrr_tries[1], |
1353 | mrr_rate[2], mrr_tries[2]); | 1361 | mrr_rate[2], mrr_tries[2]); |
@@ -1443,17 +1451,20 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
1443 | { | 1451 | { |
1444 | struct ath5k_buf *bf; | 1452 | struct ath5k_buf *bf; |
1445 | 1453 | ||
1446 | ath5k_txbuf_free(sc, sc->bbuf); | 1454 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
1447 | list_for_each_entry(bf, &sc->txbuf, list) | 1455 | list_for_each_entry(bf, &sc->txbuf, list) |
1448 | ath5k_txbuf_free(sc, bf); | 1456 | ath5k_txbuf_free_skb(sc, bf); |
1449 | list_for_each_entry(bf, &sc->rxbuf, list) | 1457 | list_for_each_entry(bf, &sc->rxbuf, list) |
1450 | ath5k_rxbuf_free(sc, bf); | 1458 | ath5k_rxbuf_free_skb(sc, bf); |
1451 | 1459 | ||
1452 | /* Free memory associated with all descriptors */ | 1460 | /* Free memory associated with all descriptors */ |
1453 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | 1461 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); |
1462 | sc->desc = NULL; | ||
1463 | sc->desc_daddr = 0; | ||
1454 | 1464 | ||
1455 | kfree(sc->bufptr); | 1465 | kfree(sc->bufptr); |
1456 | sc->bufptr = NULL; | 1466 | sc->bufptr = NULL; |
1467 | sc->bbuf = NULL; | ||
1457 | } | 1468 | } |
1458 | 1469 | ||
1459 | 1470 | ||
@@ -1602,7 +1613,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1602 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1613 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
1603 | ath5k_debug_printtxbuf(sc, bf); | 1614 | ath5k_debug_printtxbuf(sc, bf); |
1604 | 1615 | ||
1605 | ath5k_txbuf_free(sc, bf); | 1616 | ath5k_txbuf_free_skb(sc, bf); |
1606 | 1617 | ||
1607 | spin_lock_bh(&sc->txbuflock); | 1618 | spin_lock_bh(&sc->txbuflock); |
1608 | list_move_tail(&bf->list, &sc->txbuf); | 1619 | list_move_tail(&bf->list, &sc->txbuf); |
@@ -1721,8 +1732,8 @@ ath5k_rx_stop(struct ath5k_softc *sc) | |||
1721 | } | 1732 | } |
1722 | 1733 | ||
1723 | static unsigned int | 1734 | static unsigned int |
1724 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | 1735 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb, |
1725 | struct sk_buff *skb, struct ath5k_rx_status *rs) | 1736 | struct ath5k_rx_status *rs) |
1726 | { | 1737 | { |
1727 | struct ath5k_hw *ah = sc->ah; | 1738 | struct ath5k_hw *ah = sc->ah; |
1728 | struct ath_common *common = ath5k_hw_common(ah); | 1739 | struct ath_common *common = ath5k_hw_common(ah); |
@@ -1889,9 +1900,138 @@ static int ath5k_remove_padding(struct sk_buff *skb) | |||
1889 | } | 1900 | } |
1890 | 1901 | ||
1891 | static void | 1902 | static void |
1892 | ath5k_tasklet_rx(unsigned long data) | 1903 | ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, |
1904 | struct ath5k_rx_status *rs) | ||
1893 | { | 1905 | { |
1894 | struct ieee80211_rx_status *rxs; | 1906 | struct ieee80211_rx_status *rxs; |
1907 | |||
1908 | /* The MAC header is padded to have 32-bit boundary if the | ||
1909 | * packet payload is non-zero. The general calculation for | ||
1910 | * padsize would take into account odd header lengths: | ||
1911 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1912 | * even-length headers are used, padding can only be 0 or 2 | ||
1913 | * bytes and we can optimize this a bit. In addition, we must | ||
1914 | * not try to remove padding from short control frames that do | ||
1915 | * not have payload. */ | ||
1916 | ath5k_remove_padding(skb); | ||
1917 | |||
1918 | rxs = IEEE80211_SKB_RXCB(skb); | ||
1919 | |||
1920 | rxs->flag = 0; | ||
1921 | if (unlikely(rs->rs_status & AR5K_RXERR_MIC)) | ||
1922 | rxs->flag |= RX_FLAG_MMIC_ERROR; | ||
1923 | |||
1924 | /* | ||
1925 | * always extend the mac timestamp, since this information is | ||
1926 | * also needed for proper IBSS merging. | ||
1927 | * | ||
1928 | * XXX: it might be too late to do it here, since rs_tstamp is | ||
1929 | * 15bit only. that means TSF extension has to be done within | ||
1930 | * 32768usec (about 32ms). it might be necessary to move this to | ||
1931 | * the interrupt handler, like it is done in madwifi. | ||
1932 | * | ||
1933 | * Unfortunately we don't know when the hardware takes the rx | ||
1934 | * timestamp (beginning of phy frame, data frame, end of rx?). | ||
1935 | * The only thing we know is that it is hardware specific... | ||
1936 | * On AR5213 it seems the rx timestamp is at the end of the | ||
1937 | * frame, but i'm not sure. | ||
1938 | * | ||
1939 | * NOTE: mac80211 defines mactime at the beginning of the first | ||
1940 | * data symbol. Since we don't have any time references it's | ||
1941 | * impossible to comply to that. This affects IBSS merge only | ||
1942 | * right now, so it's not too bad... | ||
1943 | */ | ||
1944 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); | ||
1945 | rxs->flag |= RX_FLAG_TSFT; | ||
1946 | |||
1947 | rxs->freq = sc->curchan->center_freq; | ||
1948 | rxs->band = sc->curband->band; | ||
1949 | |||
1950 | rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; | ||
1951 | |||
1952 | rxs->antenna = rs->rs_antenna; | ||
1953 | |||
1954 | if (rs->rs_antenna > 0 && rs->rs_antenna < 5) | ||
1955 | sc->stats.antenna_rx[rs->rs_antenna]++; | ||
1956 | else | ||
1957 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
1958 | |||
1959 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate); | ||
1960 | rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); | ||
1961 | |||
1962 | if (rxs->rate_idx >= 0 && rs->rs_rate == | ||
1963 | sc->curband->bitrates[rxs->rate_idx].hw_value_short) | ||
1964 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
1965 | |||
1966 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | ||
1967 | |||
1968 | ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); | ||
1969 | |||
1970 | /* check beacons in IBSS mode */ | ||
1971 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | ||
1972 | ath5k_check_ibss_tsf(sc, skb, rxs); | ||
1973 | |||
1974 | ieee80211_rx(sc->hw, skb); | ||
1975 | } | ||
1976 | |||
1977 | /** ath5k_frame_receive_ok() - Do we want to receive this frame or not? | ||
1978 | * | ||
1979 | * Check if we want to further process this frame or not. Also update | ||
1980 | * statistics. Return true if we want this frame, false if not. | ||
1981 | */ | ||
1982 | static bool | ||
1983 | ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | ||
1984 | { | ||
1985 | sc->stats.rx_all_count++; | ||
1986 | |||
1987 | if (unlikely(rs->rs_status)) { | ||
1988 | if (rs->rs_status & AR5K_RXERR_CRC) | ||
1989 | sc->stats.rxerr_crc++; | ||
1990 | if (rs->rs_status & AR5K_RXERR_FIFO) | ||
1991 | sc->stats.rxerr_fifo++; | ||
1992 | if (rs->rs_status & AR5K_RXERR_PHY) { | ||
1993 | sc->stats.rxerr_phy++; | ||
1994 | if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32) | ||
1995 | sc->stats.rxerr_phy_code[rs->rs_phyerr]++; | ||
1996 | return false; | ||
1997 | } | ||
1998 | if (rs->rs_status & AR5K_RXERR_DECRYPT) { | ||
1999 | /* | ||
2000 | * Decrypt error. If the error occurred | ||
2001 | * because there was no hardware key, then | ||
2002 | * let the frame through so the upper layers | ||
2003 | * can process it. This is necessary for 5210 | ||
2004 | * parts which have no way to setup a ``clear'' | ||
2005 | * key cache entry. | ||
2006 | * | ||
2007 | * XXX do key cache faulting | ||
2008 | */ | ||
2009 | sc->stats.rxerr_decrypt++; | ||
2010 | if (rs->rs_keyix == AR5K_RXKEYIX_INVALID && | ||
2011 | !(rs->rs_status & AR5K_RXERR_CRC)) | ||
2012 | return true; | ||
2013 | } | ||
2014 | if (rs->rs_status & AR5K_RXERR_MIC) { | ||
2015 | sc->stats.rxerr_mic++; | ||
2016 | return true; | ||
2017 | } | ||
2018 | |||
2019 | /* let crypto-error packets fall through in MNTR */ | ||
2020 | if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | ||
2021 | sc->opmode != NL80211_IFTYPE_MONITOR) | ||
2022 | return false; | ||
2023 | } | ||
2024 | |||
2025 | if (unlikely(rs->rs_more)) { | ||
2026 | sc->stats.rxerr_jumbo++; | ||
2027 | return false; | ||
2028 | } | ||
2029 | return true; | ||
2030 | } | ||
2031 | |||
2032 | static void | ||
2033 | ath5k_tasklet_rx(unsigned long data) | ||
2034 | { | ||
1895 | struct ath5k_rx_status rs = {}; | 2035 | struct ath5k_rx_status rs = {}; |
1896 | struct sk_buff *skb, *next_skb; | 2036 | struct sk_buff *skb, *next_skb; |
1897 | dma_addr_t next_skb_addr; | 2037 | dma_addr_t next_skb_addr; |
@@ -1901,7 +2041,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1901 | struct ath5k_buf *bf; | 2041 | struct ath5k_buf *bf; |
1902 | struct ath5k_desc *ds; | 2042 | struct ath5k_desc *ds; |
1903 | int ret; | 2043 | int ret; |
1904 | int rx_flag; | ||
1905 | 2044 | ||
1906 | spin_lock(&sc->rxbuflock); | 2045 | spin_lock(&sc->rxbuflock); |
1907 | if (list_empty(&sc->rxbuf)) { | 2046 | if (list_empty(&sc->rxbuf)) { |
@@ -1909,8 +2048,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1909 | goto unlock; | 2048 | goto unlock; |
1910 | } | 2049 | } |
1911 | do { | 2050 | do { |
1912 | rx_flag = 0; | ||
1913 | |||
1914 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | 2051 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); |
1915 | BUG_ON(bf->skb == NULL); | 2052 | BUG_ON(bf->skb == NULL); |
1916 | skb = bf->skb; | 2053 | skb = bf->skb; |
@@ -1926,137 +2063,30 @@ ath5k_tasklet_rx(unsigned long data) | |||
1926 | else if (unlikely(ret)) { | 2063 | else if (unlikely(ret)) { |
1927 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | 2064 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); |
1928 | sc->stats.rxerr_proc++; | 2065 | sc->stats.rxerr_proc++; |
1929 | spin_unlock(&sc->rxbuflock); | 2066 | break; |
1930 | return; | ||
1931 | } | 2067 | } |
1932 | 2068 | ||
1933 | sc->stats.rx_all_count++; | 2069 | if (ath5k_receive_frame_ok(sc, &rs)) { |
1934 | 2070 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | |
1935 | if (unlikely(rs.rs_status)) { | ||
1936 | if (rs.rs_status & AR5K_RXERR_CRC) | ||
1937 | sc->stats.rxerr_crc++; | ||
1938 | if (rs.rs_status & AR5K_RXERR_FIFO) | ||
1939 | sc->stats.rxerr_fifo++; | ||
1940 | if (rs.rs_status & AR5K_RXERR_PHY) { | ||
1941 | sc->stats.rxerr_phy++; | ||
1942 | if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) | ||
1943 | sc->stats.rxerr_phy_code[rs.rs_phyerr]++; | ||
1944 | goto next; | ||
1945 | } | ||
1946 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | ||
1947 | /* | ||
1948 | * Decrypt error. If the error occurred | ||
1949 | * because there was no hardware key, then | ||
1950 | * let the frame through so the upper layers | ||
1951 | * can process it. This is necessary for 5210 | ||
1952 | * parts which have no way to setup a ``clear'' | ||
1953 | * key cache entry. | ||
1954 | * | ||
1955 | * XXX do key cache faulting | ||
1956 | */ | ||
1957 | sc->stats.rxerr_decrypt++; | ||
1958 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && | ||
1959 | !(rs.rs_status & AR5K_RXERR_CRC)) | ||
1960 | goto accept; | ||
1961 | } | ||
1962 | if (rs.rs_status & AR5K_RXERR_MIC) { | ||
1963 | rx_flag |= RX_FLAG_MMIC_ERROR; | ||
1964 | sc->stats.rxerr_mic++; | ||
1965 | goto accept; | ||
1966 | } | ||
1967 | 2071 | ||
1968 | /* let crypto-error packets fall through in MNTR */ | 2072 | /* |
1969 | if ((rs.rs_status & | 2073 | * If we can't replace bf->skb with a new skb under |
1970 | ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | 2074 | * memory pressure, just skip this packet |
1971 | sc->opmode != NL80211_IFTYPE_MONITOR) | 2075 | */ |
2076 | if (!next_skb) | ||
1972 | goto next; | 2077 | goto next; |
1973 | } | ||
1974 | |||
1975 | if (unlikely(rs.rs_more)) { | ||
1976 | sc->stats.rxerr_jumbo++; | ||
1977 | goto next; | ||
1978 | |||
1979 | } | ||
1980 | accept: | ||
1981 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | ||
1982 | |||
1983 | /* | ||
1984 | * If we can't replace bf->skb with a new skb under memory | ||
1985 | * pressure, just skip this packet | ||
1986 | */ | ||
1987 | if (!next_skb) | ||
1988 | goto next; | ||
1989 | |||
1990 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, | ||
1991 | PCI_DMA_FROMDEVICE); | ||
1992 | skb_put(skb, rs.rs_datalen); | ||
1993 | |||
1994 | /* The MAC header is padded to have 32-bit boundary if the | ||
1995 | * packet payload is non-zero. The general calculation for | ||
1996 | * padsize would take into account odd header lengths: | ||
1997 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1998 | * even-length headers are used, padding can only be 0 or 2 | ||
1999 | * bytes and we can optimize this a bit. In addition, we must | ||
2000 | * not try to remove padding from short control frames that do | ||
2001 | * not have payload. */ | ||
2002 | ath5k_remove_padding(skb); | ||
2003 | |||
2004 | rxs = IEEE80211_SKB_RXCB(skb); | ||
2005 | |||
2006 | /* | ||
2007 | * always extend the mac timestamp, since this information is | ||
2008 | * also needed for proper IBSS merging. | ||
2009 | * | ||
2010 | * XXX: it might be too late to do it here, since rs_tstamp is | ||
2011 | * 15bit only. that means TSF extension has to be done within | ||
2012 | * 32768usec (about 32ms). it might be necessary to move this to | ||
2013 | * the interrupt handler, like it is done in madwifi. | ||
2014 | * | ||
2015 | * Unfortunately we don't know when the hardware takes the rx | ||
2016 | * timestamp (beginning of phy frame, data frame, end of rx?). | ||
2017 | * The only thing we know is that it is hardware specific... | ||
2018 | * On AR5213 it seems the rx timestamp is at the end of the | ||
2019 | * frame, but i'm not sure. | ||
2020 | * | ||
2021 | * NOTE: mac80211 defines mactime at the beginning of the first | ||
2022 | * data symbol. Since we don't have any time references it's | ||
2023 | * impossible to comply to that. This affects IBSS merge only | ||
2024 | * right now, so it's not too bad... | ||
2025 | */ | ||
2026 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); | ||
2027 | rxs->flag = rx_flag | RX_FLAG_TSFT; | ||
2028 | |||
2029 | rxs->freq = sc->curchan->center_freq; | ||
2030 | rxs->band = sc->curband->band; | ||
2031 | |||
2032 | rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi; | ||
2033 | |||
2034 | rxs->antenna = rs.rs_antenna; | ||
2035 | |||
2036 | if (rs.rs_antenna > 0 && rs.rs_antenna < 5) | ||
2037 | sc->stats.antenna_rx[rs.rs_antenna]++; | ||
2038 | else | ||
2039 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
2040 | |||
2041 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | ||
2042 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | ||
2043 | |||
2044 | if (rxs->rate_idx >= 0 && rs.rs_rate == | ||
2045 | sc->curband->bitrates[rxs->rate_idx].hw_value_short) | ||
2046 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
2047 | 2078 | ||
2048 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 2079 | pci_unmap_single(sc->pdev, bf->skbaddr, |
2080 | common->rx_bufsize, | ||
2081 | PCI_DMA_FROMDEVICE); | ||
2049 | 2082 | ||
2050 | ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); | 2083 | skb_put(skb, rs.rs_datalen); |
2051 | 2084 | ||
2052 | /* check beacons in IBSS mode */ | 2085 | ath5k_receive_frame(sc, skb, &rs); |
2053 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | ||
2054 | ath5k_check_ibss_tsf(sc, skb, rxs); | ||
2055 | 2086 | ||
2056 | ieee80211_rx(sc->hw, skb); | 2087 | bf->skb = next_skb; |
2057 | 2088 | bf->skbaddr = next_skb_addr; | |
2058 | bf->skb = next_skb; | 2089 | } |
2059 | bf->skbaddr = next_skb_addr; | ||
2060 | next: | 2090 | next: |
2061 | list_move_tail(&bf->list, &sc->rxbuf); | 2091 | list_move_tail(&bf->list, &sc->rxbuf); |
2062 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 2092 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
@@ -2065,8 +2095,6 @@ unlock: | |||
2065 | } | 2095 | } |
2066 | 2096 | ||
2067 | 2097 | ||
2068 | |||
2069 | |||
2070 | /*************\ | 2098 | /*************\ |
2071 | * TX Handling * | 2099 | * TX Handling * |
2072 | \*************/ | 2100 | \*************/ |
@@ -2298,6 +2326,8 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2298 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 2326 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, |
2299 | "stuck beacon time (%u missed)\n", | 2327 | "stuck beacon time (%u missed)\n", |
2300 | sc->bmisscount); | 2328 | sc->bmisscount); |
2329 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2330 | "stuck beacon, resetting\n"); | ||
2301 | tasklet_schedule(&sc->restq); | 2331 | tasklet_schedule(&sc->restq); |
2302 | } | 2332 | } |
2303 | return; | 2333 | return; |
@@ -2647,7 +2677,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2647 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2677 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2648 | "putting device to sleep\n"); | 2678 | "putting device to sleep\n"); |
2649 | } | 2679 | } |
2650 | ath5k_txbuf_free(sc, sc->bbuf); | 2680 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
2651 | 2681 | ||
2652 | mmiowb(); | 2682 | mmiowb(); |
2653 | mutex_unlock(&sc->lock); | 2683 | mutex_unlock(&sc->lock); |
@@ -2705,6 +2735,8 @@ ath5k_intr(int irq, void *dev_id) | |||
2705 | * Fatal errors are unrecoverable. | 2735 | * Fatal errors are unrecoverable. |
2706 | * Typically these are caused by DMA errors. | 2736 | * Typically these are caused by DMA errors. |
2707 | */ | 2737 | */ |
2738 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2739 | "fatal int, resetting\n"); | ||
2708 | tasklet_schedule(&sc->restq); | 2740 | tasklet_schedule(&sc->restq); |
2709 | } else if (unlikely(status & AR5K_INT_RXORN)) { | 2741 | } else if (unlikely(status & AR5K_INT_RXORN)) { |
2710 | /* | 2742 | /* |
@@ -2717,8 +2749,11 @@ ath5k_intr(int irq, void *dev_id) | |||
2717 | * this guess is copied from the HAL. | 2749 | * this guess is copied from the HAL. |
2718 | */ | 2750 | */ |
2719 | sc->stats.rxorn_intr++; | 2751 | sc->stats.rxorn_intr++; |
2720 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) | 2752 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) { |
2753 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2754 | "rx overrun, resetting\n"); | ||
2721 | tasklet_schedule(&sc->restq); | 2755 | tasklet_schedule(&sc->restq); |
2756 | } | ||
2722 | else | 2757 | else |
2723 | tasklet_schedule(&sc->rxtq); | 2758 | tasklet_schedule(&sc->rxtq); |
2724 | } else { | 2759 | } else { |
@@ -2785,10 +2820,6 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2785 | /* Only full calibration for now */ | 2820 | /* Only full calibration for now */ |
2786 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; | 2821 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; |
2787 | 2822 | ||
2788 | /* Stop queues so that calibration | ||
2789 | * doesn't interfere with tx */ | ||
2790 | ieee80211_stop_queues(sc->hw); | ||
2791 | |||
2792 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", | 2823 | ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", |
2793 | ieee80211_frequency_to_channel(sc->curchan->center_freq), | 2824 | ieee80211_frequency_to_channel(sc->curchan->center_freq), |
2794 | sc->curchan->hw_value); | 2825 | sc->curchan->hw_value); |
@@ -2806,8 +2837,16 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2806 | ieee80211_frequency_to_channel( | 2837 | ieee80211_frequency_to_channel( |
2807 | sc->curchan->center_freq)); | 2838 | sc->curchan->center_freq)); |
2808 | 2839 | ||
2809 | /* Wake queues */ | 2840 | /* Noise floor calibration interrupts rx/tx path while I/Q calibration |
2810 | ieee80211_wake_queues(sc->hw); | 2841 | * doesn't. We stop the queues so that calibration doesn't interfere |
2842 | * with TX and don't run it as often */ | ||
2843 | if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { | ||
2844 | ah->ah_cal_next_nf = jiffies + | ||
2845 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); | ||
2846 | ieee80211_stop_queues(sc->hw); | ||
2847 | ath5k_hw_update_noise_floor(ah); | ||
2848 | ieee80211_wake_queues(sc->hw); | ||
2849 | } | ||
2811 | 2850 | ||
2812 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | 2851 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; |
2813 | } | 2852 | } |
@@ -2926,6 +2965,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
2926 | 2965 | ||
2927 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); | 2966 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); |
2928 | 2967 | ||
2968 | ah->ah_cal_next_full = jiffies; | ||
2969 | ah->ah_cal_next_ani = jiffies; | ||
2970 | ah->ah_cal_next_nf = jiffies; | ||
2971 | |||
2929 | /* | 2972 | /* |
2930 | * Change channels and update the h/w rate map if we're switching; | 2973 | * Change channels and update the h/w rate map if we're switching; |
2931 | * e.g. 11a to 11b/g. | 2974 | * e.g. 11a to 11b/g. |
@@ -3360,7 +3403,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
3360 | 3403 | ||
3361 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | 3404 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); |
3362 | 3405 | ||
3363 | ath5k_txbuf_free(sc, sc->bbuf); | 3406 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
3364 | sc->bbuf->skb = skb; | 3407 | sc->bbuf->skb = skb; |
3365 | ret = ath5k_beacon_setup(sc, sc->bbuf); | 3408 | ret = ath5k_beacon_setup(sc, sc->bbuf); |
3366 | if (ret) | 3409 | if (ret) |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 74f007126f41..beae519aa735 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -34,7 +34,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
34 | { | 34 | { |
35 | u16 ee_header; | 35 | u16 ee_header; |
36 | 36 | ||
37 | ATH5K_TRACE(ah->ah_sc); | ||
38 | /* Capabilities stored in the EEPROM */ | 37 | /* Capabilities stored in the EEPROM */ |
39 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; | 38 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; |
40 | 39 | ||
@@ -123,8 +122,6 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah, | |||
123 | enum ath5k_capability_type cap_type, | 122 | enum ath5k_capability_type cap_type, |
124 | u32 capability, u32 *result) | 123 | u32 capability, u32 *result) |
125 | { | 124 | { |
126 | ATH5K_TRACE(ah->ah_sc); | ||
127 | |||
128 | switch (cap_type) { | 125 | switch (cap_type) { |
129 | case AR5K_CAP_NUM_TXQUEUES: | 126 | case AR5K_CAP_NUM_TXQUEUES: |
130 | if (result) { | 127 | if (result) { |
@@ -173,8 +170,6 @@ yes: | |||
173 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, | 170 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, |
174 | u16 assoc_id) | 171 | u16 assoc_id) |
175 | { | 172 | { |
176 | ATH5K_TRACE(ah->ah_sc); | ||
177 | |||
178 | if (ah->ah_version == AR5K_AR5210) { | 173 | if (ah->ah_version == AR5K_AR5210) { |
179 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | 174 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, |
180 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | 175 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); |
@@ -186,8 +181,6 @@ int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, | |||
186 | 181 | ||
187 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) | 182 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) |
188 | { | 183 | { |
189 | ATH5K_TRACE(ah->ah_sc); | ||
190 | |||
191 | if (ah->ah_version == AR5K_AR5210) { | 184 | if (ah->ah_version == AR5K_AR5210) { |
192 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | 185 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, |
193 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); | 186 | AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 6fb5c5ffa5b1..8c638865c712 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -278,6 +278,7 @@ static ssize_t write_file_reset(struct file *file, | |||
278 | size_t count, loff_t *ppos) | 278 | size_t count, loff_t *ppos) |
279 | { | 279 | { |
280 | struct ath5k_softc *sc = file->private_data; | 280 | struct ath5k_softc *sc = file->private_data; |
281 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); | ||
281 | tasklet_schedule(&sc->restq); | 282 | tasklet_schedule(&sc->restq); |
282 | return count; | 283 | return count; |
283 | } | 284 | } |
@@ -307,7 +308,6 @@ static const struct { | |||
307 | { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, | 308 | { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, |
308 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | 309 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, |
309 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, | 310 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, |
310 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, | ||
311 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, | 311 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, |
312 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, | 312 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, |
313 | }; | 313 | }; |
@@ -426,6 +426,13 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf, | |||
426 | "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", | 426 | "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", |
427 | (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); | 427 | (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); |
428 | 428 | ||
429 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0); | ||
430 | len += snprintf(buf+len, sizeof(buf)-len, | ||
431 | "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v); | ||
432 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1); | ||
433 | len += snprintf(buf+len, sizeof(buf)-len, | ||
434 | "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v); | ||
435 | |||
429 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 436 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
430 | } | 437 | } |
431 | 438 | ||
@@ -729,6 +736,66 @@ static const struct file_operations fops_ani = { | |||
729 | }; | 736 | }; |
730 | 737 | ||
731 | 738 | ||
739 | /* debugfs: queues etc */ | ||
740 | |||
741 | static ssize_t read_file_queue(struct file *file, char __user *user_buf, | ||
742 | size_t count, loff_t *ppos) | ||
743 | { | ||
744 | struct ath5k_softc *sc = file->private_data; | ||
745 | char buf[700]; | ||
746 | unsigned int len = 0; | ||
747 | |||
748 | struct ath5k_txq *txq; | ||
749 | struct ath5k_buf *bf, *bf0; | ||
750 | int i, n = 0; | ||
751 | |||
752 | len += snprintf(buf+len, sizeof(buf)-len, | ||
753 | "available txbuffers: %d\n", sc->txbuf_len); | ||
754 | |||
755 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { | ||
756 | txq = &sc->txqs[i]; | ||
757 | |||
758 | len += snprintf(buf+len, sizeof(buf)-len, | ||
759 | "%02d: %ssetup\n", i, txq->setup ? "" : "not "); | ||
760 | |||
761 | if (!txq->setup) | ||
762 | continue; | ||
763 | |||
764 | list_for_each_entry_safe(bf, bf0, &txq->q, list) | ||
765 | n++; | ||
766 | len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n); | ||
767 | } | ||
768 | |||
769 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
770 | } | ||
771 | |||
772 | static ssize_t write_file_queue(struct file *file, | ||
773 | const char __user *userbuf, | ||
774 | size_t count, loff_t *ppos) | ||
775 | { | ||
776 | struct ath5k_softc *sc = file->private_data; | ||
777 | char buf[20]; | ||
778 | |||
779 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
780 | return -EFAULT; | ||
781 | |||
782 | if (strncmp(buf, "start", 5) == 0) | ||
783 | ieee80211_wake_queues(sc->hw); | ||
784 | else if (strncmp(buf, "stop", 4) == 0) | ||
785 | ieee80211_stop_queues(sc->hw); | ||
786 | |||
787 | return count; | ||
788 | } | ||
789 | |||
790 | |||
791 | static const struct file_operations fops_queue = { | ||
792 | .read = read_file_queue, | ||
793 | .write = write_file_queue, | ||
794 | .open = ath5k_debugfs_open, | ||
795 | .owner = THIS_MODULE, | ||
796 | }; | ||
797 | |||
798 | |||
732 | /* init */ | 799 | /* init */ |
733 | 800 | ||
734 | void | 801 | void |
@@ -772,6 +839,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc) | |||
772 | S_IWUSR | S_IRUSR, | 839 | S_IWUSR | S_IRUSR, |
773 | sc->debug.debugfs_phydir, sc, | 840 | sc->debug.debugfs_phydir, sc, |
774 | &fops_ani); | 841 | &fops_ani); |
842 | |||
843 | sc->debug.debugfs_queue = debugfs_create_file("queue", | ||
844 | S_IWUSR | S_IRUSR, | ||
845 | sc->debug.debugfs_phydir, sc, | ||
846 | &fops_queue); | ||
775 | } | 847 | } |
776 | 848 | ||
777 | void | 849 | void |
@@ -790,6 +862,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) | |||
790 | debugfs_remove(sc->debug.debugfs_antenna); | 862 | debugfs_remove(sc->debug.debugfs_antenna); |
791 | debugfs_remove(sc->debug.debugfs_frameerrors); | 863 | debugfs_remove(sc->debug.debugfs_frameerrors); |
792 | debugfs_remove(sc->debug.debugfs_ani); | 864 | debugfs_remove(sc->debug.debugfs_ani); |
865 | debugfs_remove(sc->debug.debugfs_queue); | ||
793 | debugfs_remove(sc->debug.debugfs_phydir); | 866 | debugfs_remove(sc->debug.debugfs_phydir); |
794 | } | 867 | } |
795 | 868 | ||
@@ -852,7 +925,7 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, | |||
852 | ds, (unsigned long long)bf->daddr, | 925 | ds, (unsigned long long)bf->daddr, |
853 | ds->ds_link, ds->ds_data, | 926 | ds->ds_link, ds->ds_data, |
854 | rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, | 927 | rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, |
855 | rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, | 928 | rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1, |
856 | !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); | 929 | !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); |
857 | } | 930 | } |
858 | 931 | ||
@@ -867,7 +940,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
867 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | 940 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) |
868 | return; | 941 | return; |
869 | 942 | ||
870 | printk(KERN_DEBUG "rx queue %x, link %p\n", | 943 | printk(KERN_DEBUG "rxdp %x, rxlink %p\n", |
871 | ath5k_hw_get_rxdp(ah), sc->rxlink); | 944 | ath5k_hw_get_rxdp(ah), sc->rxlink); |
872 | 945 | ||
873 | spin_lock_bh(&sc->rxbuflock); | 946 | spin_lock_bh(&sc->rxbuflock); |
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index ddd5b3a99e8d..606ae94a9157 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -77,6 +77,7 @@ struct ath5k_dbg_info { | |||
77 | struct dentry *debugfs_antenna; | 77 | struct dentry *debugfs_antenna; |
78 | struct dentry *debugfs_frameerrors; | 78 | struct dentry *debugfs_frameerrors; |
79 | struct dentry *debugfs_ani; | 79 | struct dentry *debugfs_ani; |
80 | struct dentry *debugfs_queue; | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | /** | 83 | /** |
@@ -115,18 +116,12 @@ enum ath5k_debug_level { | |||
115 | ATH5K_DEBUG_DUMP_RX = 0x00000100, | 116 | ATH5K_DEBUG_DUMP_RX = 0x00000100, |
116 | ATH5K_DEBUG_DUMP_TX = 0x00000200, | 117 | ATH5K_DEBUG_DUMP_TX = 0x00000200, |
117 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, | 118 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, |
118 | ATH5K_DEBUG_TRACE = 0x00001000, | ||
119 | ATH5K_DEBUG_ANI = 0x00002000, | 119 | ATH5K_DEBUG_ANI = 0x00002000, |
120 | ATH5K_DEBUG_ANY = 0xffffffff | 120 | ATH5K_DEBUG_ANY = 0xffffffff |
121 | }; | 121 | }; |
122 | 122 | ||
123 | #ifdef CONFIG_ATH5K_DEBUG | 123 | #ifdef CONFIG_ATH5K_DEBUG |
124 | 124 | ||
125 | #define ATH5K_TRACE(_sc) do { \ | ||
126 | if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ | ||
127 | printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \ | ||
128 | } while (0) | ||
129 | |||
130 | #define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ | 125 | #define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ |
131 | if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ | 126 | if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ |
132 | ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ | 127 | ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ |
@@ -168,8 +163,6 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); | |||
168 | 163 | ||
169 | #include <linux/compiler.h> | 164 | #include <linux/compiler.h> |
170 | 165 | ||
171 | #define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc)) | ||
172 | |||
173 | static inline void __attribute__ ((format (printf, 3, 4))) | 166 | static inline void __attribute__ ((format (printf, 3, 4))) |
174 | ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} | 167 | ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} |
175 | 168 | ||
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 7d7b646ab65a..43244382f213 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -91,14 +91,13 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
91 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; | 91 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Verify and set header length | 94 | * Verify and set header length (only 5210) |
95 | * XXX: I only found that on 5210 code, does it work on 5211 ? | ||
96 | */ | 95 | */ |
97 | if (ah->ah_version == AR5K_AR5210) { | 96 | if (ah->ah_version == AR5K_AR5210) { |
98 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) | 97 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210) |
99 | return -EINVAL; | 98 | return -EINVAL; |
100 | tx_ctl->tx_control_0 |= | 99 | tx_ctl->tx_control_0 |= |
101 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | 100 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210); |
102 | } | 101 | } |
103 | 102 | ||
104 | /*Differences between 5210-5211*/ | 103 | /*Differences between 5210-5211*/ |
@@ -110,11 +109,11 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
110 | case AR5K_PKT_TYPE_PIFS: | 109 | case AR5K_PKT_TYPE_PIFS: |
111 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; | 110 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; |
112 | default: | 111 | default: |
113 | frame_type = type /*<< 2 ?*/; | 112 | frame_type = type; |
114 | } | 113 | } |
115 | 114 | ||
116 | tx_ctl->tx_control_0 |= | 115 | tx_ctl->tx_control_0 |= |
117 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | | 116 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210) | |
118 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | 117 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); |
119 | 118 | ||
120 | } else { | 119 | } else { |
@@ -123,21 +122,30 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
123 | AR5K_REG_SM(antenna_mode, | 122 | AR5K_REG_SM(antenna_mode, |
124 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); | 123 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); |
125 | tx_ctl->tx_control_1 |= | 124 | tx_ctl->tx_control_1 |= |
126 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); | 125 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211); |
127 | } | 126 | } |
127 | |||
128 | #define _TX_FLAGS(_c, _flag) \ | 128 | #define _TX_FLAGS(_c, _flag) \ |
129 | if (flags & AR5K_TXDESC_##_flag) { \ | 129 | if (flags & AR5K_TXDESC_##_flag) { \ |
130 | tx_ctl->tx_control_##_c |= \ | 130 | tx_ctl->tx_control_##_c |= \ |
131 | AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ | 131 | AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ |
132 | } | 132 | } |
133 | 133 | #define _TX_FLAGS_5211(_c, _flag) \ | |
134 | if (flags & AR5K_TXDESC_##_flag) { \ | ||
135 | tx_ctl->tx_control_##_c |= \ | ||
136 | AR5K_2W_TX_DESC_CTL##_c##_##_flag##_5211; \ | ||
137 | } | ||
134 | _TX_FLAGS(0, CLRDMASK); | 138 | _TX_FLAGS(0, CLRDMASK); |
135 | _TX_FLAGS(0, VEOL); | ||
136 | _TX_FLAGS(0, INTREQ); | 139 | _TX_FLAGS(0, INTREQ); |
137 | _TX_FLAGS(0, RTSENA); | 140 | _TX_FLAGS(0, RTSENA); |
138 | _TX_FLAGS(1, NOACK); | 141 | |
142 | if (ah->ah_version == AR5K_AR5211) { | ||
143 | _TX_FLAGS_5211(0, VEOL); | ||
144 | _TX_FLAGS_5211(1, NOACK); | ||
145 | } | ||
139 | 146 | ||
140 | #undef _TX_FLAGS | 147 | #undef _TX_FLAGS |
148 | #undef _TX_FLAGS_5211 | ||
141 | 149 | ||
142 | /* | 150 | /* |
143 | * WEP crap | 151 | * WEP crap |
@@ -147,7 +155,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
147 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 155 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
148 | tx_ctl->tx_control_1 |= | 156 | tx_ctl->tx_control_1 |= |
149 | AR5K_REG_SM(key_index, | 157 | AR5K_REG_SM(key_index, |
150 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | 158 | AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX); |
151 | } | 159 | } |
152 | 160 | ||
153 | /* | 161 | /* |
@@ -156,7 +164,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
156 | if ((ah->ah_version == AR5K_AR5210) && | 164 | if ((ah->ah_version == AR5K_AR5210) && |
157 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) | 165 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) |
158 | tx_ctl->tx_control_1 |= rtscts_duration & | 166 | tx_ctl->tx_control_1 |= rtscts_duration & |
159 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; | 167 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210; |
160 | 168 | ||
161 | return 0; | 169 | return 0; |
162 | } | 170 | } |
@@ -176,7 +184,6 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
176 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 184 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
177 | unsigned int frame_len; | 185 | unsigned int frame_len; |
178 | 186 | ||
179 | ATH5K_TRACE(ah->ah_sc); | ||
180 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | 187 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
181 | 188 | ||
182 | /* | 189 | /* |
@@ -256,7 +263,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
256 | if (key_index != AR5K_TXKEYIX_INVALID) { | 263 | if (key_index != AR5K_TXKEYIX_INVALID) { |
257 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 264 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
258 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, | 265 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, |
259 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | 266 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); |
260 | } | 267 | } |
261 | 268 | ||
262 | /* | 269 | /* |
@@ -278,13 +285,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
278 | /* | 285 | /* |
279 | * Initialize a 4-word multi rate retry tx control descriptor on 5212 | 286 | * Initialize a 4-word multi rate retry tx control descriptor on 5212 |
280 | */ | 287 | */ |
281 | static int | 288 | int |
282 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 289 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
283 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | 290 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, |
284 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | 291 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) |
285 | { | 292 | { |
286 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 293 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
287 | 294 | ||
295 | /* no mrr support for cards older than 5212 */ | ||
296 | if (ah->ah_version < AR5K_AR5212) | ||
297 | return 0; | ||
298 | |||
288 | /* | 299 | /* |
289 | * Rates can be 0 as long as the retry count is 0 too. | 300 | * Rates can be 0 as long as the retry count is 0 too. |
290 | * A zero rate and nonzero retry count will put the HW into a mode where | 301 | * A zero rate and nonzero retry count will put the HW into a mode where |
@@ -324,15 +335,6 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
324 | return 0; | 335 | return 0; |
325 | } | 336 | } |
326 | 337 | ||
327 | /* no mrr support for cards older than 5212 */ | ||
328 | static int | ||
329 | ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
330 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | ||
331 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | ||
332 | { | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | /* | 338 | /* |
337 | * Proccess the tx status descriptor on 5210/5211 | 339 | * Proccess the tx status descriptor on 5210/5211 |
338 | */ | 340 | */ |
@@ -342,8 +344,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
342 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | 344 | struct ath5k_hw_2w_tx_ctl *tx_ctl; |
343 | struct ath5k_hw_tx_status *tx_status; | 345 | struct ath5k_hw_tx_status *tx_status; |
344 | 346 | ||
345 | ATH5K_TRACE(ah->ah_sc); | ||
346 | |||
347 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | 347 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; |
348 | tx_status = &desc->ud.ds_tx5210.tx_stat; | 348 | tx_status = &desc->ud.ds_tx5210.tx_stat; |
349 | 349 | ||
@@ -396,8 +396,6 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
396 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 396 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
397 | struct ath5k_hw_tx_status *tx_status; | 397 | struct ath5k_hw_tx_status *tx_status; |
398 | 398 | ||
399 | ATH5K_TRACE(ah->ah_sc); | ||
400 | |||
401 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | 399 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
402 | tx_status = &desc->ud.ds_tx5212.tx_stat; | 400 | tx_status = &desc->ud.ds_tx5212.tx_stat; |
403 | 401 | ||
@@ -419,11 +417,11 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
419 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | 417 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, |
420 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 418 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
421 | ts->ts_antenna = (tx_status->tx_status_1 & | 419 | ts->ts_antenna = (tx_status->tx_status_1 & |
422 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | 420 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; |
423 | ts->ts_status = 0; | 421 | ts->ts_status = 0; |
424 | 422 | ||
425 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, | 423 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, |
426 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); | 424 | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); |
427 | 425 | ||
428 | /* The longretry counter has the number of un-acked retries | 426 | /* The longretry counter has the number of un-acked retries |
429 | * for the final rate. To get the total number of retries | 427 | * for the final rate. To get the total number of retries |
@@ -485,12 +483,11 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
485 | /* | 483 | /* |
486 | * Initialize an rx control descriptor | 484 | * Initialize an rx control descriptor |
487 | */ | 485 | */ |
488 | static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 486 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
489 | u32 size, unsigned int flags) | 487 | u32 size, unsigned int flags) |
490 | { | 488 | { |
491 | struct ath5k_hw_rx_ctl *rx_ctl; | 489 | struct ath5k_hw_rx_ctl *rx_ctl; |
492 | 490 | ||
493 | ATH5K_TRACE(ah->ah_sc); | ||
494 | rx_ctl = &desc->ud.ds_rx.rx_ctl; | 491 | rx_ctl = &desc->ud.ds_rx.rx_ctl; |
495 | 492 | ||
496 | /* | 493 | /* |
@@ -502,10 +499,11 @@ static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
502 | */ | 499 | */ |
503 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); | 500 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); |
504 | 501 | ||
502 | if (unlikely(size & ~AR5K_DESC_RX_CTL1_BUF_LEN)) | ||
503 | return -EINVAL; | ||
504 | |||
505 | /* Setup descriptor */ | 505 | /* Setup descriptor */ |
506 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; | 506 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; |
507 | if (unlikely(rx_ctl->rx_control_1 != size)) | ||
508 | return -EINVAL; | ||
509 | 507 | ||
510 | if (flags & AR5K_RXDESC_INTREQ) | 508 | if (flags & AR5K_RXDESC_INTREQ) |
511 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; | 509 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; |
@@ -521,13 +519,15 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
521 | { | 519 | { |
522 | struct ath5k_hw_rx_status *rx_status; | 520 | struct ath5k_hw_rx_status *rx_status; |
523 | 521 | ||
524 | rx_status = &desc->ud.ds_rx.u.rx_stat; | 522 | rx_status = &desc->ud.ds_rx.rx_stat; |
525 | 523 | ||
526 | /* No frame received / not ready */ | 524 | /* No frame received / not ready */ |
527 | if (unlikely(!(rx_status->rx_status_1 & | 525 | if (unlikely(!(rx_status->rx_status_1 & |
528 | AR5K_5210_RX_DESC_STATUS1_DONE))) | 526 | AR5K_5210_RX_DESC_STATUS1_DONE))) |
529 | return -EINPROGRESS; | 527 | return -EINPROGRESS; |
530 | 528 | ||
529 | memset(rs, 0, sizeof(struct ath5k_rx_status)); | ||
530 | |||
531 | /* | 531 | /* |
532 | * Frame receive status | 532 | * Frame receive status |
533 | */ | 533 | */ |
@@ -537,15 +537,23 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
537 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); | 537 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
538 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | 538 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, |
539 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); | 539 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); |
540 | rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, | ||
541 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); | ||
542 | rs->rs_more = !!(rx_status->rx_status_0 & | 540 | rs->rs_more = !!(rx_status->rx_status_0 & |
543 | AR5K_5210_RX_DESC_STATUS0_MORE); | 541 | AR5K_5210_RX_DESC_STATUS0_MORE); |
544 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ | 542 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit! |
543 | * also the HAL code for 5210 says the timestamp is bits [10..22] of the | ||
544 | * TSF, and extends the timestamp here to 15 bit. | ||
545 | * we need to check on 5210... | ||
546 | */ | ||
545 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | 547 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
546 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 548 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
547 | rs->rs_status = 0; | 549 | |
548 | rs->rs_phyerr = 0; | 550 | if (ah->ah_version == AR5K_AR5211) |
551 | rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, | ||
552 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211); | ||
553 | else | ||
554 | rs->rs_antenna = (rx_status->rx_status_0 & | ||
555 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210) | ||
556 | ? 2 : 1; | ||
549 | 557 | ||
550 | /* | 558 | /* |
551 | * Key table status | 559 | * Key table status |
@@ -560,19 +568,21 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
560 | * Receive/descriptor errors | 568 | * Receive/descriptor errors |
561 | */ | 569 | */ |
562 | if (!(rx_status->rx_status_1 & | 570 | if (!(rx_status->rx_status_1 & |
563 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | 571 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
564 | if (rx_status->rx_status_1 & | 572 | if (rx_status->rx_status_1 & |
565 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) | 573 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) |
566 | rs->rs_status |= AR5K_RXERR_CRC; | 574 | rs->rs_status |= AR5K_RXERR_CRC; |
567 | 575 | ||
568 | if (rx_status->rx_status_1 & | 576 | /* only on 5210 */ |
569 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) | 577 | if ((ah->ah_version == AR5K_AR5210) && |
578 | (rx_status->rx_status_1 & | ||
579 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210)) | ||
570 | rs->rs_status |= AR5K_RXERR_FIFO; | 580 | rs->rs_status |= AR5K_RXERR_FIFO; |
571 | 581 | ||
572 | if (rx_status->rx_status_1 & | 582 | if (rx_status->rx_status_1 & |
573 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { | 583 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { |
574 | rs->rs_status |= AR5K_RXERR_PHY; | 584 | rs->rs_status |= AR5K_RXERR_PHY; |
575 | rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, | 585 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, |
576 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); | 586 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); |
577 | } | 587 | } |
578 | 588 | ||
@@ -588,22 +598,20 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
588 | * Proccess the rx status descriptor on 5212 | 598 | * Proccess the rx status descriptor on 5212 |
589 | */ | 599 | */ |
590 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | 600 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, |
591 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | 601 | struct ath5k_desc *desc, |
602 | struct ath5k_rx_status *rs) | ||
592 | { | 603 | { |
593 | struct ath5k_hw_rx_status *rx_status; | 604 | struct ath5k_hw_rx_status *rx_status; |
594 | struct ath5k_hw_rx_error *rx_err; | ||
595 | 605 | ||
596 | ATH5K_TRACE(ah->ah_sc); | 606 | rx_status = &desc->ud.ds_rx.rx_stat; |
597 | rx_status = &desc->ud.ds_rx.u.rx_stat; | ||
598 | |||
599 | /* Overlay on error */ | ||
600 | rx_err = &desc->ud.ds_rx.u.rx_err; | ||
601 | 607 | ||
602 | /* No frame received / not ready */ | 608 | /* No frame received / not ready */ |
603 | if (unlikely(!(rx_status->rx_status_1 & | 609 | if (unlikely(!(rx_status->rx_status_1 & |
604 | AR5K_5212_RX_DESC_STATUS1_DONE))) | 610 | AR5K_5212_RX_DESC_STATUS1_DONE))) |
605 | return -EINPROGRESS; | 611 | return -EINPROGRESS; |
606 | 612 | ||
613 | memset(rs, 0, sizeof(struct ath5k_rx_status)); | ||
614 | |||
607 | /* | 615 | /* |
608 | * Frame receive status | 616 | * Frame receive status |
609 | */ | 617 | */ |
@@ -619,15 +627,13 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
619 | AR5K_5212_RX_DESC_STATUS0_MORE); | 627 | AR5K_5212_RX_DESC_STATUS0_MORE); |
620 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | 628 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
621 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 629 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
622 | rs->rs_status = 0; | ||
623 | rs->rs_phyerr = 0; | ||
624 | 630 | ||
625 | /* | 631 | /* |
626 | * Key table status | 632 | * Key table status |
627 | */ | 633 | */ |
628 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) | 634 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
629 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | 635 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, |
630 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); | 636 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); |
631 | else | 637 | else |
632 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | 638 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
633 | 639 | ||
@@ -635,7 +641,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
635 | * Receive/descriptor errors | 641 | * Receive/descriptor errors |
636 | */ | 642 | */ |
637 | if (!(rx_status->rx_status_1 & | 643 | if (!(rx_status->rx_status_1 & |
638 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | 644 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
639 | if (rx_status->rx_status_1 & | 645 | if (rx_status->rx_status_1 & |
640 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) | 646 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
641 | rs->rs_status |= AR5K_RXERR_CRC; | 647 | rs->rs_status |= AR5K_RXERR_CRC; |
@@ -643,9 +649,10 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
643 | if (rx_status->rx_status_1 & | 649 | if (rx_status->rx_status_1 & |
644 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { | 650 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
645 | rs->rs_status |= AR5K_RXERR_PHY; | 651 | rs->rs_status |= AR5K_RXERR_PHY; |
646 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | 652 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, |
647 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | 653 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); |
648 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | 654 | if (!ah->ah_capabilities.cap_has_phyerr_counters) |
655 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | ||
649 | } | 656 | } |
650 | 657 | ||
651 | if (rx_status->rx_status_1 & | 658 | if (rx_status->rx_status_1 & |
@@ -656,7 +663,6 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
656 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) | 663 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
657 | rs->rs_status |= AR5K_RXERR_MIC; | 664 | rs->rs_status |= AR5K_RXERR_MIC; |
658 | } | 665 | } |
659 | |||
660 | return 0; | 666 | return 0; |
661 | } | 667 | } |
662 | 668 | ||
@@ -665,29 +671,15 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
665 | */ | 671 | */ |
666 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | 672 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) |
667 | { | 673 | { |
668 | |||
669 | if (ah->ah_version != AR5K_AR5210 && | ||
670 | ah->ah_version != AR5K_AR5211 && | ||
671 | ah->ah_version != AR5K_AR5212) | ||
672 | return -ENOTSUPP; | ||
673 | |||
674 | if (ah->ah_version == AR5K_AR5212) { | 674 | if (ah->ah_version == AR5K_AR5212) { |
675 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | ||
676 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | 675 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; |
677 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; | ||
678 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; | 676 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; |
679 | } else { | 677 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; |
680 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | 678 | } else if (ah->ah_version <= AR5K_AR5211) { |
681 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; | 679 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; |
682 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; | ||
683 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; | 680 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; |
684 | } | ||
685 | |||
686 | if (ah->ah_version == AR5K_AR5212) | ||
687 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; | ||
688 | else if (ah->ah_version <= AR5K_AR5211) | ||
689 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; | 681 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; |
690 | 682 | } else | |
683 | return -ENOTSUPP; | ||
691 | return 0; | 684 | return 0; |
692 | } | 685 | } |
693 | |||
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 64538fbe4167..b2adb2a281c2 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -17,28 +17,24 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * Internal RX/TX descriptor structures | 20 | * RX/TX descriptor structures |
21 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) | ||
22 | */ | 21 | */ |
23 | 22 | ||
24 | /* | 23 | /* |
25 | * common hardware RX control descriptor | 24 | * Common hardware RX control descriptor |
26 | */ | 25 | */ |
27 | struct ath5k_hw_rx_ctl { | 26 | struct ath5k_hw_rx_ctl { |
28 | u32 rx_control_0; /* RX control word 0 */ | 27 | u32 rx_control_0; /* RX control word 0 */ |
29 | u32 rx_control_1; /* RX control word 1 */ | 28 | u32 rx_control_1; /* RX control word 1 */ |
30 | } __packed; | 29 | } __packed; |
31 | 30 | ||
32 | /* RX control word 0 field/sflags */ | ||
33 | #define AR5K_DESC_RX_CTL0 0x00000000 | ||
34 | |||
35 | /* RX control word 1 fields/flags */ | 31 | /* RX control word 1 fields/flags */ |
36 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff | 32 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
37 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 | 33 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ |
38 | 34 | ||
39 | /* | 35 | /* |
40 | * common hardware RX status descriptor | 36 | * Common hardware RX status descriptor |
41 | * 5210/11 and 5212 differ only in the flags defined below | 37 | * 5210, 5211 and 5212 differ only in the fields and flags defined below |
42 | */ | 38 | */ |
43 | struct ath5k_hw_rx_status { | 39 | struct ath5k_hw_rx_status { |
44 | u32 rx_status_0; /* RX status word 0 */ | 40 | u32 rx_status_0; /* RX status word 0 */ |
@@ -47,81 +43,69 @@ struct ath5k_hw_rx_status { | |||
47 | 43 | ||
48 | /* 5210/5211 */ | 44 | /* 5210/5211 */ |
49 | /* RX status word 0 fields/flags */ | 45 | /* RX status word 0 fields/flags */ |
50 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff | 46 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff /* RX data length */ |
51 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 | 47 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 /* more desc for this frame */ |
52 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 | 48 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210 0x00004000 /* [5210] receive on ant 1 */ |
49 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 /* reception rate */ | ||
53 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | 50 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 |
54 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 | 51 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 /* rssi */ |
55 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 | 52 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 |
56 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 | 53 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211 0x38000000 /* [5211] receive antenna */ |
57 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 | 54 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211_S 27 |
58 | 55 | ||
59 | /* RX status word 1 fields/flags */ | 56 | /* RX status word 1 fields/flags */ |
60 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 | 57 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 /* descriptor complete */ |
61 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | 58 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* reception success */ |
62 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | 59 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */ |
63 | #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 | 60 | #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210 0x00000008 /* [5210] FIFO overrun */ |
64 | #define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 | 61 | #define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decyption CRC failure */ |
65 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 | 62 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 /* PHY error */ |
66 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 | 63 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 |
67 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | 64 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */ |
68 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 | 65 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decyption key index */ |
69 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 | 66 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 |
70 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 | 67 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 /* 13 bit of TSF */ |
71 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 | 68 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 |
72 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 | 69 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 /* key cache miss */ |
73 | 70 | ||
74 | /* 5212 */ | 71 | /* 5212 */ |
75 | /* RX status word 0 fields/flags */ | 72 | /* RX status word 0 fields/flags */ |
76 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff | 73 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff /* RX data length */ |
77 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 | 74 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 /* more desc for this frame */ |
78 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 | 75 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 /* decompression CRC error */ |
79 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 | 76 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 /* reception rate */ |
80 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | 77 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 |
81 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 | 78 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 /* rssi */ |
82 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 | 79 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 |
83 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 | 80 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 /* receive antenna */ |
84 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 | 81 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 |
85 | 82 | ||
86 | /* RX status word 1 fields/flags */ | 83 | /* RX status word 1 fields/flags */ |
87 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 | 84 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 /* descriptor complete */ |
88 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | 85 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* frame reception success */ |
89 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | 86 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */ |
90 | #define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 | 87 | #define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 /* decryption CRC failure */ |
91 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 | 88 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 /* PHY error */ |
92 | #define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 | 89 | #define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 /* MIC decrypt error */ |
93 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | 90 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */ |
94 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 | 91 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 /* decryption key index */ |
95 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 | 92 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 |
96 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 | 93 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 /* first 15bit of the TSF */ |
97 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 | 94 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 |
98 | #define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 | 95 | #define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 /* key cache miss */ |
99 | 96 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE 0x0000ff00 /* phy error code overlays key index and valid fields */ | |
100 | /* | 97 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE_S 8 |
101 | * common hardware RX error descriptor | ||
102 | */ | ||
103 | struct ath5k_hw_rx_error { | ||
104 | u32 rx_error_0; /* RX status word 0 */ | ||
105 | u32 rx_error_1; /* RX status word 1 */ | ||
106 | } __packed; | ||
107 | |||
108 | /* RX error word 0 fields/flags */ | ||
109 | #define AR5K_RX_DESC_ERROR0 0x00000000 | ||
110 | |||
111 | /* RX error word 1 fields/flags */ | ||
112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | ||
113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | ||
114 | 98 | ||
115 | /** | 99 | /** |
116 | * enum ath5k_phy_error_code - PHY Error codes | 100 | * enum ath5k_phy_error_code - PHY Error codes |
117 | */ | 101 | */ |
118 | enum ath5k_phy_error_code { | 102 | enum ath5k_phy_error_code { |
119 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ | 103 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun, [5210] No error */ |
120 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ | 104 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ |
121 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ | 105 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ |
122 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ | 106 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ |
123 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ | 107 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ |
124 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ | 108 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect, [5210] 64 QAM rate */ |
125 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ | 109 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ |
126 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ | 110 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ |
127 | /* these are specific to the 5212 */ | 111 | /* these are specific to the 5212 */ |
@@ -148,112 +132,111 @@ struct ath5k_hw_2w_tx_ctl { | |||
148 | } __packed; | 132 | } __packed; |
149 | 133 | ||
150 | /* TX control word 0 fields/flags */ | 134 | /* TX control word 0 fields/flags */ |
151 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 135 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ |
152 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ | 136 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210 0x0003f000 /* [5210] header length */ |
153 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 | 137 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210_S 12 |
154 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 | 138 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 /* tx rate */ |
155 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 | 139 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 |
156 | #define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 | 140 | #define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 /* RTS/CTS enable */ |
157 | #define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 | 141 | #define AR5K_2W_TX_DESC_CTL0_LONG_PACKET_5210 0x00800000 /* [5210] long packet */ |
158 | #define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ | 142 | #define AR5K_2W_TX_DESC_CTL0_VEOL_5211 0x00800000 /* [5211] virtual end-of-list */ |
159 | #define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ | 143 | #define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 /* clear destination mask */ |
160 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ | 144 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 /* [5210] antenna selection */ |
161 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 | 145 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 /* [5211] antenna selection */ |
162 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 | ||
163 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 | ||
164 | |||
165 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ | 146 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ |
166 | (ah->ah_version == AR5K_AR5210 ? \ | 147 | (ah->ah_version == AR5K_AR5210 ? \ |
167 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ | 148 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ |
168 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) | 149 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) |
169 | |||
170 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | 150 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 |
171 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 | 151 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210 0x1c000000 /* [5210] frame type */ |
172 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | 152 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210_S 26 |
153 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 /* TX interrupt request */ | ||
154 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 /* key is valid */ | ||
173 | 155 | ||
174 | /* TX control word 1 fields/flags */ | 156 | /* TX control word 1 fields/flags */ |
175 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff | 157 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
176 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 | 158 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 /* more desc for this frame */ |
177 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 | 159 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5210 0x0007e000 /* [5210] key table index */ |
178 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 | 160 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5211 0x000fe000 /* [5211] key table index */ |
179 | 161 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX \ | |
180 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ | ||
181 | (ah->ah_version == AR5K_AR5210 ? \ | 162 | (ah->ah_version == AR5K_AR5210 ? \ |
182 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ | 163 | AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5210 : \ |
183 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) | 164 | AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5211) |
184 | 165 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_S 13 | |
185 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | 166 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211 0x00700000 /* [5211] frame type */ |
186 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ | 167 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211_S 20 |
187 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 | 168 | #define AR5K_2W_TX_DESC_CTL1_NOACK_5211 0x00800000 /* [5211] no ACK */ |
188 | #define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ | 169 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210 0xfff80000 /* [5210] lower 13 bit of duration */ |
189 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ | ||
190 | 170 | ||
191 | /* Frame types */ | 171 | /* Frame types */ |
192 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 | 172 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0 |
193 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 | 173 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 1 |
194 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 | 174 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 2 |
195 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c | 175 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 3 |
196 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 | 176 | #define AR5K_AR5211_TX_DESC_FRAME_TYPE_BEACON 3 |
177 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 | ||
178 | #define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 | ||
197 | 179 | ||
198 | /* | 180 | /* |
199 | * 5212 hardware 4-word TX control descriptor | 181 | * 5212 hardware 4-word TX control descriptor |
200 | */ | 182 | */ |
201 | struct ath5k_hw_4w_tx_ctl { | 183 | struct ath5k_hw_4w_tx_ctl { |
202 | u32 tx_control_0; /* TX control word 0 */ | 184 | u32 tx_control_0; /* TX control word 0 */ |
185 | u32 tx_control_1; /* TX control word 1 */ | ||
186 | u32 tx_control_2; /* TX control word 2 */ | ||
187 | u32 tx_control_3; /* TX control word 3 */ | ||
188 | } __packed; | ||
203 | 189 | ||
204 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 190 | /* TX control word 0 fields/flags */ |
205 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 | 191 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ |
192 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 /* transmit power */ | ||
206 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 | 193 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 |
207 | #define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 | 194 | #define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 /* RTS/CTS enable */ |
208 | #define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 | 195 | #define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 /* virtual end-of-list */ |
209 | #define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 | 196 | #define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 /* clear destination mask */ |
210 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 | 197 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 /* TX antenna selection */ |
211 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | 198 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 |
212 | #define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 | 199 | #define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 /* TX interrupt request */ |
213 | #define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | 200 | #define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 /* destination index valid */ |
214 | #define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 | 201 | #define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 /* precede frame with CTS */ |
215 | |||
216 | u32 tx_control_1; /* TX control word 1 */ | ||
217 | 202 | ||
218 | #define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff | 203 | /* TX control word 1 fields/flags */ |
219 | #define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 | 204 | #define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
220 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 | 205 | #define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 /* more desc for this frame */ |
221 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | 206 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX 0x000fe000 /* destination table index */ |
222 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 | 207 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX_S 13 |
208 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 /* frame type */ | ||
223 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 | 209 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 |
224 | #define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 | 210 | #define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 /* no ACK */ |
225 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 | 211 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 /* compression processing */ |
226 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 | 212 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 |
227 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 | 213 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 /* length of frame IV */ |
228 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 | 214 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 |
229 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 | 215 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 /* length of frame ICV */ |
230 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 | 216 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 |
231 | 217 | ||
232 | u32 tx_control_2; /* TX control word 2 */ | 218 | /* TX control word 2 fields/flags */ |
233 | 219 | #define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff /* RTS/CTS duration */ | |
234 | #define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff | 220 | #define AR5K_4W_TX_DESC_CTL2_DURATION_UPD_EN 0x00008000 /* frame duration update */ |
235 | #define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 | 221 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 /* series 0 max attempts */ |
236 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 | 222 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 |
237 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 | 223 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 /* series 1 max attempts */ |
238 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 | 224 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 |
239 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 | 225 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 /* series 2 max attempts */ |
240 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 | 226 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 |
241 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 | 227 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 /* series 3 max attempts */ |
242 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 | 228 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 |
243 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 | 229 | |
244 | 230 | /* TX control word 3 fields/flags */ | |
245 | u32 tx_control_3; /* TX control word 3 */ | 231 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f /* series 0 tx rate */ |
246 | 232 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 /* series 1 tx rate */ | |
247 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f | ||
248 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 | ||
249 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 | 233 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 |
250 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 | 234 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 /* series 2 tx rate */ |
251 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 | 235 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 |
252 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 | 236 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 /* series 3 tx rate */ |
253 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 | 237 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 |
254 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 | 238 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ |
255 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 | 239 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 |
256 | } __packed; | ||
257 | 240 | ||
258 | /* | 241 | /* |
259 | * Common TX status descriptor | 242 | * Common TX status descriptor |
@@ -264,37 +247,34 @@ struct ath5k_hw_tx_status { | |||
264 | } __packed; | 247 | } __packed; |
265 | 248 | ||
266 | /* TX status word 0 fields/flags */ | 249 | /* TX status word 0 fields/flags */ |
267 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 | 250 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ |
268 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 | 251 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 /* excessive retries */ |
269 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 | 252 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 /* FIFO underrun */ |
270 | #define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 | 253 | #define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 /* TX filter indication */ |
271 | /*??? | 254 | /* according to the HAL sources the spec has short/long retry counts reversed. |
272 | #define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 | 255 | * we have it reversed to the HAL sources as well, for 5210 and 5211. |
273 | #define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 | 256 | * For 5212 these fields are defined as RTS_FAIL_COUNT and DATA_FAIL_COUNT, |
274 | */ | 257 | * but used respectively as SHORT and LONG retry count in the code later. This |
275 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 | 258 | * is consistent with the definitions here... TODO: check */ |
259 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 /* short retry count */ | ||
276 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 | 260 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 |
277 | /*??? | 261 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 /* long retry count */ |
278 | #define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 | ||
279 | #define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 | ||
280 | */ | ||
281 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 | ||
282 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 | 262 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 |
283 | #define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 | 263 | #define AR5K_DESC_TX_STATUS0_VIRTCOLL_CT_5211 0x0000f000 /* [5211+] virtual collision count */ |
284 | #define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 | 264 | #define AR5K_DESC_TX_STATUS0_VIRTCOLL_CT_5212_S 12 |
285 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 | 265 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 /* TX timestamp */ |
286 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 | 266 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 |
287 | 267 | ||
288 | /* TX status word 1 fields/flags */ | 268 | /* TX status word 1 fields/flags */ |
289 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 | 269 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 /* descriptor complete */ |
290 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe | 270 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe /* TX sequence number */ |
291 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 | 271 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 |
292 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 | 272 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 /* signal strength of ACK */ |
293 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 | 273 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 |
294 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 | 274 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212 0x00600000 /* [5212] final TX attempt series ix */ |
295 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 | 275 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212_S 21 |
296 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 | 276 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ |
297 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 | 277 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ |
298 | 278 | ||
299 | /* | 279 | /* |
300 | * 5210/5211 hardware TX descriptor | 280 | * 5210/5211 hardware TX descriptor |
@@ -313,18 +293,15 @@ struct ath5k_hw_5212_tx_desc { | |||
313 | } __packed; | 293 | } __packed; |
314 | 294 | ||
315 | /* | 295 | /* |
316 | * common hardware RX descriptor | 296 | * Common hardware RX descriptor |
317 | */ | 297 | */ |
318 | struct ath5k_hw_all_rx_desc { | 298 | struct ath5k_hw_all_rx_desc { |
319 | struct ath5k_hw_rx_ctl rx_ctl; | 299 | struct ath5k_hw_rx_ctl rx_ctl; |
320 | union { | 300 | struct ath5k_hw_rx_status rx_stat; |
321 | struct ath5k_hw_rx_status rx_stat; | ||
322 | struct ath5k_hw_rx_error rx_err; | ||
323 | } u; | ||
324 | } __packed; | 301 | } __packed; |
325 | 302 | ||
326 | /* | 303 | /* |
327 | * Atheros hardware descriptor | 304 | * Atheros hardware DMA descriptor |
328 | * This is read and written to by the hardware | 305 | * This is read and written to by the hardware |
329 | */ | 306 | */ |
330 | struct ath5k_desc { | 307 | struct ath5k_desc { |
@@ -346,4 +323,3 @@ struct ath5k_desc { | |||
346 | #define AR5K_TXDESC_CTSENA 0x0008 | 323 | #define AR5K_TXDESC_CTSENA 0x0008 |
347 | #define AR5K_TXDESC_INTREQ 0x0010 | 324 | #define AR5K_TXDESC_INTREQ 0x0010 |
348 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ | 325 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ |
349 | |||
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 941b51130a6f..484f31870ba8 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -48,7 +48,6 @@ | |||
48 | */ | 48 | */ |
49 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) | 49 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) |
50 | { | 50 | { |
51 | ATH5K_TRACE(ah->ah_sc); | ||
52 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); | 51 | ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); |
53 | ath5k_hw_reg_read(ah, AR5K_CR); | 52 | ath5k_hw_reg_read(ah, AR5K_CR); |
54 | } | 53 | } |
@@ -62,7 +61,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | |||
62 | { | 61 | { |
63 | unsigned int i; | 62 | unsigned int i; |
64 | 63 | ||
65 | ATH5K_TRACE(ah->ah_sc); | ||
66 | ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); | 64 | ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); |
67 | 65 | ||
68 | /* | 66 | /* |
@@ -96,8 +94,6 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) | |||
96 | */ | 94 | */ |
97 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | 95 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) |
98 | { | 96 | { |
99 | ATH5K_TRACE(ah->ah_sc); | ||
100 | |||
101 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); | 97 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); |
102 | } | 98 | } |
103 | 99 | ||
@@ -125,7 +121,6 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
125 | { | 121 | { |
126 | u32 tx_queue; | 122 | u32 tx_queue; |
127 | 123 | ||
128 | ATH5K_TRACE(ah->ah_sc); | ||
129 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 124 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
130 | 125 | ||
131 | /* Return if queue is declared inactive */ | 126 | /* Return if queue is declared inactive */ |
@@ -186,7 +181,6 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
186 | unsigned int i = 40; | 181 | unsigned int i = 40; |
187 | u32 tx_queue, pending; | 182 | u32 tx_queue, pending; |
188 | 183 | ||
189 | ATH5K_TRACE(ah->ah_sc); | ||
190 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 184 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
191 | 185 | ||
192 | /* Return if queue is declared inactive */ | 186 | /* Return if queue is declared inactive */ |
@@ -297,7 +291,6 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) | |||
297 | { | 291 | { |
298 | u16 tx_reg; | 292 | u16 tx_reg; |
299 | 293 | ||
300 | ATH5K_TRACE(ah->ah_sc); | ||
301 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 294 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
302 | 295 | ||
303 | /* | 296 | /* |
@@ -340,7 +333,6 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | |||
340 | { | 333 | { |
341 | u16 tx_reg; | 334 | u16 tx_reg; |
342 | 335 | ||
343 | ATH5K_TRACE(ah->ah_sc); | ||
344 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 336 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
345 | 337 | ||
346 | /* | 338 | /* |
@@ -400,8 +392,6 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) | |||
400 | u32 trigger_level, imr; | 392 | u32 trigger_level, imr; |
401 | int ret = -EIO; | 393 | int ret = -EIO; |
402 | 394 | ||
403 | ATH5K_TRACE(ah->ah_sc); | ||
404 | |||
405 | /* | 395 | /* |
406 | * Disable interrupts by setting the mask | 396 | * Disable interrupts by setting the mask |
407 | */ | 397 | */ |
@@ -451,7 +441,6 @@ done: | |||
451 | */ | 441 | */ |
452 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) | 442 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) |
453 | { | 443 | { |
454 | ATH5K_TRACE(ah->ah_sc); | ||
455 | return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; | 444 | return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; |
456 | } | 445 | } |
457 | 446 | ||
@@ -475,8 +464,6 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) | |||
475 | { | 464 | { |
476 | u32 data; | 465 | u32 data; |
477 | 466 | ||
478 | ATH5K_TRACE(ah->ah_sc); | ||
479 | |||
480 | /* | 467 | /* |
481 | * Read interrupt status from the Interrupt Status register | 468 | * Read interrupt status from the Interrupt Status register |
482 | * on 5210 | 469 | * on 5210 |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ed0263672d6d..ae316fec4a6a 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -35,7 +35,6 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | |||
35 | { | 35 | { |
36 | u32 status, timeout; | 36 | u32 status, timeout; |
37 | 37 | ||
38 | ATH5K_TRACE(ah->ah_sc); | ||
39 | /* | 38 | /* |
40 | * Initialize EEPROM access | 39 | * Initialize EEPROM access |
41 | */ | 40 | */ |
@@ -715,7 +714,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
715 | 714 | ||
716 | /* Only one curve for RF5111 | 715 | /* Only one curve for RF5111 |
717 | * find out which one and place | 716 | * find out which one and place |
718 | * in in pd_curves. | 717 | * in pd_curves. |
719 | * Note: ee_x_gain is reversed here */ | 718 | * Note: ee_x_gain is reversed here */ |
720 | for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { | 719 | for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { |
721 | 720 | ||
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c index 64a27e73d02e..bc90503f4b7a 100644 --- a/drivers/net/wireless/ath/ath5k/gpio.c +++ b/drivers/net/wireless/ath/ath5k/gpio.c | |||
@@ -34,8 +34,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | |||
34 | /*5210 has different led mode handling*/ | 34 | /*5210 has different led mode handling*/ |
35 | u32 led_5210; | 35 | u32 led_5210; |
36 | 36 | ||
37 | ATH5K_TRACE(ah->ah_sc); | ||
38 | |||
39 | /*Reset led status*/ | 37 | /*Reset led status*/ |
40 | if (ah->ah_version != AR5K_AR5210) | 38 | if (ah->ah_version != AR5K_AR5210) |
41 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | 39 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, |
@@ -82,7 +80,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | |||
82 | */ | 80 | */ |
83 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | 81 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) |
84 | { | 82 | { |
85 | ATH5K_TRACE(ah->ah_sc); | ||
86 | if (gpio >= AR5K_NUM_GPIO) | 83 | if (gpio >= AR5K_NUM_GPIO) |
87 | return -EINVAL; | 84 | return -EINVAL; |
88 | 85 | ||
@@ -98,7 +95,6 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | |||
98 | */ | 95 | */ |
99 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | 96 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) |
100 | { | 97 | { |
101 | ATH5K_TRACE(ah->ah_sc); | ||
102 | if (gpio >= AR5K_NUM_GPIO) | 98 | if (gpio >= AR5K_NUM_GPIO) |
103 | return -EINVAL; | 99 | return -EINVAL; |
104 | 100 | ||
@@ -114,7 +110,6 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | |||
114 | */ | 110 | */ |
115 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | 111 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) |
116 | { | 112 | { |
117 | ATH5K_TRACE(ah->ah_sc); | ||
118 | if (gpio >= AR5K_NUM_GPIO) | 113 | if (gpio >= AR5K_NUM_GPIO) |
119 | return 0xffffffff; | 114 | return 0xffffffff; |
120 | 115 | ||
@@ -129,7 +124,6 @@ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | |||
129 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | 124 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) |
130 | { | 125 | { |
131 | u32 data; | 126 | u32 data; |
132 | ATH5K_TRACE(ah->ah_sc); | ||
133 | 127 | ||
134 | if (gpio >= AR5K_NUM_GPIO) | 128 | if (gpio >= AR5K_NUM_GPIO) |
135 | return -EINVAL; | 129 | return -EINVAL; |
@@ -153,7 +147,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | |||
153 | { | 147 | { |
154 | u32 data; | 148 | u32 data; |
155 | 149 | ||
156 | ATH5K_TRACE(ah->ah_sc); | ||
157 | if (gpio >= AR5K_NUM_GPIO) | 150 | if (gpio >= AR5K_NUM_GPIO) |
158 | return; | 151 | return; |
159 | 152 | ||
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 5212e275f1c7..86fdb6ddfaaa 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -59,8 +59,6 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | |||
59 | 59 | ||
60 | beacon_reg = 0; | 60 | beacon_reg = 0; |
61 | 61 | ||
62 | ATH5K_TRACE(ah->ah_sc); | ||
63 | |||
64 | switch (op_mode) { | 62 | switch (op_mode) { |
65 | case NL80211_IFTYPE_ADHOC: | 63 | case NL80211_IFTYPE_ADHOC: |
66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | 64 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; |
@@ -173,7 +171,6 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
173 | */ | 171 | */ |
174 | static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 172 | static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
175 | { | 173 | { |
176 | ATH5K_TRACE(ah->ah_sc); | ||
177 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) | 174 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
178 | <= timeout) | 175 | <= timeout) |
179 | return -EINVAL; | 176 | return -EINVAL; |
@@ -192,7 +189,6 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
192 | */ | 189 | */ |
193 | static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 190 | static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
194 | { | 191 | { |
195 | ATH5K_TRACE(ah->ah_sc); | ||
196 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) | 192 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
197 | <= timeout) | 193 | <= timeout) |
198 | return -EINVAL; | 194 | return -EINVAL; |
@@ -297,7 +293,6 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
297 | u32 low_id, high_id; | 293 | u32 low_id, high_id; |
298 | u32 pcu_reg; | 294 | u32 pcu_reg; |
299 | 295 | ||
300 | ATH5K_TRACE(ah->ah_sc); | ||
301 | /* Set new station ID */ | 296 | /* Set new station ID */ |
302 | memcpy(common->macaddr, mac, ETH_ALEN); | 297 | memcpy(common->macaddr, mac, ETH_ALEN); |
303 | 298 | ||
@@ -357,7 +352,6 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah) | |||
357 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | 352 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) |
358 | { | 353 | { |
359 | struct ath_common *common = ath5k_hw_common(ah); | 354 | struct ath_common *common = ath5k_hw_common(ah); |
360 | ATH5K_TRACE(ah->ah_sc); | ||
361 | 355 | ||
362 | /* Cache bssid mask so that we can restore it | 356 | /* Cache bssid mask so that we can restore it |
363 | * on reset */ | 357 | * on reset */ |
@@ -382,7 +376,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
382 | */ | 376 | */ |
383 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 377 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) |
384 | { | 378 | { |
385 | ATH5K_TRACE(ah->ah_sc); | ||
386 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 379 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
387 | } | 380 | } |
388 | 381 | ||
@@ -397,7 +390,6 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | |||
397 | */ | 390 | */ |
398 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | 391 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) |
399 | { | 392 | { |
400 | ATH5K_TRACE(ah->ah_sc); | ||
401 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | 393 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
402 | } | 394 | } |
403 | 395 | ||
@@ -406,8 +398,6 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | |||
406 | */ | 398 | */ |
407 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | 399 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) |
408 | { | 400 | { |
409 | ATH5K_TRACE(ah->ah_sc); | ||
410 | /* Set the multicat filter */ | ||
411 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); | 401 | ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); |
412 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | 402 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); |
413 | } | 403 | } |
@@ -427,7 +417,6 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) | |||
427 | { | 417 | { |
428 | u32 data, filter = 0; | 418 | u32 data, filter = 0; |
429 | 419 | ||
430 | ATH5K_TRACE(ah->ah_sc); | ||
431 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); | 420 | filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); |
432 | 421 | ||
433 | /*Radar detection for 5212*/ | 422 | /*Radar detection for 5212*/ |
@@ -457,8 +446,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
457 | { | 446 | { |
458 | u32 data = 0; | 447 | u32 data = 0; |
459 | 448 | ||
460 | ATH5K_TRACE(ah->ah_sc); | ||
461 | |||
462 | /* Set PHY error filter register on 5212*/ | 449 | /* Set PHY error filter register on 5212*/ |
463 | if (ah->ah_version == AR5K_AR5212) { | 450 | if (ah->ah_version == AR5K_AR5212) { |
464 | if (filter & AR5K_RX_FILTER_RADARERR) | 451 | if (filter & AR5K_RX_FILTER_RADARERR) |
@@ -533,8 +520,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | |||
533 | 520 | ||
534 | WARN_ON( i == ATH5K_MAX_TSF_READ ); | 521 | WARN_ON( i == ATH5K_MAX_TSF_READ ); |
535 | 522 | ||
536 | ATH5K_TRACE(ah->ah_sc); | ||
537 | |||
538 | return (((u64)tsf_upper1 << 32) | tsf_lower); | 523 | return (((u64)tsf_upper1 << 32) | tsf_lower); |
539 | } | 524 | } |
540 | 525 | ||
@@ -548,8 +533,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | |||
548 | */ | 533 | */ |
549 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) | 534 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) |
550 | { | 535 | { |
551 | ATH5K_TRACE(ah->ah_sc); | ||
552 | |||
553 | ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); | 536 | ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); |
554 | ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); | 537 | ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); |
555 | } | 538 | } |
@@ -565,8 +548,6 @@ void ath5k_hw_reset_tsf(struct ath5k_hw *ah) | |||
565 | { | 548 | { |
566 | u32 val; | 549 | u32 val; |
567 | 550 | ||
568 | ATH5K_TRACE(ah->ah_sc); | ||
569 | |||
570 | val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; | 551 | val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; |
571 | 552 | ||
572 | /* | 553 | /* |
@@ -586,7 +567,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
586 | { | 567 | { |
587 | u32 timer1, timer2, timer3; | 568 | u32 timer1, timer2, timer3; |
588 | 569 | ||
589 | ATH5K_TRACE(ah->ah_sc); | ||
590 | /* | 570 | /* |
591 | * Set the additional timers by mode | 571 | * Set the additional timers by mode |
592 | */ | 572 | */ |
@@ -674,7 +654,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
674 | unsigned int i, type; | 654 | unsigned int i, type; |
675 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | 655 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; |
676 | 656 | ||
677 | ATH5K_TRACE(ah->ah_sc); | ||
678 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 657 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
679 | 658 | ||
680 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); | 659 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); |
@@ -749,8 +728,6 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | |||
749 | bool is_tkip; | 728 | bool is_tkip; |
750 | const u8 *key_ptr; | 729 | const u8 *key_ptr; |
751 | 730 | ||
752 | ATH5K_TRACE(ah->ah_sc); | ||
753 | |||
754 | is_tkip = (key->alg == ALG_TKIP); | 731 | is_tkip = (key->alg == ALG_TKIP); |
755 | 732 | ||
756 | /* | 733 | /* |
@@ -836,7 +813,6 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
836 | { | 813 | { |
837 | u32 low_id, high_id; | 814 | u32 low_id, high_id; |
838 | 815 | ||
839 | ATH5K_TRACE(ah->ah_sc); | ||
840 | /* Invalid entry (key table overflow) */ | 816 | /* Invalid entry (key table overflow) */ |
841 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 817 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
842 | 818 | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 492cbb15720d..73c4fcd142bb 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -378,8 +378,6 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) | |||
378 | u32 data, type; | 378 | u32 data, type; |
379 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 379 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
380 | 380 | ||
381 | ATH5K_TRACE(ah->ah_sc); | ||
382 | |||
383 | if (ah->ah_rf_banks == NULL || | 381 | if (ah->ah_rf_banks == NULL || |
384 | ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) | 382 | ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) |
385 | return AR5K_RFGAIN_INACTIVE; | 383 | return AR5K_RFGAIN_INACTIVE; |
@@ -1167,7 +1165,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | |||
1167 | * The median of the values in the history is then loaded into the | 1165 | * The median of the values in the history is then loaded into the |
1168 | * hardware for its own use for RSSI and CCA measurements. | 1166 | * hardware for its own use for RSSI and CCA measurements. |
1169 | */ | 1167 | */ |
1170 | static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | 1168 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) |
1171 | { | 1169 | { |
1172 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 1170 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1173 | u32 val; | 1171 | u32 val; |
@@ -1248,7 +1246,6 @@ static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1248 | /* | 1246 | /* |
1249 | * Perform a PHY calibration on RF5110 | 1247 | * Perform a PHY calibration on RF5110 |
1250 | * -Fix BPSK/QAM Constellation (I/Q correction) | 1248 | * -Fix BPSK/QAM Constellation (I/Q correction) |
1251 | * -Calculate Noise Floor | ||
1252 | */ | 1249 | */ |
1253 | static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | 1250 | static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, |
1254 | struct ieee80211_channel *channel) | 1251 | struct ieee80211_channel *channel) |
@@ -1335,8 +1332,6 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1335 | return ret; | 1332 | return ret; |
1336 | } | 1333 | } |
1337 | 1334 | ||
1338 | ath5k_hw_update_noise_floor(ah); | ||
1339 | |||
1340 | /* | 1335 | /* |
1341 | * Re-enable RX/TX and beacons | 1336 | * Re-enable RX/TX and beacons |
1342 | */ | 1337 | */ |
@@ -1348,22 +1343,20 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1348 | } | 1343 | } |
1349 | 1344 | ||
1350 | /* | 1345 | /* |
1351 | * Perform a PHY calibration on RF5111/5112 and newer chips | 1346 | * Perform I/Q calibration on RF5111/5112 and newer chips |
1352 | */ | 1347 | */ |
1353 | static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | 1348 | static int |
1354 | struct ieee80211_channel *channel) | 1349 | ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) |
1355 | { | 1350 | { |
1356 | u32 i_pwr, q_pwr; | 1351 | u32 i_pwr, q_pwr; |
1357 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; | 1352 | s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; |
1358 | int i; | 1353 | int i; |
1359 | ATH5K_TRACE(ah->ah_sc); | ||
1360 | 1354 | ||
1361 | if (!ah->ah_calibration || | 1355 | if (!ah->ah_calibration || |
1362 | ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) | 1356 | ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) |
1363 | goto done; | 1357 | return 0; |
1364 | 1358 | ||
1365 | /* Calibration has finished, get the results and re-run */ | 1359 | /* Calibration has finished, get the results and re-run */ |
1366 | |||
1367 | /* work around empty results which can apparently happen on 5212 */ | 1360 | /* work around empty results which can apparently happen on 5212 */ |
1368 | for (i = 0; i <= 10; i++) { | 1361 | for (i = 0; i <= 10; i++) { |
1369 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); | 1362 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); |
@@ -1384,7 +1377,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1384 | 1377 | ||
1385 | /* protect against divide by 0 and loss of sign bits */ | 1378 | /* protect against divide by 0 and loss of sign bits */ |
1386 | if (i_coffd == 0 || q_coffd < 2) | 1379 | if (i_coffd == 0 || q_coffd < 2) |
1387 | goto done; | 1380 | return -1; |
1388 | 1381 | ||
1389 | i_coff = (-iq_corr) / i_coffd; | 1382 | i_coff = (-iq_corr) / i_coffd; |
1390 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1383 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
@@ -1410,17 +1403,6 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1410 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | 1403 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); |
1411 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); | 1404 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); |
1412 | 1405 | ||
1413 | done: | ||
1414 | |||
1415 | /* TODO: Separate noise floor calibration from I/Q calibration | ||
1416 | * since noise floor calibration interrupts rx path while I/Q | ||
1417 | * calibration doesn't. We don't need to run noise floor calibration | ||
1418 | * as often as I/Q calibration.*/ | ||
1419 | ath5k_hw_update_noise_floor(ah); | ||
1420 | |||
1421 | /* Initiate a gain_F calibration */ | ||
1422 | ath5k_hw_request_rfgain_probe(ah); | ||
1423 | |||
1424 | return 0; | 1406 | return 0; |
1425 | } | 1407 | } |
1426 | 1408 | ||
@@ -1434,8 +1416,10 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1434 | 1416 | ||
1435 | if (ah->ah_radio == AR5K_RF5110) | 1417 | if (ah->ah_radio == AR5K_RF5110) |
1436 | ret = ath5k_hw_rf5110_calibrate(ah, channel); | 1418 | ret = ath5k_hw_rf5110_calibrate(ah, channel); |
1437 | else | 1419 | else { |
1438 | ret = ath5k_hw_rf511x_calibrate(ah, channel); | 1420 | ret = ath5k_hw_rf511x_iq_calibrate(ah); |
1421 | ath5k_hw_request_rfgain_probe(ah); | ||
1422 | } | ||
1439 | 1423 | ||
1440 | return ret; | 1424 | return ret; |
1441 | } | 1425 | } |
@@ -1693,7 +1677,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1693 | 1677 | ||
1694 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | 1678 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) |
1695 | { | 1679 | { |
1696 | ATH5K_TRACE(ah->ah_sc); | ||
1697 | /*Just a try M.F.*/ | 1680 | /*Just a try M.F.*/ |
1698 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | 1681 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); |
1699 | 1682 | ||
@@ -1709,8 +1692,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | |||
1709 | u32 srev; | 1692 | u32 srev; |
1710 | u16 ret; | 1693 | u16 ret; |
1711 | 1694 | ||
1712 | ATH5K_TRACE(ah->ah_sc); | ||
1713 | |||
1714 | /* | 1695 | /* |
1715 | * Set the radio chip access register | 1696 | * Set the radio chip access register |
1716 | */ | 1697 | */ |
@@ -1755,8 +1736,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | |||
1755 | static void /*TODO:Boundary check*/ | 1736 | static void /*TODO:Boundary check*/ |
1756 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) | 1737 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) |
1757 | { | 1738 | { |
1758 | ATH5K_TRACE(ah->ah_sc); | ||
1759 | |||
1760 | if (ah->ah_version != AR5K_AR5210) | 1739 | if (ah->ah_version != AR5K_AR5210) |
1761 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); | 1740 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); |
1762 | } | 1741 | } |
@@ -1789,19 +1768,50 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) | |||
1789 | 1768 | ||
1790 | if (enable) { | 1769 | if (enable) { |
1791 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, | 1770 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, |
1792 | AR5K_PHY_RESTART_DIV_GC, 0xc); | 1771 | AR5K_PHY_RESTART_DIV_GC, 1); |
1793 | 1772 | ||
1794 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, | 1773 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, |
1795 | AR5K_PHY_FAST_ANT_DIV_EN); | 1774 | AR5K_PHY_FAST_ANT_DIV_EN); |
1796 | } else { | 1775 | } else { |
1797 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, | 1776 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, |
1798 | AR5K_PHY_RESTART_DIV_GC, 0x8); | 1777 | AR5K_PHY_RESTART_DIV_GC, 0); |
1799 | 1778 | ||
1800 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, | 1779 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, |
1801 | AR5K_PHY_FAST_ANT_DIV_EN); | 1780 | AR5K_PHY_FAST_ANT_DIV_EN); |
1802 | } | 1781 | } |
1803 | } | 1782 | } |
1804 | 1783 | ||
1784 | void | ||
1785 | ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) | ||
1786 | { | ||
1787 | u8 ant0, ant1; | ||
1788 | |||
1789 | /* | ||
1790 | * In case a fixed antenna was set as default | ||
1791 | * use the same switch table twice. | ||
1792 | */ | ||
1793 | if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) | ||
1794 | ant0 = ant1 = AR5K_ANT_SWTABLE_A; | ||
1795 | else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) | ||
1796 | ant0 = ant1 = AR5K_ANT_SWTABLE_B; | ||
1797 | else { | ||
1798 | ant0 = AR5K_ANT_SWTABLE_A; | ||
1799 | ant1 = AR5K_ANT_SWTABLE_B; | ||
1800 | } | ||
1801 | |||
1802 | /* Set antenna idle switch table */ | ||
1803 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, | ||
1804 | AR5K_PHY_ANT_CTL_SWTABLE_IDLE, | ||
1805 | (ah->ah_ant_ctl[ee_mode][AR5K_ANT_CTL] | | ||
1806 | AR5K_PHY_ANT_CTL_TXRX_EN)); | ||
1807 | |||
1808 | /* Set antenna switch tables */ | ||
1809 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant0], | ||
1810 | AR5K_PHY_ANT_SWITCH_TABLE_0); | ||
1811 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant1], | ||
1812 | AR5K_PHY_ANT_SWITCH_TABLE_1); | ||
1813 | } | ||
1814 | |||
1805 | /* | 1815 | /* |
1806 | * Set antenna operating mode | 1816 | * Set antenna operating mode |
1807 | */ | 1817 | */ |
@@ -1823,8 +1833,6 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1823 | 1833 | ||
1824 | def_ant = ah->ah_def_ant; | 1834 | def_ant = ah->ah_def_ant; |
1825 | 1835 | ||
1826 | ATH5K_TRACE(ah->ah_sc); | ||
1827 | |||
1828 | switch (channel->hw_value & CHANNEL_MODES) { | 1836 | switch (channel->hw_value & CHANNEL_MODES) { |
1829 | case CHANNEL_A: | 1837 | case CHANNEL_A: |
1830 | case CHANNEL_T: | 1838 | case CHANNEL_T: |
@@ -1923,6 +1931,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1923 | if (sta_id1) | 1931 | if (sta_id1) |
1924 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); | 1932 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); |
1925 | 1933 | ||
1934 | ath5k_hw_set_antenna_switch(ah, ee_mode); | ||
1926 | /* Note: set diversity before default antenna | 1935 | /* Note: set diversity before default antenna |
1927 | * because it won't work correctly */ | 1936 | * because it won't work correctly */ |
1928 | ath5k_hw_set_fast_div(ah, ee_mode, fast_div); | 1937 | ath5k_hw_set_fast_div(ah, ee_mode, fast_div); |
@@ -2988,7 +2997,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
2988 | u8 type; | 2997 | u8 type; |
2989 | int ret; | 2998 | int ret; |
2990 | 2999 | ||
2991 | ATH5K_TRACE(ah->ah_sc); | ||
2992 | if (txpower > AR5K_TUNE_MAX_TXPOWER) { | 3000 | if (txpower > AR5K_TUNE_MAX_TXPOWER) { |
2993 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); | 3001 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); |
2994 | return -EINVAL; | 3002 | return -EINVAL; |
@@ -3084,8 +3092,6 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | |||
3084 | struct ieee80211_channel *channel = ah->ah_current_channel; | 3092 | struct ieee80211_channel *channel = ah->ah_current_channel; |
3085 | u8 ee_mode; | 3093 | u8 ee_mode; |
3086 | 3094 | ||
3087 | ATH5K_TRACE(ah->ah_sc); | ||
3088 | |||
3089 | switch (channel->hw_value & CHANNEL_MODES) { | 3095 | switch (channel->hw_value & CHANNEL_MODES) { |
3090 | case CHANNEL_A: | 3096 | case CHANNEL_A: |
3091 | case CHANNEL_T: | 3097 | case CHANNEL_T: |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index f5831da33f7b..4186ff4c6e9c 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -31,7 +31,6 @@ Queue Control Unit, DFS Control Unit Functions | |||
31 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 31 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
32 | struct ath5k_txq_info *queue_info) | 32 | struct ath5k_txq_info *queue_info) |
33 | { | 33 | { |
34 | ATH5K_TRACE(ah->ah_sc); | ||
35 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | 34 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); |
36 | return 0; | 35 | return 0; |
37 | } | 36 | } |
@@ -42,7 +41,6 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
42 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 41 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
43 | const struct ath5k_txq_info *queue_info) | 42 | const struct ath5k_txq_info *queue_info) |
44 | { | 43 | { |
45 | ATH5K_TRACE(ah->ah_sc); | ||
46 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 44 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
47 | 45 | ||
48 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 46 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) |
@@ -69,8 +67,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
69 | unsigned int queue; | 67 | unsigned int queue; |
70 | int ret; | 68 | int ret; |
71 | 69 | ||
72 | ATH5K_TRACE(ah->ah_sc); | ||
73 | |||
74 | /* | 70 | /* |
75 | * Get queue by type | 71 | * Get queue by type |
76 | */ | 72 | */ |
@@ -149,7 +145,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
149 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | 145 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) |
150 | { | 146 | { |
151 | u32 pending; | 147 | u32 pending; |
152 | ATH5K_TRACE(ah->ah_sc); | ||
153 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 148 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
154 | 149 | ||
155 | /* Return if queue is declared inactive */ | 150 | /* Return if queue is declared inactive */ |
@@ -177,7 +172,6 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | |||
177 | */ | 172 | */ |
178 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 173 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) |
179 | { | 174 | { |
180 | ATH5K_TRACE(ah->ah_sc); | ||
181 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | 175 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) |
182 | return; | 176 | return; |
183 | 177 | ||
@@ -195,7 +189,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
195 | u32 cw_min, cw_max, retry_lg, retry_sh; | 189 | u32 cw_min, cw_max, retry_lg, retry_sh; |
196 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | 190 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; |
197 | 191 | ||
198 | ATH5K_TRACE(ah->ah_sc); | ||
199 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 192 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
200 | 193 | ||
201 | tq = &ah->ah_txq[queue]; | 194 | tq = &ah->ah_txq[queue]; |
@@ -523,8 +516,6 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | |||
523 | { | 516 | { |
524 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); | 517 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); |
525 | 518 | ||
526 | ATH5K_TRACE(ah->ah_sc); | ||
527 | |||
528 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) | 519 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) |
529 | return -EINVAL; | 520 | return -EINVAL; |
530 | 521 | ||
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 307f80e83f94..498aa28ea9e6 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -201,8 +201,6 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
201 | int ret; | 201 | int ret; |
202 | u32 mask = val ? val : ~0U; | 202 | u32 mask = val ? val : ~0U; |
203 | 203 | ||
204 | ATH5K_TRACE(ah->ah_sc); | ||
205 | |||
206 | /* Read-and-clear RX Descriptor Pointer*/ | 204 | /* Read-and-clear RX Descriptor Pointer*/ |
207 | ath5k_hw_reg_read(ah, AR5K_RXDP); | 205 | ath5k_hw_reg_read(ah, AR5K_RXDP); |
208 | 206 | ||
@@ -246,7 +244,6 @@ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | |||
246 | unsigned int i; | 244 | unsigned int i; |
247 | u32 staid, data; | 245 | u32 staid, data; |
248 | 246 | ||
249 | ATH5K_TRACE(ah->ah_sc); | ||
250 | staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); | 247 | staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); |
251 | 248 | ||
252 | switch (mode) { | 249 | switch (mode) { |
@@ -393,8 +390,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
393 | mode = 0; | 390 | mode = 0; |
394 | clock = 0; | 391 | clock = 0; |
395 | 392 | ||
396 | ATH5K_TRACE(ah->ah_sc); | ||
397 | |||
398 | /* Wakeup the device */ | 393 | /* Wakeup the device */ |
399 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 394 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); |
400 | if (ret) { | 395 | if (ret) { |
@@ -734,7 +729,7 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
734 | } | 729 | } |
735 | 730 | ||
736 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | 731 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, |
737 | struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) | 732 | struct ieee80211_channel *channel, u8 ee_mode) |
738 | { | 733 | { |
739 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 734 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
740 | s16 cck_ofdm_pwr_delta; | 735 | s16 cck_ofdm_pwr_delta; |
@@ -768,17 +763,9 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
768 | ee->ee_cck_ofdm_gain_delta; | 763 | ee->ee_cck_ofdm_gain_delta; |
769 | } | 764 | } |
770 | 765 | ||
771 | /* Set antenna idle switch table */ | 766 | /* XXX: necessary here? is called from ath5k_hw_set_antenna_mode() |
772 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, | 767 | * too */ |
773 | AR5K_PHY_ANT_CTL_SWTABLE_IDLE, | 768 | ath5k_hw_set_antenna_switch(ah, ee_mode); |
774 | (ah->ah_ant_ctl[ee_mode][0] | | ||
775 | AR5K_PHY_ANT_CTL_TXRX_EN)); | ||
776 | |||
777 | /* Set antenna switch tables */ | ||
778 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], | ||
779 | AR5K_PHY_ANT_SWITCH_TABLE_0); | ||
780 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], | ||
781 | AR5K_PHY_ANT_SWITCH_TABLE_1); | ||
782 | 769 | ||
783 | /* Noise floor threshold */ | 770 | /* Noise floor threshold */ |
784 | ath5k_hw_reg_write(ah, | 771 | ath5k_hw_reg_write(ah, |
@@ -855,7 +842,6 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
855 | AR5K_PHY_NF_THRESH62, | 842 | AR5K_PHY_NF_THRESH62, |
856 | ee->ee_thr_62[ee_mode]); | 843 | ee->ee_thr_62[ee_mode]); |
857 | 844 | ||
858 | |||
859 | /* False detect backoff for channels | 845 | /* False detect backoff for channels |
860 | * that have spur noise. Write the new | 846 | * that have spur noise. Write the new |
861 | * cyclic power RSSI threshold. */ | 847 | * cyclic power RSSI threshold. */ |
@@ -891,14 +877,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
891 | struct ieee80211_channel *channel, bool change_channel) | 877 | struct ieee80211_channel *channel, bool change_channel) |
892 | { | 878 | { |
893 | struct ath_common *common = ath5k_hw_common(ah); | 879 | struct ath_common *common = ath5k_hw_common(ah); |
894 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; | 880 | u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; |
895 | u32 phy_tst1; | 881 | u32 phy_tst1; |
896 | u8 mode, freq, ee_mode, ant[2]; | 882 | u8 mode, freq, ee_mode; |
897 | int i, ret; | 883 | int i, ret; |
898 | 884 | ||
899 | ATH5K_TRACE(ah->ah_sc); | ||
900 | |||
901 | s_ant = 0; | ||
902 | ee_mode = 0; | 885 | ee_mode = 0; |
903 | staid1_flags = 0; | 886 | staid1_flags = 0; |
904 | tsf_up = 0; | 887 | tsf_up = 0; |
@@ -995,9 +978,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
995 | } | 978 | } |
996 | } | 979 | } |
997 | 980 | ||
998 | /* Save default antenna */ | ||
999 | s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | ||
1000 | |||
1001 | if (ah->ah_version == AR5K_AR5212) { | 981 | if (ah->ah_version == AR5K_AR5212) { |
1002 | /* Restore normal 32/40MHz clock operation | 982 | /* Restore normal 32/40MHz clock operation |
1003 | * to avoid register access delay on certain | 983 | * to avoid register access delay on certain |
@@ -1094,22 +1074,17 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1094 | /* Write OFDM timings on 5212*/ | 1074 | /* Write OFDM timings on 5212*/ |
1095 | if (ah->ah_version == AR5K_AR5212 && | 1075 | if (ah->ah_version == AR5K_AR5212 && |
1096 | channel->hw_value & CHANNEL_OFDM) { | 1076 | channel->hw_value & CHANNEL_OFDM) { |
1097 | struct ath5k_eeprom_info *ee = | ||
1098 | &ah->ah_capabilities.cap_eeprom; | ||
1099 | 1077 | ||
1100 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | 1078 | ret = ath5k_hw_write_ofdm_timings(ah, channel); |
1101 | if (ret) | 1079 | if (ret) |
1102 | return ret; | 1080 | return ret; |
1103 | 1081 | ||
1104 | /* Note: According to docs we can have a newer | 1082 | /* Spur info is available only from EEPROM versions |
1105 | * EEPROM on old hardware, so we need to verify | 1083 | * bigger than 5.3 but but the EEPOM routines will use |
1106 | * that our hardware is new enough to have spur | 1084 | * static values for older versions */ |
1107 | * mitigation registers (delta phase etc) */ | 1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) |
1108 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424 || | ||
1109 | (ah->ah_mac_srev >= AR5K_SREV_AR5424 && | ||
1110 | ee->ee_version >= AR5K_EEPROM_VERSION_5_3)) | ||
1111 | ath5k_hw_set_spur_mitigation_filter(ah, | 1086 | ath5k_hw_set_spur_mitigation_filter(ah, |
1112 | channel); | 1087 | channel); |
1113 | } | 1088 | } |
1114 | 1089 | ||
1115 | /*Enable/disable 802.11b mode on 5111 | 1090 | /*Enable/disable 802.11b mode on 5111 |
@@ -1123,21 +1098,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1123 | AR5K_TXCFG_B_MODE); | 1098 | AR5K_TXCFG_B_MODE); |
1124 | } | 1099 | } |
1125 | 1100 | ||
1126 | /* | ||
1127 | * In case a fixed antenna was set as default | ||
1128 | * use the same switch table twice. | ||
1129 | */ | ||
1130 | if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) | ||
1131 | ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; | ||
1132 | else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) | ||
1133 | ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; | ||
1134 | else { | ||
1135 | ant[0] = AR5K_ANT_SWTABLE_A; | ||
1136 | ant[1] = AR5K_ANT_SWTABLE_B; | ||
1137 | } | ||
1138 | |||
1139 | /* Commit values from EEPROM */ | 1101 | /* Commit values from EEPROM */ |
1140 | ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode); | 1102 | ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); |
1141 | 1103 | ||
1142 | } else { | 1104 | } else { |
1143 | /* | 1105 | /* |
@@ -1175,8 +1137,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1175 | ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); | 1137 | ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); |
1176 | } | 1138 | } |
1177 | } | 1139 | } |
1178 | |||
1179 | ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); | ||
1180 | } | 1140 | } |
1181 | 1141 | ||
1182 | /* Ledstate */ | 1142 | /* Ledstate */ |
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c new file mode 100644 index 000000000000..90757de7bf59 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/sysfs.c | |||
@@ -0,0 +1,116 @@ | |||
1 | #include <linux/device.h> | ||
2 | #include <linux/pci.h> | ||
3 | |||
4 | #include "base.h" | ||
5 | #include "ath5k.h" | ||
6 | #include "reg.h" | ||
7 | |||
8 | #define SIMPLE_SHOW_STORE(name, get, set) \ | ||
9 | static ssize_t ath5k_attr_show_##name(struct device *dev, \ | ||
10 | struct device_attribute *attr, \ | ||
11 | char *buf) \ | ||
12 | { \ | ||
13 | struct ath5k_softc *sc = dev_get_drvdata(dev); \ | ||
14 | return snprintf(buf, PAGE_SIZE, "%d\n", get); \ | ||
15 | } \ | ||
16 | \ | ||
17 | static ssize_t ath5k_attr_store_##name(struct device *dev, \ | ||
18 | struct device_attribute *attr, \ | ||
19 | const char *buf, size_t count) \ | ||
20 | { \ | ||
21 | struct ath5k_softc *sc = dev_get_drvdata(dev); \ | ||
22 | int val; \ | ||
23 | \ | ||
24 | val = (int)simple_strtoul(buf, NULL, 10); \ | ||
25 | set(sc->ah, val); \ | ||
26 | return count; \ | ||
27 | } \ | ||
28 | static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \ | ||
29 | ath5k_attr_show_##name, ath5k_attr_store_##name) | ||
30 | |||
31 | #define SIMPLE_SHOW(name, get) \ | ||
32 | static ssize_t ath5k_attr_show_##name(struct device *dev, \ | ||
33 | struct device_attribute *attr, \ | ||
34 | char *buf) \ | ||
35 | { \ | ||
36 | struct ath5k_softc *sc = dev_get_drvdata(dev); \ | ||
37 | return snprintf(buf, PAGE_SIZE, "%d\n", get); \ | ||
38 | } \ | ||
39 | static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) | ||
40 | |||
41 | /*** ANI ***/ | ||
42 | |||
43 | SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init); | ||
44 | SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level, | ||
45 | ath5k_ani_set_noise_immunity_level); | ||
46 | SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level, | ||
47 | ath5k_ani_set_spur_immunity_level); | ||
48 | SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level, | ||
49 | ath5k_ani_set_firstep_level); | ||
50 | SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig, | ||
51 | ath5k_ani_set_ofdm_weak_signal_detection); | ||
52 | SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig, | ||
53 | ath5k_ani_set_cck_weak_signal_detection); | ||
54 | SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level); | ||
55 | |||
56 | static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev, | ||
57 | struct device_attribute *attr, | ||
58 | char *buf) | ||
59 | { | ||
60 | return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
61 | } | ||
62 | static DEVICE_ATTR(noise_immunity_level_max, S_IRUGO, | ||
63 | ath5k_attr_show_noise_immunity_level_max, NULL); | ||
64 | |||
65 | static ssize_t ath5k_attr_show_firstep_level_max(struct device *dev, | ||
66 | struct device_attribute *attr, | ||
67 | char *buf) | ||
68 | { | ||
69 | return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
70 | } | ||
71 | static DEVICE_ATTR(firstep_level_max, S_IRUGO, | ||
72 | ath5k_attr_show_firstep_level_max, NULL); | ||
73 | |||
74 | static struct attribute *ath5k_sysfs_entries_ani[] = { | ||
75 | &dev_attr_ani_mode.attr, | ||
76 | &dev_attr_noise_immunity_level.attr, | ||
77 | &dev_attr_spur_level.attr, | ||
78 | &dev_attr_firstep_level.attr, | ||
79 | &dev_attr_ofdm_weak_signal_detection.attr, | ||
80 | &dev_attr_cck_weak_signal_detection.attr, | ||
81 | &dev_attr_noise_immunity_level_max.attr, | ||
82 | &dev_attr_spur_level_max.attr, | ||
83 | &dev_attr_firstep_level_max.attr, | ||
84 | NULL | ||
85 | }; | ||
86 | |||
87 | static struct attribute_group ath5k_attribute_group_ani = { | ||
88 | .name = "ani", | ||
89 | .attrs = ath5k_sysfs_entries_ani, | ||
90 | }; | ||
91 | |||
92 | |||
93 | /*** register / unregister ***/ | ||
94 | |||
95 | int | ||
96 | ath5k_sysfs_register(struct ath5k_softc *sc) | ||
97 | { | ||
98 | struct device *dev = &sc->pdev->dev; | ||
99 | int err; | ||
100 | |||
101 | err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); | ||
102 | if (err) { | ||
103 | ATH5K_ERR(sc, "failed to create sysfs group\n"); | ||
104 | return err; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | void | ||
111 | ath5k_sysfs_unregister(struct ath5k_softc *sc) | ||
112 | { | ||
113 | struct device *dev = &sc->pdev->dev; | ||
114 | |||
115 | sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); | ||
116 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index dd112be218ab..973ae4f49f35 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -32,7 +32,8 @@ ath9k_hw-y:= \ | |||
32 | mac.o \ | 32 | mac.o \ |
33 | ar9002_mac.o \ | 33 | ar9002_mac.o \ |
34 | ar9003_mac.o \ | 34 | ar9003_mac.o \ |
35 | ar9003_eeprom.o | 35 | ar9003_eeprom.o \ |
36 | ar9003_paprd.o | ||
36 | 37 | ||
37 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 38 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o |
38 | 39 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index ba8b20f01594..cc648b6ae31c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2010 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,8 +17,99 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | 19 | ||
20 | static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 20 | struct ani_ofdm_level_entry { |
21 | struct ath9k_channel *chan) | 21 | int spur_immunity_level; |
22 | int fir_step_level; | ||
23 | int ofdm_weak_signal_on; | ||
24 | }; | ||
25 | |||
26 | /* values here are relative to the INI */ | ||
27 | |||
28 | /* | ||
29 | * Legend: | ||
30 | * | ||
31 | * SI: Spur immunity | ||
32 | * FS: FIR Step | ||
33 | * WS: OFDM / CCK Weak Signal detection | ||
34 | * MRC-CCK: Maximal Ratio Combining for CCK | ||
35 | */ | ||
36 | |||
37 | static const struct ani_ofdm_level_entry ofdm_level_table[] = { | ||
38 | /* SI FS WS */ | ||
39 | { 0, 0, 1 }, /* lvl 0 */ | ||
40 | { 1, 1, 1 }, /* lvl 1 */ | ||
41 | { 2, 2, 1 }, /* lvl 2 */ | ||
42 | { 3, 2, 1 }, /* lvl 3 (default) */ | ||
43 | { 4, 3, 1 }, /* lvl 4 */ | ||
44 | { 5, 4, 1 }, /* lvl 5 */ | ||
45 | { 6, 5, 1 }, /* lvl 6 */ | ||
46 | { 7, 6, 1 }, /* lvl 7 */ | ||
47 | { 7, 7, 1 }, /* lvl 8 */ | ||
48 | { 7, 8, 0 } /* lvl 9 */ | ||
49 | }; | ||
50 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ | ||
51 | (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) | ||
52 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ | ||
53 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) | ||
54 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ | ||
55 | 3 /* default level - matches the INI settings */ | ||
56 | |||
57 | /* | ||
58 | * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm. | ||
59 | * With OFDM for single stream you just add up all antenna inputs, you're | ||
60 | * only interested in what you get after FFT. Signal aligment is also not | ||
61 | * required for OFDM because any phase difference adds up in the frequency | ||
62 | * domain. | ||
63 | * | ||
64 | * MRC requires extra work for use with CCK. You need to align the antenna | ||
65 | * signals from the different antenna before you can add the signals together. | ||
66 | * You need aligment of signals as CCK is in time domain, so addition can cancel | ||
67 | * your signal completely if phase is 180 degrees (think of adding sine waves). | ||
68 | * You also need to remove noise before the addition and this is where ANI | ||
69 | * MRC CCK comes into play. One of the antenna inputs may be stronger but | ||
70 | * lower SNR, so just adding after alignment can be dangerous. | ||
71 | * | ||
72 | * Regardless of alignment in time, the antenna signals add constructively after | ||
73 | * FFT and improve your reception. For more information: | ||
74 | * | ||
75 | * http://en.wikipedia.org/wiki/Maximal-ratio_combining | ||
76 | */ | ||
77 | |||
78 | struct ani_cck_level_entry { | ||
79 | int fir_step_level; | ||
80 | int mrc_cck_on; | ||
81 | }; | ||
82 | |||
83 | static const struct ani_cck_level_entry cck_level_table[] = { | ||
84 | /* FS MRC-CCK */ | ||
85 | { 0, 1 }, /* lvl 0 */ | ||
86 | { 1, 1 }, /* lvl 1 */ | ||
87 | { 2, 1 }, /* lvl 2 (default) */ | ||
88 | { 3, 1 }, /* lvl 3 */ | ||
89 | { 4, 0 }, /* lvl 4 */ | ||
90 | { 5, 0 }, /* lvl 5 */ | ||
91 | { 6, 0 }, /* lvl 6 */ | ||
92 | { 7, 0 }, /* lvl 7 (only for high rssi) */ | ||
93 | { 8, 0 } /* lvl 8 (only for high rssi) */ | ||
94 | }; | ||
95 | |||
96 | #define ATH9K_ANI_CCK_NUM_LEVEL \ | ||
97 | (sizeof(cck_level_table)/sizeof(cck_level_table[0])) | ||
98 | #define ATH9K_ANI_CCK_MAX_LEVEL \ | ||
99 | (ATH9K_ANI_CCK_NUM_LEVEL-1) | ||
100 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ | ||
101 | (ATH9K_ANI_CCK_NUM_LEVEL-3) | ||
102 | #define ATH9K_ANI_CCK_DEF_LEVEL \ | ||
103 | 2 /* default level - matches the INI settings */ | ||
104 | |||
105 | /* Private to ani.c */ | ||
106 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | ||
107 | { | ||
108 | ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); | ||
109 | } | ||
110 | |||
111 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
112 | struct ath9k_channel *chan) | ||
22 | { | 113 | { |
23 | int i; | 114 | int i; |
24 | 115 | ||
@@ -48,7 +139,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
48 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | 139 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); |
49 | } | 140 | } |
50 | 141 | ||
51 | static void ath9k_ani_restart(struct ath_hw *ah) | 142 | static void ath9k_ani_restart_old(struct ath_hw *ah) |
52 | { | 143 | { |
53 | struct ar5416AniState *aniState; | 144 | struct ar5416AniState *aniState; |
54 | struct ath_common *common = ath9k_hw_common(ah); | 145 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -96,7 +187,42 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
96 | aniState->cckPhyErrCount = 0; | 187 | aniState->cckPhyErrCount = 0; |
97 | } | 188 | } |
98 | 189 | ||
99 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | 190 | static void ath9k_ani_restart_new(struct ath_hw *ah) |
191 | { | ||
192 | struct ar5416AniState *aniState; | ||
193 | struct ath_common *common = ath9k_hw_common(ah); | ||
194 | |||
195 | if (!DO_ANI(ah)) | ||
196 | return; | ||
197 | |||
198 | aniState = ah->curani; | ||
199 | aniState->listenTime = 0; | ||
200 | |||
201 | aniState->ofdmPhyErrBase = 0; | ||
202 | aniState->cckPhyErrBase = 0; | ||
203 | |||
204 | ath_print(common, ATH_DBG_ANI, | ||
205 | "Writing ofdmbase=%08x cckbase=%08x\n", | ||
206 | aniState->ofdmPhyErrBase, | ||
207 | aniState->cckPhyErrBase); | ||
208 | |||
209 | ENABLE_REGWRITE_BUFFER(ah); | ||
210 | |||
211 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
212 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
213 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
214 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
215 | |||
216 | REGWRITE_BUFFER_FLUSH(ah); | ||
217 | DISABLE_REGWRITE_BUFFER(ah); | ||
218 | |||
219 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
220 | |||
221 | aniState->ofdmPhyErrCount = 0; | ||
222 | aniState->cckPhyErrCount = 0; | ||
223 | } | ||
224 | |||
225 | static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) | ||
100 | { | 226 | { |
101 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 227 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
102 | struct ar5416AniState *aniState; | 228 | struct ar5416AniState *aniState; |
@@ -168,7 +294,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | |||
168 | } | 294 | } |
169 | } | 295 | } |
170 | 296 | ||
171 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | 297 | static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) |
172 | { | 298 | { |
173 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 299 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
174 | struct ar5416AniState *aniState; | 300 | struct ar5416AniState *aniState; |
@@ -206,7 +332,125 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | |||
206 | } | 332 | } |
207 | } | 333 | } |
208 | 334 | ||
209 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | 335 | /* Adjust the OFDM Noise Immunity Level */ |
336 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | ||
337 | { | ||
338 | struct ar5416AniState *aniState = ah->curani; | ||
339 | struct ath_common *common = ath9k_hw_common(ah); | ||
340 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
341 | const struct ani_cck_level_entry *entry_cck; | ||
342 | |||
343 | aniState->noiseFloor = BEACON_RSSI(ah); | ||
344 | |||
345 | ath_print(common, ATH_DBG_ANI, | ||
346 | "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | ||
347 | aniState->ofdmNoiseImmunityLevel, | ||
348 | immunityLevel, aniState->noiseFloor, | ||
349 | aniState->rssiThrLow, aniState->rssiThrHigh); | ||
350 | |||
351 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | ||
352 | |||
353 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | ||
354 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | ||
355 | |||
356 | if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level) | ||
357 | ath9k_hw_ani_control(ah, | ||
358 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
359 | entry_ofdm->spur_immunity_level); | ||
360 | |||
361 | if (aniState->firstepLevel != entry_ofdm->fir_step_level && | ||
362 | entry_ofdm->fir_step_level >= entry_cck->fir_step_level) | ||
363 | ath9k_hw_ani_control(ah, | ||
364 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
365 | entry_ofdm->fir_step_level); | ||
366 | |||
367 | if ((ah->opmode != NL80211_IFTYPE_STATION && | ||
368 | ah->opmode != NL80211_IFTYPE_ADHOC) || | ||
369 | aniState->noiseFloor <= aniState->rssiThrHigh) { | ||
370 | if (aniState->ofdmWeakSigDetectOff) | ||
371 | /* force on ofdm weak sig detect */ | ||
372 | ath9k_hw_ani_control(ah, | ||
373 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
374 | true); | ||
375 | else if (aniState->ofdmWeakSigDetectOff == | ||
376 | entry_ofdm->ofdm_weak_signal_on) | ||
377 | ath9k_hw_ani_control(ah, | ||
378 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
379 | entry_ofdm->ofdm_weak_signal_on); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | ||
384 | { | ||
385 | struct ar5416AniState *aniState; | ||
386 | |||
387 | if (!DO_ANI(ah)) | ||
388 | return; | ||
389 | |||
390 | aniState = ah->curani; | ||
391 | |||
392 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | ||
393 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * Set the ANI settings to match an CCK level. | ||
398 | */ | ||
399 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | ||
400 | { | ||
401 | struct ar5416AniState *aniState = ah->curani; | ||
402 | struct ath_common *common = ath9k_hw_common(ah); | ||
403 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
404 | const struct ani_cck_level_entry *entry_cck; | ||
405 | |||
406 | aniState->noiseFloor = BEACON_RSSI(ah); | ||
407 | ath_print(common, ATH_DBG_ANI, | ||
408 | "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | ||
409 | aniState->cckNoiseImmunityLevel, immunityLevel, | ||
410 | aniState->noiseFloor, aniState->rssiThrLow, | ||
411 | aniState->rssiThrHigh); | ||
412 | |||
413 | if ((ah->opmode == NL80211_IFTYPE_STATION || | ||
414 | ah->opmode == NL80211_IFTYPE_ADHOC) && | ||
415 | aniState->noiseFloor <= aniState->rssiThrLow && | ||
416 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) | ||
417 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; | ||
418 | |||
419 | aniState->cckNoiseImmunityLevel = immunityLevel; | ||
420 | |||
421 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | ||
422 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | ||
423 | |||
424 | if (aniState->firstepLevel != entry_cck->fir_step_level && | ||
425 | entry_cck->fir_step_level >= entry_ofdm->fir_step_level) | ||
426 | ath9k_hw_ani_control(ah, | ||
427 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
428 | entry_cck->fir_step_level); | ||
429 | |||
430 | /* Skip MRC CCK for pre AR9003 families */ | ||
431 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
432 | return; | ||
433 | |||
434 | if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) | ||
435 | ath9k_hw_ani_control(ah, | ||
436 | ATH9K_ANI_MRC_CCK, | ||
437 | entry_cck->mrc_cck_on); | ||
438 | } | ||
439 | |||
440 | static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) | ||
441 | { | ||
442 | struct ar5416AniState *aniState; | ||
443 | |||
444 | if (!DO_ANI(ah)) | ||
445 | return; | ||
446 | |||
447 | aniState = ah->curani; | ||
448 | |||
449 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | ||
450 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); | ||
451 | } | ||
452 | |||
453 | static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | ||
210 | { | 454 | { |
211 | struct ar5416AniState *aniState; | 455 | struct ar5416AniState *aniState; |
212 | int32_t rssi; | 456 | int32_t rssi; |
@@ -259,9 +503,53 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | |||
259 | } | 503 | } |
260 | } | 504 | } |
261 | 505 | ||
506 | /* | ||
507 | * only lower either OFDM or CCK errors per turn | ||
508 | * we lower the other one next time | ||
509 | */ | ||
510 | static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) | ||
511 | { | ||
512 | struct ar5416AniState *aniState; | ||
513 | |||
514 | aniState = ah->curani; | ||
515 | |||
516 | /* lower OFDM noise immunity */ | ||
517 | if (aniState->ofdmNoiseImmunityLevel > 0 && | ||
518 | (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) { | ||
519 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | /* lower CCK noise immunity */ | ||
524 | if (aniState->cckNoiseImmunityLevel > 0) | ||
525 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); | ||
526 | } | ||
527 | |||
528 | static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | ||
529 | { | ||
530 | struct ath9k_channel *chan = ah->curchan; | ||
531 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
532 | u8 clockrate; /* in MHz */ | ||
533 | |||
534 | if (!ah->curchan) /* should really check for CCK instead */ | ||
535 | clockrate = ATH9K_CLOCK_RATE_CCK; | ||
536 | else if (conf->channel->band == IEEE80211_BAND_2GHZ) | ||
537 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; | ||
538 | else if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | ||
539 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; | ||
540 | else | ||
541 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; | ||
542 | |||
543 | if (conf_is_ht40(conf)) | ||
544 | return clockrate * 2; | ||
545 | |||
546 | return clockrate * 2; | ||
547 | } | ||
548 | |||
262 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | 549 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) |
263 | { | 550 | { |
264 | struct ar5416AniState *aniState; | 551 | struct ar5416AniState *aniState; |
552 | struct ath_common *common = ath9k_hw_common(ah); | ||
265 | u32 txFrameCount, rxFrameCount, cycleCount; | 553 | u32 txFrameCount, rxFrameCount, cycleCount; |
266 | int32_t listenTime; | 554 | int32_t listenTime; |
267 | 555 | ||
@@ -271,15 +559,31 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | |||
271 | 559 | ||
272 | aniState = ah->curani; | 560 | aniState = ah->curani; |
273 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { | 561 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { |
274 | |||
275 | listenTime = 0; | 562 | listenTime = 0; |
276 | ah->stats.ast_ani_lzero++; | 563 | ah->stats.ast_ani_lzero++; |
564 | ath_print(common, ATH_DBG_ANI, | ||
565 | "1st call: aniState->cycleCount=%d\n", | ||
566 | aniState->cycleCount); | ||
277 | } else { | 567 | } else { |
278 | int32_t ccdelta = cycleCount - aniState->cycleCount; | 568 | int32_t ccdelta = cycleCount - aniState->cycleCount; |
279 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; | 569 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; |
280 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; | 570 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; |
281 | listenTime = (ccdelta - rfdelta - tfdelta) / 44000; | 571 | int32_t clock_rate; |
572 | |||
573 | /* | ||
574 | * convert HW counter values to ms using mode | ||
575 | * specifix clock rate | ||
576 | */ | ||
577 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; | ||
578 | |||
579 | listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; | ||
580 | |||
581 | ath_print(common, ATH_DBG_ANI, | ||
582 | "cyclecount=%d, rfcount=%d, " | ||
583 | "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", | ||
584 | ccdelta, rfdelta, tfdelta, listenTime, clock_rate); | ||
282 | } | 585 | } |
586 | |||
283 | aniState->cycleCount = cycleCount; | 587 | aniState->cycleCount = cycleCount; |
284 | aniState->txFrameCount = txFrameCount; | 588 | aniState->txFrameCount = txFrameCount; |
285 | aniState->rxFrameCount = rxFrameCount; | 589 | aniState->rxFrameCount = rxFrameCount; |
@@ -287,7 +591,7 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | |||
287 | return listenTime; | 591 | return listenTime; |
288 | } | 592 | } |
289 | 593 | ||
290 | void ath9k_ani_reset(struct ath_hw *ah) | 594 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) |
291 | { | 595 | { |
292 | struct ar5416AniState *aniState; | 596 | struct ar5416AniState *aniState; |
293 | struct ath9k_channel *chan = ah->curchan; | 597 | struct ath9k_channel *chan = ah->curchan; |
@@ -340,7 +644,7 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
340 | ah->curani->cckTrigLow = | 644 | ah->curani->cckTrigLow = |
341 | ah->config.cck_trig_low; | 645 | ah->config.cck_trig_low; |
342 | } | 646 | } |
343 | ath9k_ani_restart(ah); | 647 | ath9k_ani_restart_old(ah); |
344 | return; | 648 | return; |
345 | } | 649 | } |
346 | 650 | ||
@@ -362,7 +666,7 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
362 | 666 | ||
363 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & | 667 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & |
364 | ~ATH9K_RX_FILTER_PHYERR); | 668 | ~ATH9K_RX_FILTER_PHYERR); |
365 | ath9k_ani_restart(ah); | 669 | ath9k_ani_restart_old(ah); |
366 | 670 | ||
367 | ENABLE_REGWRITE_BUFFER(ah); | 671 | ENABLE_REGWRITE_BUFFER(ah); |
368 | 672 | ||
@@ -373,8 +677,102 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
373 | DISABLE_REGWRITE_BUFFER(ah); | 677 | DISABLE_REGWRITE_BUFFER(ah); |
374 | } | 678 | } |
375 | 679 | ||
376 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 680 | /* |
377 | struct ath9k_channel *chan) | 681 | * Restore the ANI parameters in the HAL and reset the statistics. |
682 | * This routine should be called for every hardware reset and for | ||
683 | * every channel change. | ||
684 | */ | ||
685 | static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | ||
686 | { | ||
687 | struct ar5416AniState *aniState = ah->curani; | ||
688 | struct ath9k_channel *chan = ah->curchan; | ||
689 | struct ath_common *common = ath9k_hw_common(ah); | ||
690 | |||
691 | if (!DO_ANI(ah)) | ||
692 | return; | ||
693 | |||
694 | BUG_ON(aniState == NULL); | ||
695 | ah->stats.ast_ani_reset++; | ||
696 | |||
697 | /* only allow a subset of functions in AP mode */ | ||
698 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
699 | if (IS_CHAN_2GHZ(chan)) { | ||
700 | ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | ||
701 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
702 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
703 | ah->ani_function |= ATH9K_ANI_MRC_CCK; | ||
704 | } else | ||
705 | ah->ani_function = 0; | ||
706 | } | ||
707 | |||
708 | /* always allow mode (on/off) to be controlled */ | ||
709 | ah->ani_function |= ATH9K_ANI_MODE; | ||
710 | |||
711 | if (is_scanning || | ||
712 | (ah->opmode != NL80211_IFTYPE_STATION && | ||
713 | ah->opmode != NL80211_IFTYPE_ADHOC)) { | ||
714 | /* | ||
715 | * If we're scanning or in AP mode, the defaults (ini) | ||
716 | * should be in place. For an AP we assume the historical | ||
717 | * levels for this channel are probably outdated so start | ||
718 | * from defaults instead. | ||
719 | */ | ||
720 | if (aniState->ofdmNoiseImmunityLevel != | ||
721 | ATH9K_ANI_OFDM_DEF_LEVEL || | ||
722 | aniState->cckNoiseImmunityLevel != | ||
723 | ATH9K_ANI_CCK_DEF_LEVEL) { | ||
724 | ath_print(common, ATH_DBG_ANI, | ||
725 | "Restore defaults: opmode %u " | ||
726 | "chan %d Mhz/0x%x is_scanning=%d " | ||
727 | "ofdm:%d cck:%d\n", | ||
728 | ah->opmode, | ||
729 | chan->channel, | ||
730 | chan->channelFlags, | ||
731 | is_scanning, | ||
732 | aniState->ofdmNoiseImmunityLevel, | ||
733 | aniState->cckNoiseImmunityLevel); | ||
734 | |||
735 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); | ||
736 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); | ||
737 | } | ||
738 | } else { | ||
739 | /* | ||
740 | * restore historical levels for this channel | ||
741 | */ | ||
742 | ath_print(common, ATH_DBG_ANI, | ||
743 | "Restore history: opmode %u " | ||
744 | "chan %d Mhz/0x%x is_scanning=%d " | ||
745 | "ofdm:%d cck:%d\n", | ||
746 | ah->opmode, | ||
747 | chan->channel, | ||
748 | chan->channelFlags, | ||
749 | is_scanning, | ||
750 | aniState->ofdmNoiseImmunityLevel, | ||
751 | aniState->cckNoiseImmunityLevel); | ||
752 | |||
753 | ath9k_hw_set_ofdm_nil(ah, | ||
754 | aniState->ofdmNoiseImmunityLevel); | ||
755 | ath9k_hw_set_cck_nil(ah, | ||
756 | aniState->cckNoiseImmunityLevel); | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * enable phy counters if hw supports or if not, enable phy | ||
761 | * interrupts (so we can count each one) | ||
762 | */ | ||
763 | ath9k_ani_restart_new(ah); | ||
764 | |||
765 | ENABLE_REGWRITE_BUFFER(ah); | ||
766 | |||
767 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
768 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
769 | |||
770 | REGWRITE_BUFFER_FLUSH(ah); | ||
771 | DISABLE_REGWRITE_BUFFER(ah); | ||
772 | } | ||
773 | |||
774 | static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | ||
775 | struct ath9k_channel *chan) | ||
378 | { | 776 | { |
379 | struct ar5416AniState *aniState; | 777 | struct ar5416AniState *aniState; |
380 | struct ath_common *common = ath9k_hw_common(ah); | 778 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -390,7 +788,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
390 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 788 | listenTime = ath9k_hw_ani_get_listen_time(ah); |
391 | if (listenTime < 0) { | 789 | if (listenTime < 0) { |
392 | ah->stats.ast_ani_lneg++; | 790 | ah->stats.ast_ani_lneg++; |
393 | ath9k_ani_restart(ah); | 791 | ath9k_ani_restart_old(ah); |
394 | return; | 792 | return; |
395 | } | 793 | } |
396 | 794 | ||
@@ -444,21 +842,166 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
444 | aniState->cckPhyErrCount <= aniState->listenTime * | 842 | aniState->cckPhyErrCount <= aniState->listenTime * |
445 | aniState->cckTrigLow / 1000) | 843 | aniState->cckTrigLow / 1000) |
446 | ath9k_hw_ani_lower_immunity(ah); | 844 | ath9k_hw_ani_lower_immunity(ah); |
447 | ath9k_ani_restart(ah); | 845 | ath9k_ani_restart_old(ah); |
448 | } else if (aniState->listenTime > ah->aniperiod) { | 846 | } else if (aniState->listenTime > ah->aniperiod) { |
449 | if (aniState->ofdmPhyErrCount > aniState->listenTime * | 847 | if (aniState->ofdmPhyErrCount > aniState->listenTime * |
450 | aniState->ofdmTrigHigh / 1000) { | 848 | aniState->ofdmTrigHigh / 1000) { |
451 | ath9k_hw_ani_ofdm_err_trigger(ah); | 849 | ath9k_hw_ani_ofdm_err_trigger_old(ah); |
452 | ath9k_ani_restart(ah); | 850 | ath9k_ani_restart_old(ah); |
453 | } else if (aniState->cckPhyErrCount > | 851 | } else if (aniState->cckPhyErrCount > |
454 | aniState->listenTime * aniState->cckTrigHigh / | 852 | aniState->listenTime * aniState->cckTrigHigh / |
455 | 1000) { | 853 | 1000) { |
456 | ath9k_hw_ani_cck_err_trigger(ah); | 854 | ath9k_hw_ani_cck_err_trigger_old(ah); |
457 | ath9k_ani_restart(ah); | 855 | ath9k_ani_restart_old(ah); |
856 | } | ||
857 | } | ||
858 | } | ||
859 | |||
860 | static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | ||
861 | struct ath9k_channel *chan) | ||
862 | { | ||
863 | struct ar5416AniState *aniState; | ||
864 | struct ath_common *common = ath9k_hw_common(ah); | ||
865 | int32_t listenTime; | ||
866 | u32 phyCnt1, phyCnt2; | ||
867 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
868 | u32 ofdmPhyErrRate, cckPhyErrRate; | ||
869 | |||
870 | if (!DO_ANI(ah)) | ||
871 | return; | ||
872 | |||
873 | aniState = ah->curani; | ||
874 | if (WARN_ON(!aniState)) | ||
875 | return; | ||
876 | |||
877 | listenTime = ath9k_hw_ani_get_listen_time(ah); | ||
878 | if (listenTime <= 0) { | ||
879 | ah->stats.ast_ani_lneg++; | ||
880 | /* restart ANI period if listenTime is invalid */ | ||
881 | ath_print(common, ATH_DBG_ANI, | ||
882 | "listenTime=%d - on new ani monitor\n", | ||
883 | listenTime); | ||
884 | ath9k_ani_restart_new(ah); | ||
885 | return; | ||
886 | } | ||
887 | |||
888 | aniState->listenTime += listenTime; | ||
889 | |||
890 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
891 | |||
892 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
893 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
894 | |||
895 | if (phyCnt1 < aniState->ofdmPhyErrBase || | ||
896 | phyCnt2 < aniState->cckPhyErrBase) { | ||
897 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
898 | ath_print(common, ATH_DBG_ANI, | ||
899 | "phyCnt1 0x%x, resetting " | ||
900 | "counter value to 0x%x\n", | ||
901 | phyCnt1, | ||
902 | aniState->ofdmPhyErrBase); | ||
903 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
904 | aniState->ofdmPhyErrBase); | ||
905 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
906 | AR_PHY_ERR_OFDM_TIMING); | ||
907 | } | ||
908 | if (phyCnt2 < aniState->cckPhyErrBase) { | ||
909 | ath_print(common, ATH_DBG_ANI, | ||
910 | "phyCnt2 0x%x, resetting " | ||
911 | "counter value to 0x%x\n", | ||
912 | phyCnt2, | ||
913 | aniState->cckPhyErrBase); | ||
914 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
915 | aniState->cckPhyErrBase); | ||
916 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
917 | AR_PHY_ERR_CCK_TIMING); | ||
918 | } | ||
919 | return; | ||
920 | } | ||
921 | |||
922 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
923 | ah->stats.ast_ani_ofdmerrs += | ||
924 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
925 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
926 | |||
927 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
928 | ah->stats.ast_ani_cckerrs += | ||
929 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
930 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
931 | |||
932 | ath_print(common, ATH_DBG_ANI, | ||
933 | "Errors: OFDM=0x%08x-0x%08x=%d " | ||
934 | "CCK=0x%08x-0x%08x=%d\n", | ||
935 | phyCnt1, | ||
936 | aniState->ofdmPhyErrBase, | ||
937 | ofdmPhyErrCnt, | ||
938 | phyCnt2, | ||
939 | aniState->cckPhyErrBase, | ||
940 | cckPhyErrCnt); | ||
941 | |||
942 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / | ||
943 | aniState->listenTime; | ||
944 | cckPhyErrRate = aniState->cckPhyErrCount * 1000 / | ||
945 | aniState->listenTime; | ||
946 | |||
947 | ath_print(common, ATH_DBG_ANI, | ||
948 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " | ||
949 | "errs=%d/s ofdm_turn=%d\n", | ||
950 | listenTime, aniState->ofdmNoiseImmunityLevel, | ||
951 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, | ||
952 | cckPhyErrRate, aniState->ofdmsTurn); | ||
953 | |||
954 | if (aniState->listenTime > 5 * ah->aniperiod) { | ||
955 | if (ofdmPhyErrRate <= aniState->ofdmTrigLow && | ||
956 | cckPhyErrRate <= aniState->cckTrigLow) { | ||
957 | ath_print(common, ATH_DBG_ANI, | ||
958 | "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " | ||
959 | "CCK:%d errs=%d/s(<%d) -> " | ||
960 | "ath9k_hw_ani_lower_immunity()\n", | ||
961 | aniState->listenTime, | ||
962 | aniState->ofdmNoiseImmunityLevel, | ||
963 | ofdmPhyErrRate, | ||
964 | aniState->ofdmTrigLow, | ||
965 | aniState->cckNoiseImmunityLevel, | ||
966 | cckPhyErrRate, | ||
967 | aniState->cckTrigLow); | ||
968 | ath9k_hw_ani_lower_immunity(ah); | ||
969 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | ||
970 | } | ||
971 | ath_print(common, ATH_DBG_ANI, | ||
972 | "1 listenTime=%d ofdm=%d/s cck=%d/s - " | ||
973 | "calling ath9k_ani_restart_new()\n", | ||
974 | aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); | ||
975 | ath9k_ani_restart_new(ah); | ||
976 | } else if (aniState->listenTime > ah->aniperiod) { | ||
977 | /* check to see if need to raise immunity */ | ||
978 | if (ofdmPhyErrRate > aniState->ofdmTrigHigh && | ||
979 | (cckPhyErrRate <= aniState->cckTrigHigh || | ||
980 | aniState->ofdmsTurn)) { | ||
981 | ath_print(common, ATH_DBG_ANI, | ||
982 | "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " | ||
983 | "ath9k_hw_ani_ofdm_err_trigger_new()\n", | ||
984 | aniState->listenTime, | ||
985 | aniState->ofdmNoiseImmunityLevel, | ||
986 | ofdmPhyErrRate, | ||
987 | aniState->ofdmTrigHigh); | ||
988 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
989 | ath9k_ani_restart_new(ah); | ||
990 | aniState->ofdmsTurn = false; | ||
991 | } else if (cckPhyErrRate > aniState->cckTrigHigh) { | ||
992 | ath_print(common, ATH_DBG_ANI, | ||
993 | "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " | ||
994 | "ath9k_hw_ani_cck_err_trigger_new()\n", | ||
995 | aniState->listenTime, | ||
996 | aniState->cckNoiseImmunityLevel, | ||
997 | cckPhyErrRate, | ||
998 | aniState->cckTrigHigh); | ||
999 | ath9k_hw_ani_cck_err_trigger_new(ah); | ||
1000 | ath9k_ani_restart_new(ah); | ||
1001 | aniState->ofdmsTurn = true; | ||
458 | } | 1002 | } |
459 | } | 1003 | } |
460 | } | 1004 | } |
461 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | ||
462 | 1005 | ||
463 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 1006 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
464 | { | 1007 | { |
@@ -495,6 +1038,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
495 | REG_WRITE(ah, AR_FILT_OFDM, 0); | 1038 | REG_WRITE(ah, AR_FILT_OFDM, 0); |
496 | REG_WRITE(ah, AR_FILT_CCK, 0); | 1039 | REG_WRITE(ah, AR_FILT_CCK, 0); |
497 | } | 1040 | } |
1041 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); | ||
498 | 1042 | ||
499 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | 1043 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, |
500 | u32 *rxc_pcnt, | 1044 | u32 *rxc_pcnt, |
@@ -542,7 +1086,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | |||
542 | * any of the MIB counters overflow/trigger so don't assume we're | 1086 | * any of the MIB counters overflow/trigger so don't assume we're |
543 | * here because a PHY error counter triggered. | 1087 | * here because a PHY error counter triggered. |
544 | */ | 1088 | */ |
545 | void ath9k_hw_procmibevent(struct ath_hw *ah) | 1089 | static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) |
546 | { | 1090 | { |
547 | u32 phyCnt1, phyCnt2; | 1091 | u32 phyCnt1, phyCnt2; |
548 | 1092 | ||
@@ -555,8 +1099,15 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) | |||
555 | /* Clear the mib counters and save them in the stats */ | 1099 | /* Clear the mib counters and save them in the stats */ |
556 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 1100 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
557 | 1101 | ||
558 | if (!DO_ANI(ah)) | 1102 | if (!DO_ANI(ah)) { |
1103 | /* | ||
1104 | * We must always clear the interrupt cause by | ||
1105 | * resetting the phy error regs. | ||
1106 | */ | ||
1107 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
1108 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
559 | return; | 1109 | return; |
1110 | } | ||
560 | 1111 | ||
561 | /* NB: these are not reset-on-read */ | 1112 | /* NB: these are not reset-on-read */ |
562 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 1113 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
@@ -584,14 +1135,51 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) | |||
584 | * check will never be true. | 1135 | * check will never be true. |
585 | */ | 1136 | */ |
586 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | 1137 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) |
587 | ath9k_hw_ani_ofdm_err_trigger(ah); | 1138 | ath9k_hw_ani_ofdm_err_trigger_new(ah); |
588 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | 1139 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) |
589 | ath9k_hw_ani_cck_err_trigger(ah); | 1140 | ath9k_hw_ani_cck_err_trigger_old(ah); |
590 | /* NB: always restart to insure the h/w counters are reset */ | 1141 | /* NB: always restart to insure the h/w counters are reset */ |
591 | ath9k_ani_restart(ah); | 1142 | ath9k_ani_restart_old(ah); |
592 | } | 1143 | } |
593 | } | 1144 | } |
594 | EXPORT_SYMBOL(ath9k_hw_procmibevent); | 1145 | |
1146 | /* | ||
1147 | * Process a MIB interrupt. We may potentially be invoked because | ||
1148 | * any of the MIB counters overflow/trigger so don't assume we're | ||
1149 | * here because a PHY error counter triggered. | ||
1150 | */ | ||
1151 | static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | ||
1152 | { | ||
1153 | u32 phyCnt1, phyCnt2; | ||
1154 | |||
1155 | /* Reset these counters regardless */ | ||
1156 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
1157 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
1158 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | ||
1159 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | ||
1160 | |||
1161 | /* Clear the mib counters and save them in the stats */ | ||
1162 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
1163 | |||
1164 | if (!DO_ANI(ah)) { | ||
1165 | /* | ||
1166 | * We must always clear the interrupt cause by | ||
1167 | * resetting the phy error regs. | ||
1168 | */ | ||
1169 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
1170 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
1171 | return; | ||
1172 | } | ||
1173 | |||
1174 | /* NB: these are not reset-on-read */ | ||
1175 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
1176 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
1177 | |||
1178 | /* NB: always restart to insure the h/w counters are reset */ | ||
1179 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
1180 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) | ||
1181 | ath9k_ani_restart_new(ah); | ||
1182 | } | ||
595 | 1183 | ||
596 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 1184 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
597 | { | 1185 | { |
@@ -619,22 +1207,70 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
619 | 1207 | ||
620 | memset(ah->ani, 0, sizeof(ah->ani)); | 1208 | memset(ah->ani, 0, sizeof(ah->ani)); |
621 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 1209 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { |
622 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; | 1210 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { |
623 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; | 1211 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; |
624 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; | 1212 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; |
625 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; | 1213 | |
1214 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; | ||
1215 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; | ||
1216 | |||
1217 | ah->ani[i].spurImmunityLevel = | ||
1218 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1219 | |||
1220 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1221 | |||
1222 | ah->ani[i].ofdmPhyErrBase = 0; | ||
1223 | ah->ani[i].cckPhyErrBase = 0; | ||
1224 | |||
1225 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
1226 | ah->ani[i].mrcCCKOff = | ||
1227 | !ATH9K_ANI_ENABLE_MRC_CCK; | ||
1228 | else | ||
1229 | ah->ani[i].mrcCCKOff = true; | ||
1230 | |||
1231 | ah->ani[i].ofdmsTurn = true; | ||
1232 | } else { | ||
1233 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1234 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1235 | |||
1236 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1237 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; | ||
1238 | |||
1239 | ah->ani[i].spurImmunityLevel = | ||
1240 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; | ||
1241 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; | ||
1242 | |||
1243 | ah->ani[i].ofdmPhyErrBase = | ||
1244 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1245 | ah->ani[i].cckPhyErrBase = | ||
1246 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1247 | ah->ani[i].cckWeakSigThreshold = | ||
1248 | ATH9K_ANI_CCK_WEAK_SIG_THR; | ||
1249 | } | ||
1250 | |||
626 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | 1251 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; |
627 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | 1252 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; |
628 | ah->ani[i].ofdmWeakSigDetectOff = | 1253 | ah->ani[i].ofdmWeakSigDetectOff = |
629 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1254 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
630 | ah->ani[i].cckWeakSigThreshold = | 1255 | ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
631 | ATH9K_ANI_CCK_WEAK_SIG_THR; | 1256 | } |
632 | ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; | 1257 | |
633 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; | 1258 | /* |
634 | ah->ani[i].ofdmPhyErrBase = | 1259 | * since we expect some ongoing maintenance on the tables, let's sanity |
635 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; | 1260 | * check here default level should not modify INI setting. |
636 | ah->ani[i].cckPhyErrBase = | 1261 | */ |
637 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; | 1262 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { |
1263 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
1264 | const struct ani_cck_level_entry *entry_cck; | ||
1265 | |||
1266 | entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; | ||
1267 | entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; | ||
1268 | |||
1269 | ah->aniperiod = ATH9K_ANI_PERIOD_NEW; | ||
1270 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; | ||
1271 | } else { | ||
1272 | ah->aniperiod = ATH9K_ANI_PERIOD_OLD; | ||
1273 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; | ||
638 | } | 1274 | } |
639 | 1275 | ||
640 | ath_print(common, ATH_DBG_ANI, | 1276 | ath_print(common, ATH_DBG_ANI, |
@@ -653,7 +1289,34 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
653 | 1289 | ||
654 | ath9k_enable_mib_counters(ah); | 1290 | ath9k_enable_mib_counters(ah); |
655 | 1291 | ||
656 | ah->aniperiod = ATH9K_ANI_PERIOD; | ||
657 | if (ah->config.enable_ani) | 1292 | if (ah->config.enable_ani) |
658 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 1293 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
659 | } | 1294 | } |
1295 | |||
1296 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) | ||
1297 | { | ||
1298 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1299 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1300 | |||
1301 | priv_ops->ani_reset = ath9k_ani_reset_old; | ||
1302 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; | ||
1303 | |||
1304 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; | ||
1305 | ops->ani_monitor = ath9k_hw_ani_monitor_old; | ||
1306 | |||
1307 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); | ||
1308 | } | ||
1309 | |||
1310 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) | ||
1311 | { | ||
1312 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1313 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1314 | |||
1315 | priv_ops->ani_reset = ath9k_ani_reset_new; | ||
1316 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; | ||
1317 | |||
1318 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; | ||
1319 | ops->ani_monitor = ath9k_hw_ani_monitor_new; | ||
1320 | |||
1321 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); | ||
1322 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 3356762ea384..f4d0a4d48b37 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -23,23 +23,55 @@ | |||
23 | 23 | ||
24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) | 24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) |
25 | 25 | ||
26 | #define ATH9K_ANI_OFDM_TRIG_HIGH 500 | 26 | /* units are errors per second */ |
27 | #define ATH9K_ANI_OFDM_TRIG_LOW 200 | 27 | #define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 |
28 | #define ATH9K_ANI_CCK_TRIG_HIGH 200 | 28 | #define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000 |
29 | #define ATH9K_ANI_CCK_TRIG_LOW 100 | 29 | |
30 | /* units are errors per second */ | ||
31 | #define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 | ||
32 | #define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400 | ||
33 | |||
34 | /* units are errors per second */ | ||
35 | #define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 | ||
36 | #define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600 | ||
37 | |||
38 | /* units are errors per second */ | ||
39 | #define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 | ||
40 | #define ATH9K_ANI_CCK_TRIG_LOW_NEW 300 | ||
41 | |||
30 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 | 42 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 |
31 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true | 43 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true |
32 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false | 44 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false |
33 | #define ATH9K_ANI_SPUR_IMMUNE_LVL 7 | 45 | |
34 | #define ATH9K_ANI_FIRSTEP_LVL 0 | 46 | #define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7 |
47 | #define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3 | ||
48 | |||
49 | #define ATH9K_ANI_FIRSTEP_LVL_OLD 0 | ||
50 | #define ATH9K_ANI_FIRSTEP_LVL_NEW 2 | ||
51 | |||
35 | #define ATH9K_ANI_RSSI_THR_HIGH 40 | 52 | #define ATH9K_ANI_RSSI_THR_HIGH 40 |
36 | #define ATH9K_ANI_RSSI_THR_LOW 7 | 53 | #define ATH9K_ANI_RSSI_THR_LOW 7 |
37 | #define ATH9K_ANI_PERIOD 100 | 54 | |
55 | #define ATH9K_ANI_PERIOD_OLD 100 | ||
56 | #define ATH9K_ANI_PERIOD_NEW 1000 | ||
57 | |||
58 | /* in ms */ | ||
59 | #define ATH9K_ANI_POLLINTERVAL_OLD 100 | ||
60 | #define ATH9K_ANI_POLLINTERVAL_NEW 1000 | ||
38 | 61 | ||
39 | #define HAL_NOISE_IMMUNE_MAX 4 | 62 | #define HAL_NOISE_IMMUNE_MAX 4 |
40 | #define HAL_SPUR_IMMUNE_MAX 7 | 63 | #define HAL_SPUR_IMMUNE_MAX 7 |
41 | #define HAL_FIRST_STEP_MAX 2 | 64 | #define HAL_FIRST_STEP_MAX 2 |
42 | 65 | ||
66 | #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 | ||
67 | #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 | ||
68 | #define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 | ||
69 | #define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22 | ||
70 | |||
71 | #define ATH9K_ANI_ENABLE_MRC_CCK true | ||
72 | |||
73 | /* values here are relative to the INI */ | ||
74 | |||
43 | enum ath9k_ani_cmd { | 75 | enum ath9k_ani_cmd { |
44 | ATH9K_ANI_PRESENT = 0x1, | 76 | ATH9K_ANI_PRESENT = 0x1, |
45 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, | 77 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, |
@@ -49,7 +81,8 @@ enum ath9k_ani_cmd { | |||
49 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, | 81 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, |
50 | ATH9K_ANI_MODE = 0x40, | 82 | ATH9K_ANI_MODE = 0x40, |
51 | ATH9K_ANI_PHYERR_RESET = 0x80, | 83 | ATH9K_ANI_PHYERR_RESET = 0x80, |
52 | ATH9K_ANI_ALL = 0xff | 84 | ATH9K_ANI_MRC_CCK = 0x100, |
85 | ATH9K_ANI_ALL = 0xfff | ||
53 | }; | 86 | }; |
54 | 87 | ||
55 | struct ath9k_mib_stats { | 88 | struct ath9k_mib_stats { |
@@ -60,9 +93,31 @@ struct ath9k_mib_stats { | |||
60 | u32 beacons; | 93 | u32 beacons; |
61 | }; | 94 | }; |
62 | 95 | ||
96 | /* INI default values for ANI registers */ | ||
97 | struct ath9k_ani_default { | ||
98 | u16 m1ThreshLow; | ||
99 | u16 m2ThreshLow; | ||
100 | u16 m1Thresh; | ||
101 | u16 m2Thresh; | ||
102 | u16 m2CountThr; | ||
103 | u16 m2CountThrLow; | ||
104 | u16 m1ThreshLowExt; | ||
105 | u16 m2ThreshLowExt; | ||
106 | u16 m1ThreshExt; | ||
107 | u16 m2ThreshExt; | ||
108 | u16 firstep; | ||
109 | u16 firstepLow; | ||
110 | u16 cycpwrThr1; | ||
111 | u16 cycpwrThr1Ext; | ||
112 | }; | ||
113 | |||
63 | struct ar5416AniState { | 114 | struct ar5416AniState { |
64 | struct ath9k_channel *c; | 115 | struct ath9k_channel *c; |
65 | u8 noiseImmunityLevel; | 116 | u8 noiseImmunityLevel; |
117 | u8 ofdmNoiseImmunityLevel; | ||
118 | u8 cckNoiseImmunityLevel; | ||
119 | bool ofdmsTurn; | ||
120 | u8 mrcCCKOff; | ||
66 | u8 spurImmunityLevel; | 121 | u8 spurImmunityLevel; |
67 | u8 firstepLevel; | 122 | u8 firstepLevel; |
68 | u8 ofdmWeakSigDetectOff; | 123 | u8 ofdmWeakSigDetectOff; |
@@ -85,6 +140,7 @@ struct ar5416AniState { | |||
85 | int16_t pktRssi[2]; | 140 | int16_t pktRssi[2]; |
86 | int16_t ofdmErrRssi[2]; | 141 | int16_t ofdmErrRssi[2]; |
87 | int16_t cckErrRssi[2]; | 142 | int16_t cckErrRssi[2]; |
143 | struct ath9k_ani_default iniDef; | ||
88 | }; | 144 | }; |
89 | 145 | ||
90 | struct ar5416Stats { | 146 | struct ar5416Stats { |
@@ -108,15 +164,13 @@ struct ar5416Stats { | |||
108 | }; | 164 | }; |
109 | #define ah_mibStats stats.ast_mibstats | 165 | #define ah_mibStats stats.ast_mibstats |
110 | 166 | ||
111 | void ath9k_ani_reset(struct ath_hw *ah); | ||
112 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | ||
113 | struct ath9k_channel *chan); | ||
114 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 167 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
115 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 168 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
116 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | 169 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, |
117 | u32 *rxf_pcnt, u32 *txf_pcnt); | 170 | u32 *rxf_pcnt, u32 *txf_pcnt); |
118 | void ath9k_hw_procmibevent(struct ath_hw *ah); | ||
119 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 171 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
120 | void ath9k_hw_ani_init(struct ath_hw *ah); | 172 | void ath9k_hw_ani_init(struct ath_hw *ah); |
173 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
174 | struct ath9k_channel *chan); | ||
121 | 175 | ||
122 | #endif /* ANI_H */ | 176 | #endif /* ANI_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index b2c17c98bb38..ee34a495b0be 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -19,7 +19,30 @@ | |||
19 | #include "../regd.h" | 19 | #include "../regd.h" |
20 | #include "ar9002_phy.h" | 20 | #include "ar9002_phy.h" |
21 | 21 | ||
22 | /* All code below is for non single-chip solutions */ | 22 | /* All code below is for AR5008, AR9001, AR9002 */ |
23 | |||
24 | static const int firstep_table[] = | ||
25 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
26 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ | ||
27 | |||
28 | static const int cycpwrThr1_table[] = | ||
29 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
30 | { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ | ||
31 | |||
32 | /* | ||
33 | * register values to turn OFDM weak signal detection OFF | ||
34 | */ | ||
35 | static const int m1ThreshLow_off = 127; | ||
36 | static const int m2ThreshLow_off = 127; | ||
37 | static const int m1Thresh_off = 127; | ||
38 | static const int m2Thresh_off = 127; | ||
39 | static const int m2CountThr_off = 31; | ||
40 | static const int m2CountThrLow_off = 63; | ||
41 | static const int m1ThreshLowExt_off = 127; | ||
42 | static const int m2ThreshLowExt_off = 127; | ||
43 | static const int m1ThreshExt_off = 127; | ||
44 | static const int m2ThreshExt_off = 127; | ||
45 | |||
23 | 46 | ||
24 | /** | 47 | /** |
25 | * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters | 48 | * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters |
@@ -742,17 +765,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
742 | return -EINVAL; | 765 | return -EINVAL; |
743 | } | 766 | } |
744 | 767 | ||
745 | if (AR_SREV_9287_12_OR_LATER(ah)) { | ||
746 | /* Enable ASYNC FIFO */ | ||
747 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
748 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); | ||
749 | REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); | ||
750 | REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
751 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | ||
752 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
753 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | ||
754 | } | ||
755 | |||
756 | /* | 768 | /* |
757 | * Set correct baseband to analog shift setting to | 769 | * Set correct baseband to analog shift setting to |
758 | * access analog chips. | 770 | * access analog chips. |
@@ -1037,8 +1049,9 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, | |||
1037 | return pll; | 1049 | return pll; |
1038 | } | 1050 | } |
1039 | 1051 | ||
1040 | static bool ar5008_hw_ani_control(struct ath_hw *ah, | 1052 | static bool ar5008_hw_ani_control_old(struct ath_hw *ah, |
1041 | enum ath9k_ani_cmd cmd, int param) | 1053 | enum ath9k_ani_cmd cmd, |
1054 | int param) | ||
1042 | { | 1055 | { |
1043 | struct ar5416AniState *aniState = ah->curani; | 1056 | struct ar5416AniState *aniState = ah->curani; |
1044 | struct ath_common *common = ath9k_hw_common(ah); | 1057 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -1220,6 +1233,265 @@ static bool ar5008_hw_ani_control(struct ath_hw *ah, | |||
1220 | return true; | 1233 | return true; |
1221 | } | 1234 | } |
1222 | 1235 | ||
1236 | static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | ||
1237 | enum ath9k_ani_cmd cmd, | ||
1238 | int param) | ||
1239 | { | ||
1240 | struct ar5416AniState *aniState = ah->curani; | ||
1241 | struct ath_common *common = ath9k_hw_common(ah); | ||
1242 | struct ath9k_channel *chan = ah->curchan; | ||
1243 | s32 value, value2; | ||
1244 | |||
1245 | switch (cmd & ah->ani_function) { | ||
1246 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | ||
1247 | /* | ||
1248 | * on == 1 means ofdm weak signal detection is ON | ||
1249 | * on == 1 is the default, for less noise immunity | ||
1250 | * | ||
1251 | * on == 0 means ofdm weak signal detection is OFF | ||
1252 | * on == 0 means more noise imm | ||
1253 | */ | ||
1254 | u32 on = param ? 1 : 0; | ||
1255 | /* | ||
1256 | * make register setting for default | ||
1257 | * (weak sig detect ON) come from INI file | ||
1258 | */ | ||
1259 | int m1ThreshLow = on ? | ||
1260 | aniState->iniDef.m1ThreshLow : m1ThreshLow_off; | ||
1261 | int m2ThreshLow = on ? | ||
1262 | aniState->iniDef.m2ThreshLow : m2ThreshLow_off; | ||
1263 | int m1Thresh = on ? | ||
1264 | aniState->iniDef.m1Thresh : m1Thresh_off; | ||
1265 | int m2Thresh = on ? | ||
1266 | aniState->iniDef.m2Thresh : m2Thresh_off; | ||
1267 | int m2CountThr = on ? | ||
1268 | aniState->iniDef.m2CountThr : m2CountThr_off; | ||
1269 | int m2CountThrLow = on ? | ||
1270 | aniState->iniDef.m2CountThrLow : m2CountThrLow_off; | ||
1271 | int m1ThreshLowExt = on ? | ||
1272 | aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; | ||
1273 | int m2ThreshLowExt = on ? | ||
1274 | aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; | ||
1275 | int m1ThreshExt = on ? | ||
1276 | aniState->iniDef.m1ThreshExt : m1ThreshExt_off; | ||
1277 | int m2ThreshExt = on ? | ||
1278 | aniState->iniDef.m2ThreshExt : m2ThreshExt_off; | ||
1279 | |||
1280 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1281 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | ||
1282 | m1ThreshLow); | ||
1283 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1284 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | ||
1285 | m2ThreshLow); | ||
1286 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1287 | AR_PHY_SFCORR_M1_THRESH, m1Thresh); | ||
1288 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1289 | AR_PHY_SFCORR_M2_THRESH, m2Thresh); | ||
1290 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1291 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); | ||
1292 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1293 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | ||
1294 | m2CountThrLow); | ||
1295 | |||
1296 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1297 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); | ||
1298 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1299 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); | ||
1300 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1301 | AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); | ||
1302 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1303 | AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); | ||
1304 | |||
1305 | if (on) | ||
1306 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | ||
1307 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
1308 | else | ||
1309 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | ||
1310 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
1311 | |||
1312 | if (!on != aniState->ofdmWeakSigDetectOff) { | ||
1313 | ath_print(common, ATH_DBG_ANI, | ||
1314 | "** ch %d: ofdm weak signal: %s=>%s\n", | ||
1315 | chan->channel, | ||
1316 | !aniState->ofdmWeakSigDetectOff ? | ||
1317 | "on" : "off", | ||
1318 | on ? "on" : "off"); | ||
1319 | if (on) | ||
1320 | ah->stats.ast_ani_ofdmon++; | ||
1321 | else | ||
1322 | ah->stats.ast_ani_ofdmoff++; | ||
1323 | aniState->ofdmWeakSigDetectOff = !on; | ||
1324 | } | ||
1325 | break; | ||
1326 | } | ||
1327 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | ||
1328 | u32 level = param; | ||
1329 | |||
1330 | if (level >= ARRAY_SIZE(firstep_table)) { | ||
1331 | ath_print(common, ATH_DBG_ANI, | ||
1332 | "ATH9K_ANI_FIRSTEP_LEVEL: level " | ||
1333 | "out of range (%u > %u)\n", | ||
1334 | level, | ||
1335 | (unsigned) ARRAY_SIZE(firstep_table)); | ||
1336 | return false; | ||
1337 | } | ||
1338 | |||
1339 | /* | ||
1340 | * make register setting relative to default | ||
1341 | * from INI file & cap value | ||
1342 | */ | ||
1343 | value = firstep_table[level] - | ||
1344 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
1345 | aniState->iniDef.firstep; | ||
1346 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
1347 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
1348 | if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
1349 | value = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
1350 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
1351 | AR_PHY_FIND_SIG_FIRSTEP, | ||
1352 | value); | ||
1353 | /* | ||
1354 | * we need to set first step low register too | ||
1355 | * make register setting relative to default | ||
1356 | * from INI file & cap value | ||
1357 | */ | ||
1358 | value2 = firstep_table[level] - | ||
1359 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
1360 | aniState->iniDef.firstepLow; | ||
1361 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
1362 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
1363 | if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
1364 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
1365 | |||
1366 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, | ||
1367 | AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); | ||
1368 | |||
1369 | if (level != aniState->firstepLevel) { | ||
1370 | ath_print(common, ATH_DBG_ANI, | ||
1371 | "** ch %d: level %d=>%d[def:%d] " | ||
1372 | "firstep[level]=%d ini=%d\n", | ||
1373 | chan->channel, | ||
1374 | aniState->firstepLevel, | ||
1375 | level, | ||
1376 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
1377 | value, | ||
1378 | aniState->iniDef.firstep); | ||
1379 | ath_print(common, ATH_DBG_ANI, | ||
1380 | "** ch %d: level %d=>%d[def:%d] " | ||
1381 | "firstep_low[level]=%d ini=%d\n", | ||
1382 | chan->channel, | ||
1383 | aniState->firstepLevel, | ||
1384 | level, | ||
1385 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
1386 | value2, | ||
1387 | aniState->iniDef.firstepLow); | ||
1388 | if (level > aniState->firstepLevel) | ||
1389 | ah->stats.ast_ani_stepup++; | ||
1390 | else if (level < aniState->firstepLevel) | ||
1391 | ah->stats.ast_ani_stepdown++; | ||
1392 | aniState->firstepLevel = level; | ||
1393 | } | ||
1394 | break; | ||
1395 | } | ||
1396 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | ||
1397 | u32 level = param; | ||
1398 | |||
1399 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { | ||
1400 | ath_print(common, ATH_DBG_ANI, | ||
1401 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " | ||
1402 | "out of range (%u > %u)\n", | ||
1403 | level, | ||
1404 | (unsigned) ARRAY_SIZE(cycpwrThr1_table)); | ||
1405 | return false; | ||
1406 | } | ||
1407 | /* | ||
1408 | * make register setting relative to default | ||
1409 | * from INI file & cap value | ||
1410 | */ | ||
1411 | value = cycpwrThr1_table[level] - | ||
1412 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
1413 | aniState->iniDef.cycpwrThr1; | ||
1414 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
1415 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
1416 | if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
1417 | value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
1418 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | ||
1419 | AR_PHY_TIMING5_CYCPWR_THR1, | ||
1420 | value); | ||
1421 | |||
1422 | /* | ||
1423 | * set AR_PHY_EXT_CCA for extension channel | ||
1424 | * make register setting relative to default | ||
1425 | * from INI file & cap value | ||
1426 | */ | ||
1427 | value2 = cycpwrThr1_table[level] - | ||
1428 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
1429 | aniState->iniDef.cycpwrThr1Ext; | ||
1430 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
1431 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
1432 | if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
1433 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
1434 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
1435 | AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); | ||
1436 | |||
1437 | if (level != aniState->spurImmunityLevel) { | ||
1438 | ath_print(common, ATH_DBG_ANI, | ||
1439 | "** ch %d: level %d=>%d[def:%d] " | ||
1440 | "cycpwrThr1[level]=%d ini=%d\n", | ||
1441 | chan->channel, | ||
1442 | aniState->spurImmunityLevel, | ||
1443 | level, | ||
1444 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
1445 | value, | ||
1446 | aniState->iniDef.cycpwrThr1); | ||
1447 | ath_print(common, ATH_DBG_ANI, | ||
1448 | "** ch %d: level %d=>%d[def:%d] " | ||
1449 | "cycpwrThr1Ext[level]=%d ini=%d\n", | ||
1450 | chan->channel, | ||
1451 | aniState->spurImmunityLevel, | ||
1452 | level, | ||
1453 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
1454 | value2, | ||
1455 | aniState->iniDef.cycpwrThr1Ext); | ||
1456 | if (level > aniState->spurImmunityLevel) | ||
1457 | ah->stats.ast_ani_spurup++; | ||
1458 | else if (level < aniState->spurImmunityLevel) | ||
1459 | ah->stats.ast_ani_spurdown++; | ||
1460 | aniState->spurImmunityLevel = level; | ||
1461 | } | ||
1462 | break; | ||
1463 | } | ||
1464 | case ATH9K_ANI_MRC_CCK: | ||
1465 | /* | ||
1466 | * You should not see this as AR5008, AR9001, AR9002 | ||
1467 | * does not have hardware support for MRC CCK. | ||
1468 | */ | ||
1469 | WARN_ON(1); | ||
1470 | break; | ||
1471 | case ATH9K_ANI_PRESENT: | ||
1472 | break; | ||
1473 | default: | ||
1474 | ath_print(common, ATH_DBG_ANI, | ||
1475 | "invalid cmd %u\n", cmd); | ||
1476 | return false; | ||
1477 | } | ||
1478 | |||
1479 | ath_print(common, ATH_DBG_ANI, | ||
1480 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " | ||
1481 | "MRCcck=%s listenTime=%d CC=%d listen=%d " | ||
1482 | "ofdmErrs=%d cckErrs=%d\n", | ||
1483 | aniState->spurImmunityLevel, | ||
1484 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | ||
1485 | aniState->firstepLevel, | ||
1486 | !aniState->mrcCCKOff ? "on" : "off", | ||
1487 | aniState->listenTime, | ||
1488 | aniState->cycleCount, | ||
1489 | aniState->listenTime, | ||
1490 | aniState->ofdmPhyErrCount, | ||
1491 | aniState->cckPhyErrCount); | ||
1492 | return true; | ||
1493 | } | ||
1494 | |||
1223 | static void ar5008_hw_do_getnf(struct ath_hw *ah, | 1495 | static void ar5008_hw_do_getnf(struct ath_hw *ah, |
1224 | int16_t nfarray[NUM_NF_READINGS]) | 1496 | int16_t nfarray[NUM_NF_READINGS]) |
1225 | { | 1497 | { |
@@ -1340,6 +1612,71 @@ static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1340 | DISABLE_REGWRITE_BUFFER(ah); | 1612 | DISABLE_REGWRITE_BUFFER(ah); |
1341 | } | 1613 | } |
1342 | 1614 | ||
1615 | /* | ||
1616 | * Initialize the ANI register values with default (ini) values. | ||
1617 | * This routine is called during a (full) hardware reset after | ||
1618 | * all the registers are initialised from the INI. | ||
1619 | */ | ||
1620 | static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
1621 | { | ||
1622 | struct ar5416AniState *aniState; | ||
1623 | struct ath_common *common = ath9k_hw_common(ah); | ||
1624 | struct ath9k_channel *chan = ah->curchan; | ||
1625 | struct ath9k_ani_default *iniDef; | ||
1626 | int index; | ||
1627 | u32 val; | ||
1628 | |||
1629 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
1630 | aniState = &ah->ani[index]; | ||
1631 | ah->curani = aniState; | ||
1632 | iniDef = &aniState->iniDef; | ||
1633 | |||
1634 | ath_print(common, ATH_DBG_ANI, | ||
1635 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | ||
1636 | ah->hw_version.macVersion, | ||
1637 | ah->hw_version.macRev, | ||
1638 | ah->opmode, | ||
1639 | chan->channel, | ||
1640 | chan->channelFlags); | ||
1641 | |||
1642 | val = REG_READ(ah, AR_PHY_SFCORR); | ||
1643 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | ||
1644 | iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH); | ||
1645 | iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR); | ||
1646 | |||
1647 | val = REG_READ(ah, AR_PHY_SFCORR_LOW); | ||
1648 | iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); | ||
1649 | iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); | ||
1650 | iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); | ||
1651 | |||
1652 | val = REG_READ(ah, AR_PHY_SFCORR_EXT); | ||
1653 | iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH); | ||
1654 | iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH); | ||
1655 | iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW); | ||
1656 | iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW); | ||
1657 | iniDef->firstep = REG_READ_FIELD(ah, | ||
1658 | AR_PHY_FIND_SIG, | ||
1659 | AR_PHY_FIND_SIG_FIRSTEP); | ||
1660 | iniDef->firstepLow = REG_READ_FIELD(ah, | ||
1661 | AR_PHY_FIND_SIG_LOW, | ||
1662 | AR_PHY_FIND_SIG_FIRSTEP_LOW); | ||
1663 | iniDef->cycpwrThr1 = REG_READ_FIELD(ah, | ||
1664 | AR_PHY_TIMING5, | ||
1665 | AR_PHY_TIMING5_CYCPWR_THR1); | ||
1666 | iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah, | ||
1667 | AR_PHY_EXT_CCA, | ||
1668 | AR_PHY_EXT_TIMING5_CYCPWR_THR1); | ||
1669 | |||
1670 | /* these levels just got reset to defaults by the INI */ | ||
1671 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1672 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1673 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | ||
1674 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ | ||
1675 | |||
1676 | aniState->cycleCount = 0; | ||
1677 | } | ||
1678 | |||
1679 | |||
1343 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | 1680 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) |
1344 | { | 1681 | { |
1345 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1682 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
@@ -1361,10 +1698,15 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1361 | priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; | 1698 | priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; |
1362 | priv_ops->restore_chainmask = ar5008_restore_chainmask; | 1699 | priv_ops->restore_chainmask = ar5008_restore_chainmask; |
1363 | priv_ops->set_diversity = ar5008_set_diversity; | 1700 | priv_ops->set_diversity = ar5008_set_diversity; |
1364 | priv_ops->ani_control = ar5008_hw_ani_control; | ||
1365 | priv_ops->do_getnf = ar5008_hw_do_getnf; | 1701 | priv_ops->do_getnf = ar5008_hw_do_getnf; |
1366 | priv_ops->loadnf = ar5008_hw_loadnf; | 1702 | priv_ops->loadnf = ar5008_hw_loadnf; |
1367 | 1703 | ||
1704 | if (modparam_force_new_ani) { | ||
1705 | priv_ops->ani_control = ar5008_hw_ani_control_new; | ||
1706 | priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs; | ||
1707 | } else | ||
1708 | priv_ops->ani_control = ar5008_hw_ani_control_old; | ||
1709 | |||
1368 | if (AR_SREV_9100(ah)) | 1710 | if (AR_SREV_9100(ah)) |
1369 | priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; | 1711 | priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; |
1370 | else if (AR_SREV_9160_10_OR_LATER(ah)) | 1712 | else if (AR_SREV_9160_10_OR_LATER(ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index a8a8cdc04afa..0317ac9fc1b7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -18,6 +18,11 @@ | |||
18 | #include "ar5008_initvals.h" | 18 | #include "ar5008_initvals.h" |
19 | #include "ar9001_initvals.h" | 19 | #include "ar9001_initvals.h" |
20 | #include "ar9002_initvals.h" | 20 | #include "ar9002_initvals.h" |
21 | #include "ar9002_phy.h" | ||
22 | |||
23 | int modparam_force_new_ani; | ||
24 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); | ||
25 | MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002"); | ||
21 | 26 | ||
22 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ | 27 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ |
23 | 28 | ||
@@ -436,55 +441,84 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
436 | } | 441 | } |
437 | 442 | ||
438 | udelay(1000); | 443 | udelay(1000); |
444 | } | ||
439 | 445 | ||
440 | /* set bit 19 to allow forcing of pcie core into L1 state */ | 446 | if (power_off) { |
441 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | 447 | /* clear bit 19 to disable L1 */ |
448 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | ||
449 | |||
450 | val = REG_READ(ah, AR_WA); | ||
451 | |||
452 | /* | ||
453 | * Set PCIe workaround bits | ||
454 | * In AR9280 and AR9285, bit 14 in WA register (disable L1) | ||
455 | * should only be set when device enters D3 and be | ||
456 | * cleared when device comes back to D0. | ||
457 | */ | ||
458 | if (ah->config.pcie_waen) { | ||
459 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) | ||
460 | val |= AR_WA_D3_L1_DISABLE; | ||
461 | } else { | ||
462 | if (((AR_SREV_9285(ah) || | ||
463 | AR_SREV_9271(ah) || | ||
464 | AR_SREV_9287(ah)) && | ||
465 | (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || | ||
466 | (AR_SREV_9280(ah) && | ||
467 | (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { | ||
468 | val |= AR_WA_D3_L1_DISABLE; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | ||
473 | /* | ||
474 | * Disable bit 6 and 7 before entering D3 to | ||
475 | * prevent system hang. | ||
476 | */ | ||
477 | val &= ~(AR_WA_BIT6 | AR_WA_BIT7); | ||
478 | } | ||
442 | 479 | ||
443 | /* Several PCIe massages to ensure proper behaviour */ | 480 | if (AR_SREV_9285E_20(ah)) |
481 | val |= AR_WA_BIT23; | ||
482 | |||
483 | REG_WRITE(ah, AR_WA, val); | ||
484 | } else { | ||
444 | if (ah->config.pcie_waen) { | 485 | if (ah->config.pcie_waen) { |
445 | val = ah->config.pcie_waen; | 486 | val = ah->config.pcie_waen; |
446 | if (!power_off) | 487 | if (!power_off) |
447 | val &= (~AR_WA_D3_L1_DISABLE); | 488 | val &= (~AR_WA_D3_L1_DISABLE); |
448 | } else { | 489 | } else { |
449 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || | 490 | if (AR_SREV_9285(ah) || |
491 | AR_SREV_9271(ah) || | ||
450 | AR_SREV_9287(ah)) { | 492 | AR_SREV_9287(ah)) { |
451 | val = AR9285_WA_DEFAULT; | 493 | val = AR9285_WA_DEFAULT; |
452 | if (!power_off) | 494 | if (!power_off) |
453 | val &= (~AR_WA_D3_L1_DISABLE); | 495 | val &= (~AR_WA_D3_L1_DISABLE); |
454 | } else if (AR_SREV_9280(ah)) { | 496 | } |
497 | else if (AR_SREV_9280(ah)) { | ||
455 | /* | 498 | /* |
456 | * On AR9280 chips bit 22 of 0x4004 needs to be | 499 | * For AR9280 chips, bit 22 of 0x4004 |
457 | * set otherwise card may disappear. | 500 | * needs to be set. |
458 | */ | 501 | */ |
459 | val = AR9280_WA_DEFAULT; | 502 | val = AR9280_WA_DEFAULT; |
460 | if (!power_off) | 503 | if (!power_off) |
461 | val &= (~AR_WA_D3_L1_DISABLE); | 504 | val &= (~AR_WA_D3_L1_DISABLE); |
462 | } else | 505 | } else { |
463 | val = AR_WA_DEFAULT; | 506 | val = AR_WA_DEFAULT; |
507 | } | ||
508 | } | ||
509 | |||
510 | /* WAR for ASPM system hang */ | ||
511 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | ||
512 | val |= (AR_WA_BIT6 | AR_WA_BIT7); | ||
464 | } | 513 | } |
465 | 514 | ||
515 | if (AR_SREV_9285E_20(ah)) | ||
516 | val |= AR_WA_BIT23; | ||
517 | |||
466 | REG_WRITE(ah, AR_WA, val); | 518 | REG_WRITE(ah, AR_WA, val); |
467 | } | ||
468 | 519 | ||
469 | if (power_off) { | 520 | /* set bit 19 to allow forcing of pcie core into L1 state */ |
470 | /* | 521 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); |
471 | * Set PCIe workaround bits | ||
472 | * bit 14 in WA register (disable L1) should only | ||
473 | * be set when device enters D3 and be cleared | ||
474 | * when device comes back to D0. | ||
475 | */ | ||
476 | if (ah->config.pcie_waen) { | ||
477 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) | ||
478 | REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); | ||
479 | } else { | ||
480 | if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || | ||
481 | AR_SREV_9287(ah)) && | ||
482 | (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || | ||
483 | (AR_SREV_9280(ah) && | ||
484 | (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { | ||
485 | REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); | ||
486 | } | ||
487 | } | ||
488 | } | 522 | } |
489 | } | 523 | } |
490 | 524 | ||
@@ -536,18 +570,29 @@ int ar9002_hw_rf_claim(struct ath_hw *ah) | |||
536 | return 0; | 570 | return 0; |
537 | } | 571 | } |
538 | 572 | ||
573 | void ar9002_hw_enable_async_fifo(struct ath_hw *ah) | ||
574 | { | ||
575 | if (AR_SREV_9287_13_OR_LATER(ah)) { | ||
576 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
577 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); | ||
578 | REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); | ||
579 | REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
580 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | ||
581 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
582 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | ||
583 | } | ||
584 | } | ||
585 | |||
539 | /* | 586 | /* |
540 | * Enable ASYNC FIFO | ||
541 | * | ||
542 | * If Async FIFO is enabled, the following counters change as MAC now runs | 587 | * If Async FIFO is enabled, the following counters change as MAC now runs |
543 | * at 117 Mhz instead of 88/44MHz when async FIFO is disabled. | 588 | * at 117 Mhz instead of 88/44MHz when async FIFO is disabled. |
544 | * | 589 | * |
545 | * The values below tested for ht40 2 chain. | 590 | * The values below tested for ht40 2 chain. |
546 | * Overwrite the delay/timeouts initialized in process ini. | 591 | * Overwrite the delay/timeouts initialized in process ini. |
547 | */ | 592 | */ |
548 | void ar9002_hw_enable_async_fifo(struct ath_hw *ah) | 593 | void ar9002_hw_update_async_fifo(struct ath_hw *ah) |
549 | { | 594 | { |
550 | if (AR_SREV_9287_12_OR_LATER(ah)) { | 595 | if (AR_SREV_9287_13_OR_LATER(ah)) { |
551 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, | 596 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, |
552 | AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); | 597 | AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); |
553 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, | 598 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, |
@@ -571,9 +616,9 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah) | |||
571 | */ | 616 | */ |
572 | void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah) | 617 | void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah) |
573 | { | 618 | { |
574 | if (AR_SREV_9287_12_OR_LATER(ah)) { | 619 | if (AR_SREV_9287_13_OR_LATER(ah)) { |
575 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | 620 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, |
576 | AR_PCU_MISC_MODE2_ENABLE_AGGWEP); | 621 | AR_PCU_MISC_MODE2_ENABLE_AGGWEP); |
577 | } | 622 | } |
578 | } | 623 | } |
579 | 624 | ||
@@ -595,4 +640,9 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) | |||
595 | 640 | ||
596 | ar9002_hw_attach_calib_ops(ah); | 641 | ar9002_hw_attach_calib_ops(ah); |
597 | ar9002_hw_attach_mac_ops(ah); | 642 | ar9002_hw_attach_mac_ops(ah); |
643 | |||
644 | if (modparam_force_new_ani) | ||
645 | ath9k_hw_attach_ani_ops_new(ah); | ||
646 | else | ||
647 | ath9k_hw_attach_ani_ops_old(ah); | ||
598 | } | 648 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index dae7f3304eb8..8ab24ee8564b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h | |||
@@ -4492,7 +4492,7 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { | |||
4492 | }; | 4492 | }; |
4493 | 4493 | ||
4494 | 4494 | ||
4495 | /* AR9271 initialization values automaticaly created: 06/04/09 */ | 4495 | /* AR9271 initialization values automaticaly created: 03/31/10 */ |
4496 | static const u32 ar9271Modes_9271[][6] = { | 4496 | static const u32 ar9271Modes_9271[][6] = { |
4497 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 4497 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
4498 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 4498 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -5011,7 +5011,7 @@ static const u32 ar9271Common_9271[][2] = { | |||
5011 | { 0x0000783c, 0x72ee0a72 }, | 5011 | { 0x0000783c, 0x72ee0a72 }, |
5012 | { 0x00007840, 0xbbfffffc }, | 5012 | { 0x00007840, 0xbbfffffc }, |
5013 | { 0x00007844, 0x000c0db6 }, | 5013 | { 0x00007844, 0x000c0db6 }, |
5014 | { 0x00007848, 0x6db61b6f }, | 5014 | { 0x00007848, 0x6db6246f }, |
5015 | { 0x0000784c, 0x6d9b66db }, | 5015 | { 0x0000784c, 0x6d9b66db }, |
5016 | { 0x00007850, 0x6d8c6dba }, | 5016 | { 0x00007850, 0x6d8c6dba }, |
5017 | { 0x00007854, 0x00040000 }, | 5017 | { 0x00007854, 0x00040000 }, |
@@ -5218,7 +5218,7 @@ static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = { | |||
5218 | { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, | 5218 | { 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff }, |
5219 | { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, | 5219 | { 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 }, |
5220 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | 5220 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, |
5221 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 }, | 5221 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652 }, |
5222 | { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | 5222 | { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, |
5223 | { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, | 5223 | { 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 }, |
5224 | { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, | 5224 | { 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 }, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 81bf6e5840e1..ce8bb001c6d1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -114,6 +114,10 @@ | |||
114 | #define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 | 114 | #define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 |
115 | #define AR_PHY_FIND_SIG_FIRPWR_S 18 | 115 | #define AR_PHY_FIND_SIG_FIRPWR_S 18 |
116 | 116 | ||
117 | #define AR_PHY_FIND_SIG_LOW 0x9840 | ||
118 | #define AR_PHY_FIND_SIG_FIRSTEP_LOW 0x00000FC0L | ||
119 | #define AR_PHY_FIND_SIG_FIRSTEP_LOW_S 6 | ||
120 | |||
117 | #define AR_PHY_AGC_CTL1 0x985C | 121 | #define AR_PHY_AGC_CTL1 0x985C |
118 | #define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 | 122 | #define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 |
119 | #define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 | 123 | #define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 |
@@ -325,6 +329,9 @@ | |||
325 | #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 | 329 | #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 |
326 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 | 330 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 |
327 | #define AR_PHY_EXT_CCA_THRESH62_S 16 | 331 | #define AR_PHY_EXT_CCA_THRESH62_S 16 |
332 | #define AR_PHY_EXT_TIMING5_CYCPWR_THR1 0x0000FE00L | ||
333 | #define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9 | ||
334 | |||
328 | #define AR_PHY_EXT_MINCCA_PWR 0xFF800000 | 335 | #define AR_PHY_EXT_MINCCA_PWR 0xFF800000 |
329 | #define AR_PHY_EXT_MINCCA_PWR_S 23 | 336 | #define AR_PHY_EXT_MINCCA_PWR_S 23 |
330 | #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 | 337 | #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h index db019dd220b7..d3375fc4ce8b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h | |||
@@ -14,8 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef INITVALS_9003_H | 17 | #ifndef INITVALS_9003_2P0_H |
18 | #define INITVALS_9003_H | 18 | #define INITVALS_9003_2P0_H |
19 | 19 | ||
20 | /* AR9003 2.0 */ | 20 | /* AR9003 2.0 */ |
21 | 21 | ||
@@ -835,71 +835,71 @@ static const u32 ar9300_2p0_baseband_core[][2] = { | |||
835 | 835 | ||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { | 836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { |
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
838 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 838 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
840 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 840 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
841 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 841 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
842 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | 842 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, |
843 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | 843 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, |
844 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | 844 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, |
845 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | 845 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, |
846 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | 846 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, |
847 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | 847 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, |
848 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | 848 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, |
849 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | 849 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, |
850 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | 850 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, |
851 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | 851 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, |
852 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | 852 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, |
853 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | 853 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, |
854 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 854 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, |
855 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 855 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
856 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 856 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
857 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 857 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, |
859 | {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, | 859 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
860 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 860 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
861 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 861 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
862 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 862 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, |
863 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 863 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, |
864 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 864 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
865 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 865 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
866 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 866 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
867 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 867 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
868 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 868 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
869 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 869 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
870 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 870 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | 871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, |
872 | {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, | 872 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, |
873 | {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, | 873 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, |
874 | {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, | 874 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, |
875 | {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, | 875 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, |
876 | {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, | 876 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, |
877 | {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, | 877 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, |
878 | {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, | 878 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, |
879 | {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, | 879 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, |
880 | {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, | 880 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, |
881 | {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, | 881 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, |
882 | {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, | 882 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, |
883 | {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, | 883 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, |
884 | {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, | 884 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, |
885 | {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, | 885 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, |
886 | {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, | 886 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, |
887 | {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, | 887 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, |
888 | {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, | 888 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, |
889 | {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, | 889 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, |
890 | {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, | 890 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, |
891 | {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, | 891 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, |
892 | {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, | 892 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, |
893 | {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, | 893 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, |
894 | {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, | 894 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, |
895 | {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, | 895 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, |
896 | {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 896 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
897 | {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 897 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
898 | {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 898 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
899 | {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 899 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
900 | {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 900 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
901 | {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 901 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
902 | {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 902 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, |
904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | 904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, |
905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | 905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, |
@@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { | |||
913 | 913 | ||
914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { | 914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { |
915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
916 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 916 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
918 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 918 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
919 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 919 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
920 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | 920 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, |
921 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | 921 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, |
922 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | 922 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, |
923 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | 923 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, |
924 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | 924 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, |
925 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | 925 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, |
926 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | 926 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, |
927 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | 927 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, |
928 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | 928 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, |
929 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | 929 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, |
930 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | 930 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, |
931 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | 931 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, |
932 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 932 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, |
933 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 933 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
934 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 934 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
935 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 935 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, |
937 | {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, | 937 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
938 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 938 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
939 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 939 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
940 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 940 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, |
941 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 941 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, |
942 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 942 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
943 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 943 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
944 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 944 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
945 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 945 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
946 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 946 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
947 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 947 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
948 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 948 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | 949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, |
950 | {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, | 950 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, |
951 | {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, | 951 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, |
952 | {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, | 952 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, |
953 | {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, | 953 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, |
954 | {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, | 954 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, |
955 | {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, | 955 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, |
956 | {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, | 956 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, |
957 | {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, | 957 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, |
958 | {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, | 958 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, |
959 | {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, | 959 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, |
960 | {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, | 960 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, |
961 | {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, | 961 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, |
962 | {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, | 962 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, |
963 | {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, | 963 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, |
964 | {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, | 964 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, |
965 | {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, | 965 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, |
966 | {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, | 966 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, |
967 | {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, | 967 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, |
968 | {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, | 968 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, |
969 | {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, | 969 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, |
970 | {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, | 970 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, |
971 | {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, | 971 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, |
972 | {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, | 972 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, |
973 | {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, | 973 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, |
974 | {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 974 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
975 | {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 975 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
976 | {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 976 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
977 | {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 977 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
978 | {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 978 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
979 | {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 979 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
980 | {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 980 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, |
982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, |
983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
@@ -1781,4 +1781,4 @@ static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { | |||
1781 | {0x00004044, 0x00000000}, | 1781 | {0x00004044, 0x00000000}, |
1782 | }; | 1782 | }; |
1783 | 1783 | ||
1784 | #endif /* INITVALS_9003_H */ | 1784 | #endif /* INITVALS_9003_2P0_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h new file mode 100644 index 000000000000..ec98ab50748a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -0,0 +1,1785 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef INITVALS_9003_2P2_H | ||
18 | #define INITVALS_9003_2P2_H | ||
19 | |||
20 | /* AR9003 2.2 */ | ||
21 | |||
22 | static const u32 ar9300_2p2_radio_postamble[][5] = { | ||
23 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
24 | {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, | ||
25 | {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, | ||
26 | {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, | ||
27 | {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | ||
28 | {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
29 | {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | ||
30 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
31 | {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | ||
32 | {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
33 | }; | ||
34 | |||
35 | static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { | ||
36 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
37 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
38 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
39 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
40 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
41 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
42 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, | ||
43 | {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, | ||
44 | {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, | ||
45 | {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, | ||
46 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, | ||
47 | {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, | ||
48 | {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, | ||
49 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, | ||
50 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, | ||
51 | {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, | ||
52 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, | ||
53 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, | ||
54 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, | ||
55 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, | ||
56 | {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, | ||
57 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, | ||
58 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, | ||
59 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, | ||
60 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, | ||
61 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, | ||
62 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, | ||
63 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
64 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
65 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
66 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
67 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
68 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
69 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
70 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
71 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | ||
72 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | ||
73 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | ||
74 | {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, | ||
75 | {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, | ||
76 | {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, | ||
77 | {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, | ||
78 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, | ||
79 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, | ||
80 | {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, | ||
81 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, | ||
82 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, | ||
83 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, | ||
84 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, | ||
85 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, | ||
86 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, | ||
87 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, | ||
88 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, | ||
89 | {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, | ||
90 | {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, | ||
91 | {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, | ||
92 | {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, | ||
93 | {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, | ||
94 | {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, | ||
95 | {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
96 | {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
97 | {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
98 | {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
99 | {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
100 | {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
101 | {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
102 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
103 | {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | ||
104 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
105 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
106 | {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | ||
107 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
108 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
109 | {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | ||
110 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
111 | }; | ||
112 | |||
113 | static const u32 ar9300Modes_fast_clock_2p2[][3] = { | ||
114 | /* Addr 5G_HT20 5G_HT40 */ | ||
115 | {0x00001030, 0x00000268, 0x000004d0}, | ||
116 | {0x00001070, 0x0000018c, 0x00000318}, | ||
117 | {0x000010b0, 0x00000fd0, 0x00001fa0}, | ||
118 | {0x00008014, 0x044c044c, 0x08980898}, | ||
119 | {0x0000801c, 0x148ec02b, 0x148ec057}, | ||
120 | {0x00008318, 0x000044c0, 0x00008980}, | ||
121 | {0x00009e00, 0x03721821, 0x03721821}, | ||
122 | {0x0000a230, 0x0000000b, 0x00000016}, | ||
123 | {0x0000a254, 0x00000898, 0x00001130}, | ||
124 | }; | ||
125 | |||
126 | static const u32 ar9300_2p2_radio_core[][2] = { | ||
127 | /* Addr allmodes */ | ||
128 | {0x00016000, 0x36db6db6}, | ||
129 | {0x00016004, 0x6db6db40}, | ||
130 | {0x00016008, 0x73f00000}, | ||
131 | {0x0001600c, 0x00000000}, | ||
132 | {0x00016040, 0x7f80fff8}, | ||
133 | {0x0001604c, 0x76d005b5}, | ||
134 | {0x00016050, 0x556cf031}, | ||
135 | {0x00016054, 0x13449440}, | ||
136 | {0x00016058, 0x0c51c92c}, | ||
137 | {0x0001605c, 0x3db7fffc}, | ||
138 | {0x00016060, 0xfffffffc}, | ||
139 | {0x00016064, 0x000f0278}, | ||
140 | {0x0001606c, 0x6db60000}, | ||
141 | {0x00016080, 0x00000000}, | ||
142 | {0x00016084, 0x0e48048c}, | ||
143 | {0x00016088, 0x54214514}, | ||
144 | {0x0001608c, 0x119f481e}, | ||
145 | {0x00016090, 0x24926490}, | ||
146 | {0x00016098, 0xd2888888}, | ||
147 | {0x000160a0, 0x0a108ffe}, | ||
148 | {0x000160a4, 0x812fc370}, | ||
149 | {0x000160a8, 0x423c8000}, | ||
150 | {0x000160b4, 0x92480080}, | ||
151 | {0x000160c0, 0x00adb6d0}, | ||
152 | {0x000160c4, 0x6db6db60}, | ||
153 | {0x000160c8, 0x6db6db6c}, | ||
154 | {0x000160cc, 0x01e6c000}, | ||
155 | {0x00016100, 0x3fffbe01}, | ||
156 | {0x00016104, 0xfff80000}, | ||
157 | {0x00016108, 0x00080010}, | ||
158 | {0x00016144, 0x02084080}, | ||
159 | {0x00016148, 0x00000000}, | ||
160 | {0x00016280, 0x058a0001}, | ||
161 | {0x00016284, 0x3d840208}, | ||
162 | {0x00016288, 0x05a20408}, | ||
163 | {0x0001628c, 0x00038c07}, | ||
164 | {0x00016290, 0x00000004}, | ||
165 | {0x00016294, 0x458aa14f}, | ||
166 | {0x00016380, 0x00000000}, | ||
167 | {0x00016384, 0x00000000}, | ||
168 | {0x00016388, 0x00800700}, | ||
169 | {0x0001638c, 0x00800700}, | ||
170 | {0x00016390, 0x00800700}, | ||
171 | {0x00016394, 0x00000000}, | ||
172 | {0x00016398, 0x00000000}, | ||
173 | {0x0001639c, 0x00000000}, | ||
174 | {0x000163a0, 0x00000001}, | ||
175 | {0x000163a4, 0x00000001}, | ||
176 | {0x000163a8, 0x00000000}, | ||
177 | {0x000163ac, 0x00000000}, | ||
178 | {0x000163b0, 0x00000000}, | ||
179 | {0x000163b4, 0x00000000}, | ||
180 | {0x000163b8, 0x00000000}, | ||
181 | {0x000163bc, 0x00000000}, | ||
182 | {0x000163c0, 0x000000a0}, | ||
183 | {0x000163c4, 0x000c0000}, | ||
184 | {0x000163c8, 0x14021402}, | ||
185 | {0x000163cc, 0x00001402}, | ||
186 | {0x000163d0, 0x00000000}, | ||
187 | {0x000163d4, 0x00000000}, | ||
188 | {0x00016400, 0x36db6db6}, | ||
189 | {0x00016404, 0x6db6db40}, | ||
190 | {0x00016408, 0x73f00000}, | ||
191 | {0x0001640c, 0x00000000}, | ||
192 | {0x00016440, 0x7f80fff8}, | ||
193 | {0x0001644c, 0x76d005b5}, | ||
194 | {0x00016450, 0x556cf031}, | ||
195 | {0x00016454, 0x13449440}, | ||
196 | {0x00016458, 0x0c51c92c}, | ||
197 | {0x0001645c, 0x3db7fffc}, | ||
198 | {0x00016460, 0xfffffffc}, | ||
199 | {0x00016464, 0x000f0278}, | ||
200 | {0x0001646c, 0x6db60000}, | ||
201 | {0x00016500, 0x3fffbe01}, | ||
202 | {0x00016504, 0xfff80000}, | ||
203 | {0x00016508, 0x00080010}, | ||
204 | {0x00016544, 0x02084080}, | ||
205 | {0x00016548, 0x00000000}, | ||
206 | {0x00016780, 0x00000000}, | ||
207 | {0x00016784, 0x00000000}, | ||
208 | {0x00016788, 0x00800700}, | ||
209 | {0x0001678c, 0x00800700}, | ||
210 | {0x00016790, 0x00800700}, | ||
211 | {0x00016794, 0x00000000}, | ||
212 | {0x00016798, 0x00000000}, | ||
213 | {0x0001679c, 0x00000000}, | ||
214 | {0x000167a0, 0x00000001}, | ||
215 | {0x000167a4, 0x00000001}, | ||
216 | {0x000167a8, 0x00000000}, | ||
217 | {0x000167ac, 0x00000000}, | ||
218 | {0x000167b0, 0x00000000}, | ||
219 | {0x000167b4, 0x00000000}, | ||
220 | {0x000167b8, 0x00000000}, | ||
221 | {0x000167bc, 0x00000000}, | ||
222 | {0x000167c0, 0x000000a0}, | ||
223 | {0x000167c4, 0x000c0000}, | ||
224 | {0x000167c8, 0x14021402}, | ||
225 | {0x000167cc, 0x00001402}, | ||
226 | {0x000167d0, 0x00000000}, | ||
227 | {0x000167d4, 0x00000000}, | ||
228 | {0x00016800, 0x36db6db6}, | ||
229 | {0x00016804, 0x6db6db40}, | ||
230 | {0x00016808, 0x73f00000}, | ||
231 | {0x0001680c, 0x00000000}, | ||
232 | {0x00016840, 0x7f80fff8}, | ||
233 | {0x0001684c, 0x76d005b5}, | ||
234 | {0x00016850, 0x556cf031}, | ||
235 | {0x00016854, 0x13449440}, | ||
236 | {0x00016858, 0x0c51c92c}, | ||
237 | {0x0001685c, 0x3db7fffc}, | ||
238 | {0x00016860, 0xfffffffc}, | ||
239 | {0x00016864, 0x000f0278}, | ||
240 | {0x0001686c, 0x6db60000}, | ||
241 | {0x00016900, 0x3fffbe01}, | ||
242 | {0x00016904, 0xfff80000}, | ||
243 | {0x00016908, 0x00080010}, | ||
244 | {0x00016944, 0x02084080}, | ||
245 | {0x00016948, 0x00000000}, | ||
246 | {0x00016b80, 0x00000000}, | ||
247 | {0x00016b84, 0x00000000}, | ||
248 | {0x00016b88, 0x00800700}, | ||
249 | {0x00016b8c, 0x00800700}, | ||
250 | {0x00016b90, 0x00800700}, | ||
251 | {0x00016b94, 0x00000000}, | ||
252 | {0x00016b98, 0x00000000}, | ||
253 | {0x00016b9c, 0x00000000}, | ||
254 | {0x00016ba0, 0x00000001}, | ||
255 | {0x00016ba4, 0x00000001}, | ||
256 | {0x00016ba8, 0x00000000}, | ||
257 | {0x00016bac, 0x00000000}, | ||
258 | {0x00016bb0, 0x00000000}, | ||
259 | {0x00016bb4, 0x00000000}, | ||
260 | {0x00016bb8, 0x00000000}, | ||
261 | {0x00016bbc, 0x00000000}, | ||
262 | {0x00016bc0, 0x000000a0}, | ||
263 | {0x00016bc4, 0x000c0000}, | ||
264 | {0x00016bc8, 0x14021402}, | ||
265 | {0x00016bcc, 0x00001402}, | ||
266 | {0x00016bd0, 0x00000000}, | ||
267 | {0x00016bd4, 0x00000000}, | ||
268 | }; | ||
269 | |||
270 | static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = { | ||
271 | /* Addr allmodes */ | ||
272 | {0x0000a000, 0x02000101}, | ||
273 | {0x0000a004, 0x02000102}, | ||
274 | {0x0000a008, 0x02000103}, | ||
275 | {0x0000a00c, 0x02000104}, | ||
276 | {0x0000a010, 0x02000200}, | ||
277 | {0x0000a014, 0x02000201}, | ||
278 | {0x0000a018, 0x02000202}, | ||
279 | {0x0000a01c, 0x02000203}, | ||
280 | {0x0000a020, 0x02000204}, | ||
281 | {0x0000a024, 0x02000205}, | ||
282 | {0x0000a028, 0x02000208}, | ||
283 | {0x0000a02c, 0x02000302}, | ||
284 | {0x0000a030, 0x02000303}, | ||
285 | {0x0000a034, 0x02000304}, | ||
286 | {0x0000a038, 0x02000400}, | ||
287 | {0x0000a03c, 0x02010300}, | ||
288 | {0x0000a040, 0x02010301}, | ||
289 | {0x0000a044, 0x02010302}, | ||
290 | {0x0000a048, 0x02000500}, | ||
291 | {0x0000a04c, 0x02010400}, | ||
292 | {0x0000a050, 0x02020300}, | ||
293 | {0x0000a054, 0x02020301}, | ||
294 | {0x0000a058, 0x02020302}, | ||
295 | {0x0000a05c, 0x02020303}, | ||
296 | {0x0000a060, 0x02020400}, | ||
297 | {0x0000a064, 0x02030300}, | ||
298 | {0x0000a068, 0x02030301}, | ||
299 | {0x0000a06c, 0x02030302}, | ||
300 | {0x0000a070, 0x02030303}, | ||
301 | {0x0000a074, 0x02030400}, | ||
302 | {0x0000a078, 0x02040300}, | ||
303 | {0x0000a07c, 0x02040301}, | ||
304 | {0x0000a080, 0x02040302}, | ||
305 | {0x0000a084, 0x02040303}, | ||
306 | {0x0000a088, 0x02030500}, | ||
307 | {0x0000a08c, 0x02040400}, | ||
308 | {0x0000a090, 0x02050203}, | ||
309 | {0x0000a094, 0x02050204}, | ||
310 | {0x0000a098, 0x02050205}, | ||
311 | {0x0000a09c, 0x02040500}, | ||
312 | {0x0000a0a0, 0x02050301}, | ||
313 | {0x0000a0a4, 0x02050302}, | ||
314 | {0x0000a0a8, 0x02050303}, | ||
315 | {0x0000a0ac, 0x02050400}, | ||
316 | {0x0000a0b0, 0x02050401}, | ||
317 | {0x0000a0b4, 0x02050402}, | ||
318 | {0x0000a0b8, 0x02050403}, | ||
319 | {0x0000a0bc, 0x02050500}, | ||
320 | {0x0000a0c0, 0x02050501}, | ||
321 | {0x0000a0c4, 0x02050502}, | ||
322 | {0x0000a0c8, 0x02050503}, | ||
323 | {0x0000a0cc, 0x02050504}, | ||
324 | {0x0000a0d0, 0x02050600}, | ||
325 | {0x0000a0d4, 0x02050601}, | ||
326 | {0x0000a0d8, 0x02050602}, | ||
327 | {0x0000a0dc, 0x02050603}, | ||
328 | {0x0000a0e0, 0x02050604}, | ||
329 | {0x0000a0e4, 0x02050700}, | ||
330 | {0x0000a0e8, 0x02050701}, | ||
331 | {0x0000a0ec, 0x02050702}, | ||
332 | {0x0000a0f0, 0x02050703}, | ||
333 | {0x0000a0f4, 0x02050704}, | ||
334 | {0x0000a0f8, 0x02050705}, | ||
335 | {0x0000a0fc, 0x02050708}, | ||
336 | {0x0000a100, 0x02050709}, | ||
337 | {0x0000a104, 0x0205070a}, | ||
338 | {0x0000a108, 0x0205070b}, | ||
339 | {0x0000a10c, 0x0205070c}, | ||
340 | {0x0000a110, 0x0205070d}, | ||
341 | {0x0000a114, 0x02050710}, | ||
342 | {0x0000a118, 0x02050711}, | ||
343 | {0x0000a11c, 0x02050712}, | ||
344 | {0x0000a120, 0x02050713}, | ||
345 | {0x0000a124, 0x02050714}, | ||
346 | {0x0000a128, 0x02050715}, | ||
347 | {0x0000a12c, 0x02050730}, | ||
348 | {0x0000a130, 0x02050731}, | ||
349 | {0x0000a134, 0x02050732}, | ||
350 | {0x0000a138, 0x02050733}, | ||
351 | {0x0000a13c, 0x02050734}, | ||
352 | {0x0000a140, 0x02050735}, | ||
353 | {0x0000a144, 0x02050750}, | ||
354 | {0x0000a148, 0x02050751}, | ||
355 | {0x0000a14c, 0x02050752}, | ||
356 | {0x0000a150, 0x02050753}, | ||
357 | {0x0000a154, 0x02050754}, | ||
358 | {0x0000a158, 0x02050755}, | ||
359 | {0x0000a15c, 0x02050770}, | ||
360 | {0x0000a160, 0x02050771}, | ||
361 | {0x0000a164, 0x02050772}, | ||
362 | {0x0000a168, 0x02050773}, | ||
363 | {0x0000a16c, 0x02050774}, | ||
364 | {0x0000a170, 0x02050775}, | ||
365 | {0x0000a174, 0x00000776}, | ||
366 | {0x0000a178, 0x00000776}, | ||
367 | {0x0000a17c, 0x00000776}, | ||
368 | {0x0000a180, 0x00000776}, | ||
369 | {0x0000a184, 0x00000776}, | ||
370 | {0x0000a188, 0x00000776}, | ||
371 | {0x0000a18c, 0x00000776}, | ||
372 | {0x0000a190, 0x00000776}, | ||
373 | {0x0000a194, 0x00000776}, | ||
374 | {0x0000a198, 0x00000776}, | ||
375 | {0x0000a19c, 0x00000776}, | ||
376 | {0x0000a1a0, 0x00000776}, | ||
377 | {0x0000a1a4, 0x00000776}, | ||
378 | {0x0000a1a8, 0x00000776}, | ||
379 | {0x0000a1ac, 0x00000776}, | ||
380 | {0x0000a1b0, 0x00000776}, | ||
381 | {0x0000a1b4, 0x00000776}, | ||
382 | {0x0000a1b8, 0x00000776}, | ||
383 | {0x0000a1bc, 0x00000776}, | ||
384 | {0x0000a1c0, 0x00000776}, | ||
385 | {0x0000a1c4, 0x00000776}, | ||
386 | {0x0000a1c8, 0x00000776}, | ||
387 | {0x0000a1cc, 0x00000776}, | ||
388 | {0x0000a1d0, 0x00000776}, | ||
389 | {0x0000a1d4, 0x00000776}, | ||
390 | {0x0000a1d8, 0x00000776}, | ||
391 | {0x0000a1dc, 0x00000776}, | ||
392 | {0x0000a1e0, 0x00000776}, | ||
393 | {0x0000a1e4, 0x00000776}, | ||
394 | {0x0000a1e8, 0x00000776}, | ||
395 | {0x0000a1ec, 0x00000776}, | ||
396 | {0x0000a1f0, 0x00000776}, | ||
397 | {0x0000a1f4, 0x00000776}, | ||
398 | {0x0000a1f8, 0x00000776}, | ||
399 | {0x0000a1fc, 0x00000776}, | ||
400 | {0x0000b000, 0x02000101}, | ||
401 | {0x0000b004, 0x02000102}, | ||
402 | {0x0000b008, 0x02000103}, | ||
403 | {0x0000b00c, 0x02000104}, | ||
404 | {0x0000b010, 0x02000200}, | ||
405 | {0x0000b014, 0x02000201}, | ||
406 | {0x0000b018, 0x02000202}, | ||
407 | {0x0000b01c, 0x02000203}, | ||
408 | {0x0000b020, 0x02000204}, | ||
409 | {0x0000b024, 0x02000205}, | ||
410 | {0x0000b028, 0x02000208}, | ||
411 | {0x0000b02c, 0x02000302}, | ||
412 | {0x0000b030, 0x02000303}, | ||
413 | {0x0000b034, 0x02000304}, | ||
414 | {0x0000b038, 0x02000400}, | ||
415 | {0x0000b03c, 0x02010300}, | ||
416 | {0x0000b040, 0x02010301}, | ||
417 | {0x0000b044, 0x02010302}, | ||
418 | {0x0000b048, 0x02000500}, | ||
419 | {0x0000b04c, 0x02010400}, | ||
420 | {0x0000b050, 0x02020300}, | ||
421 | {0x0000b054, 0x02020301}, | ||
422 | {0x0000b058, 0x02020302}, | ||
423 | {0x0000b05c, 0x02020303}, | ||
424 | {0x0000b060, 0x02020400}, | ||
425 | {0x0000b064, 0x02030300}, | ||
426 | {0x0000b068, 0x02030301}, | ||
427 | {0x0000b06c, 0x02030302}, | ||
428 | {0x0000b070, 0x02030303}, | ||
429 | {0x0000b074, 0x02030400}, | ||
430 | {0x0000b078, 0x02040300}, | ||
431 | {0x0000b07c, 0x02040301}, | ||
432 | {0x0000b080, 0x02040302}, | ||
433 | {0x0000b084, 0x02040303}, | ||
434 | {0x0000b088, 0x02030500}, | ||
435 | {0x0000b08c, 0x02040400}, | ||
436 | {0x0000b090, 0x02050203}, | ||
437 | {0x0000b094, 0x02050204}, | ||
438 | {0x0000b098, 0x02050205}, | ||
439 | {0x0000b09c, 0x02040500}, | ||
440 | {0x0000b0a0, 0x02050301}, | ||
441 | {0x0000b0a4, 0x02050302}, | ||
442 | {0x0000b0a8, 0x02050303}, | ||
443 | {0x0000b0ac, 0x02050400}, | ||
444 | {0x0000b0b0, 0x02050401}, | ||
445 | {0x0000b0b4, 0x02050402}, | ||
446 | {0x0000b0b8, 0x02050403}, | ||
447 | {0x0000b0bc, 0x02050500}, | ||
448 | {0x0000b0c0, 0x02050501}, | ||
449 | {0x0000b0c4, 0x02050502}, | ||
450 | {0x0000b0c8, 0x02050503}, | ||
451 | {0x0000b0cc, 0x02050504}, | ||
452 | {0x0000b0d0, 0x02050600}, | ||
453 | {0x0000b0d4, 0x02050601}, | ||
454 | {0x0000b0d8, 0x02050602}, | ||
455 | {0x0000b0dc, 0x02050603}, | ||
456 | {0x0000b0e0, 0x02050604}, | ||
457 | {0x0000b0e4, 0x02050700}, | ||
458 | {0x0000b0e8, 0x02050701}, | ||
459 | {0x0000b0ec, 0x02050702}, | ||
460 | {0x0000b0f0, 0x02050703}, | ||
461 | {0x0000b0f4, 0x02050704}, | ||
462 | {0x0000b0f8, 0x02050705}, | ||
463 | {0x0000b0fc, 0x02050708}, | ||
464 | {0x0000b100, 0x02050709}, | ||
465 | {0x0000b104, 0x0205070a}, | ||
466 | {0x0000b108, 0x0205070b}, | ||
467 | {0x0000b10c, 0x0205070c}, | ||
468 | {0x0000b110, 0x0205070d}, | ||
469 | {0x0000b114, 0x02050710}, | ||
470 | {0x0000b118, 0x02050711}, | ||
471 | {0x0000b11c, 0x02050712}, | ||
472 | {0x0000b120, 0x02050713}, | ||
473 | {0x0000b124, 0x02050714}, | ||
474 | {0x0000b128, 0x02050715}, | ||
475 | {0x0000b12c, 0x02050730}, | ||
476 | {0x0000b130, 0x02050731}, | ||
477 | {0x0000b134, 0x02050732}, | ||
478 | {0x0000b138, 0x02050733}, | ||
479 | {0x0000b13c, 0x02050734}, | ||
480 | {0x0000b140, 0x02050735}, | ||
481 | {0x0000b144, 0x02050750}, | ||
482 | {0x0000b148, 0x02050751}, | ||
483 | {0x0000b14c, 0x02050752}, | ||
484 | {0x0000b150, 0x02050753}, | ||
485 | {0x0000b154, 0x02050754}, | ||
486 | {0x0000b158, 0x02050755}, | ||
487 | {0x0000b15c, 0x02050770}, | ||
488 | {0x0000b160, 0x02050771}, | ||
489 | {0x0000b164, 0x02050772}, | ||
490 | {0x0000b168, 0x02050773}, | ||
491 | {0x0000b16c, 0x02050774}, | ||
492 | {0x0000b170, 0x02050775}, | ||
493 | {0x0000b174, 0x00000776}, | ||
494 | {0x0000b178, 0x00000776}, | ||
495 | {0x0000b17c, 0x00000776}, | ||
496 | {0x0000b180, 0x00000776}, | ||
497 | {0x0000b184, 0x00000776}, | ||
498 | {0x0000b188, 0x00000776}, | ||
499 | {0x0000b18c, 0x00000776}, | ||
500 | {0x0000b190, 0x00000776}, | ||
501 | {0x0000b194, 0x00000776}, | ||
502 | {0x0000b198, 0x00000776}, | ||
503 | {0x0000b19c, 0x00000776}, | ||
504 | {0x0000b1a0, 0x00000776}, | ||
505 | {0x0000b1a4, 0x00000776}, | ||
506 | {0x0000b1a8, 0x00000776}, | ||
507 | {0x0000b1ac, 0x00000776}, | ||
508 | {0x0000b1b0, 0x00000776}, | ||
509 | {0x0000b1b4, 0x00000776}, | ||
510 | {0x0000b1b8, 0x00000776}, | ||
511 | {0x0000b1bc, 0x00000776}, | ||
512 | {0x0000b1c0, 0x00000776}, | ||
513 | {0x0000b1c4, 0x00000776}, | ||
514 | {0x0000b1c8, 0x00000776}, | ||
515 | {0x0000b1cc, 0x00000776}, | ||
516 | {0x0000b1d0, 0x00000776}, | ||
517 | {0x0000b1d4, 0x00000776}, | ||
518 | {0x0000b1d8, 0x00000776}, | ||
519 | {0x0000b1dc, 0x00000776}, | ||
520 | {0x0000b1e0, 0x00000776}, | ||
521 | {0x0000b1e4, 0x00000776}, | ||
522 | {0x0000b1e8, 0x00000776}, | ||
523 | {0x0000b1ec, 0x00000776}, | ||
524 | {0x0000b1f0, 0x00000776}, | ||
525 | {0x0000b1f4, 0x00000776}, | ||
526 | {0x0000b1f8, 0x00000776}, | ||
527 | {0x0000b1fc, 0x00000776}, | ||
528 | }; | ||
529 | |||
530 | static const u32 ar9300_2p2_mac_postamble[][5] = { | ||
531 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
532 | {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, | ||
533 | {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, | ||
534 | {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, | ||
535 | {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, | ||
536 | {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, | ||
537 | {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, | ||
538 | {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, | ||
539 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, | ||
540 | }; | ||
541 | |||
542 | static const u32 ar9300_2p2_soc_postamble[][5] = { | ||
543 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
544 | {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, | ||
545 | }; | ||
546 | |||
547 | static const u32 ar9200_merlin_2p2_radio_core[][2] = { | ||
548 | /* Addr allmodes */ | ||
549 | {0x00007800, 0x00040000}, | ||
550 | {0x00007804, 0xdb005012}, | ||
551 | {0x00007808, 0x04924914}, | ||
552 | {0x0000780c, 0x21084210}, | ||
553 | {0x00007810, 0x6d801300}, | ||
554 | {0x00007814, 0x0019beff}, | ||
555 | {0x00007818, 0x07e41000}, | ||
556 | {0x0000781c, 0x00392000}, | ||
557 | {0x00007820, 0x92592480}, | ||
558 | {0x00007824, 0x00040000}, | ||
559 | {0x00007828, 0xdb005012}, | ||
560 | {0x0000782c, 0x04924914}, | ||
561 | {0x00007830, 0x21084210}, | ||
562 | {0x00007834, 0x6d801300}, | ||
563 | {0x00007838, 0x0019beff}, | ||
564 | {0x0000783c, 0x07e40000}, | ||
565 | {0x00007840, 0x00392000}, | ||
566 | {0x00007844, 0x92592480}, | ||
567 | {0x00007848, 0x00100000}, | ||
568 | {0x0000784c, 0x773f0567}, | ||
569 | {0x00007850, 0x54214514}, | ||
570 | {0x00007854, 0x12035828}, | ||
571 | {0x00007858, 0x92592692}, | ||
572 | {0x0000785c, 0x00000000}, | ||
573 | {0x00007860, 0x56400000}, | ||
574 | {0x00007864, 0x0a8e370e}, | ||
575 | {0x00007868, 0xc0102850}, | ||
576 | {0x0000786c, 0x812d4000}, | ||
577 | {0x00007870, 0x807ec400}, | ||
578 | {0x00007874, 0x001b6db0}, | ||
579 | {0x00007878, 0x00376b63}, | ||
580 | {0x0000787c, 0x06db6db6}, | ||
581 | {0x00007880, 0x006d8000}, | ||
582 | {0x00007884, 0xffeffffe}, | ||
583 | {0x00007888, 0xffeffffe}, | ||
584 | {0x0000788c, 0x00010000}, | ||
585 | {0x00007890, 0x02060aeb}, | ||
586 | {0x00007894, 0x5a108000}, | ||
587 | }; | ||
588 | |||
589 | static const u32 ar9300_2p2_baseband_postamble[][5] = { | ||
590 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
591 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, | ||
592 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, | ||
593 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, | ||
594 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, | ||
595 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | ||
596 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | ||
597 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | ||
598 | {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, | ||
599 | {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, | ||
600 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, | ||
601 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, | ||
602 | {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, | ||
603 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
604 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | ||
605 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | ||
606 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | ||
607 | {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, | ||
608 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | ||
609 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | ||
610 | {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, | ||
611 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | ||
612 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, | ||
613 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, | ||
614 | {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, | ||
615 | {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, | ||
616 | {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, | ||
617 | {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, | ||
618 | {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, | ||
619 | {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, | ||
620 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, | ||
621 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, | ||
622 | {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | ||
623 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | ||
624 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | ||
625 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | ||
626 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, | ||
627 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, | ||
628 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
629 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
630 | {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
631 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
632 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
633 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | ||
634 | {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | ||
635 | {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
636 | {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
637 | {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
638 | {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
639 | {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | ||
640 | {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | ||
641 | }; | ||
642 | |||
643 | static const u32 ar9300_2p2_baseband_core[][2] = { | ||
644 | /* Addr allmodes */ | ||
645 | {0x00009800, 0xafe68e30}, | ||
646 | {0x00009804, 0xfd14e000}, | ||
647 | {0x00009808, 0x9c0a9f6b}, | ||
648 | {0x0000980c, 0x04900000}, | ||
649 | {0x00009814, 0x9280c00a}, | ||
650 | {0x00009818, 0x00000000}, | ||
651 | {0x0000981c, 0x00020028}, | ||
652 | {0x00009834, 0x5f3ca3de}, | ||
653 | {0x00009838, 0x0108ecff}, | ||
654 | {0x0000983c, 0x14750600}, | ||
655 | {0x00009880, 0x201fff00}, | ||
656 | {0x00009884, 0x00001042}, | ||
657 | {0x000098a4, 0x00200400}, | ||
658 | {0x000098b0, 0x52440bbe}, | ||
659 | {0x000098d0, 0x004b6a8e}, | ||
660 | {0x000098d4, 0x00000820}, | ||
661 | {0x000098dc, 0x00000000}, | ||
662 | {0x000098f0, 0x00000000}, | ||
663 | {0x000098f4, 0x00000000}, | ||
664 | {0x00009c04, 0xff55ff55}, | ||
665 | {0x00009c08, 0x0320ff55}, | ||
666 | {0x00009c0c, 0x00000000}, | ||
667 | {0x00009c10, 0x00000000}, | ||
668 | {0x00009c14, 0x00046384}, | ||
669 | {0x00009c18, 0x05b6b440}, | ||
670 | {0x00009c1c, 0x00b6b440}, | ||
671 | {0x00009d00, 0xc080a333}, | ||
672 | {0x00009d04, 0x40206c10}, | ||
673 | {0x00009d08, 0x009c4060}, | ||
674 | {0x00009d0c, 0x9883800a}, | ||
675 | {0x00009d10, 0x01834061}, | ||
676 | {0x00009d14, 0x00c0040b}, | ||
677 | {0x00009d18, 0x00000000}, | ||
678 | {0x00009e08, 0x0038230c}, | ||
679 | {0x00009e24, 0x990bb515}, | ||
680 | {0x00009e28, 0x0c6f0000}, | ||
681 | {0x00009e30, 0x06336f77}, | ||
682 | {0x00009e34, 0x6af6532f}, | ||
683 | {0x00009e38, 0x0cc80c00}, | ||
684 | {0x00009e3c, 0xcf946222}, | ||
685 | {0x00009e40, 0x0d261820}, | ||
686 | {0x00009e4c, 0x00001004}, | ||
687 | {0x00009e50, 0x00ff03f1}, | ||
688 | {0x00009e54, 0x00000000}, | ||
689 | {0x00009fc0, 0x803e4788}, | ||
690 | {0x00009fc4, 0x0001efb5}, | ||
691 | {0x00009fcc, 0x40000014}, | ||
692 | {0x00009fd0, 0x01193b93}, | ||
693 | {0x0000a20c, 0x00000000}, | ||
694 | {0x0000a220, 0x00000000}, | ||
695 | {0x0000a224, 0x00000000}, | ||
696 | {0x0000a228, 0x10002310}, | ||
697 | {0x0000a22c, 0x01036a1e}, | ||
698 | {0x0000a23c, 0x00000000}, | ||
699 | {0x0000a244, 0x0c000000}, | ||
700 | {0x0000a2a0, 0x00000001}, | ||
701 | {0x0000a2c0, 0x00000001}, | ||
702 | {0x0000a2c8, 0x00000000}, | ||
703 | {0x0000a2cc, 0x18c43433}, | ||
704 | {0x0000a2d4, 0x00000000}, | ||
705 | {0x0000a2dc, 0x00000000}, | ||
706 | {0x0000a2e0, 0x00000000}, | ||
707 | {0x0000a2e4, 0x00000000}, | ||
708 | {0x0000a2e8, 0x00000000}, | ||
709 | {0x0000a2ec, 0x00000000}, | ||
710 | {0x0000a2f0, 0x00000000}, | ||
711 | {0x0000a2f4, 0x00000000}, | ||
712 | {0x0000a2f8, 0x00000000}, | ||
713 | {0x0000a344, 0x00000000}, | ||
714 | {0x0000a34c, 0x00000000}, | ||
715 | {0x0000a350, 0x0000a000}, | ||
716 | {0x0000a364, 0x00000000}, | ||
717 | {0x0000a370, 0x00000000}, | ||
718 | {0x0000a390, 0x00000001}, | ||
719 | {0x0000a394, 0x00000444}, | ||
720 | {0x0000a398, 0x001f0e0f}, | ||
721 | {0x0000a39c, 0x0075393f}, | ||
722 | {0x0000a3a0, 0xb79f6427}, | ||
723 | {0x0000a3a4, 0x00000000}, | ||
724 | {0x0000a3a8, 0xaaaaaaaa}, | ||
725 | {0x0000a3ac, 0x3c466478}, | ||
726 | {0x0000a3c0, 0x20202020}, | ||
727 | {0x0000a3c4, 0x22222220}, | ||
728 | {0x0000a3c8, 0x20200020}, | ||
729 | {0x0000a3cc, 0x20202020}, | ||
730 | {0x0000a3d0, 0x20202020}, | ||
731 | {0x0000a3d4, 0x20202020}, | ||
732 | {0x0000a3d8, 0x20202020}, | ||
733 | {0x0000a3dc, 0x20202020}, | ||
734 | {0x0000a3e0, 0x20202020}, | ||
735 | {0x0000a3e4, 0x20202020}, | ||
736 | {0x0000a3e8, 0x20202020}, | ||
737 | {0x0000a3ec, 0x20202020}, | ||
738 | {0x0000a3f0, 0x00000000}, | ||
739 | {0x0000a3f4, 0x00000246}, | ||
740 | {0x0000a3f8, 0x0cdbd380}, | ||
741 | {0x0000a3fc, 0x000f0f01}, | ||
742 | {0x0000a400, 0x8fa91f01}, | ||
743 | {0x0000a404, 0x00000000}, | ||
744 | {0x0000a408, 0x0e79e5c6}, | ||
745 | {0x0000a40c, 0x00820820}, | ||
746 | {0x0000a414, 0x1ce739ce}, | ||
747 | {0x0000a418, 0x2d001dce}, | ||
748 | {0x0000a41c, 0x1ce739ce}, | ||
749 | {0x0000a420, 0x000001ce}, | ||
750 | {0x0000a424, 0x1ce739ce}, | ||
751 | {0x0000a428, 0x000001ce}, | ||
752 | {0x0000a42c, 0x1ce739ce}, | ||
753 | {0x0000a430, 0x1ce739ce}, | ||
754 | {0x0000a434, 0x00000000}, | ||
755 | {0x0000a438, 0x00001801}, | ||
756 | {0x0000a43c, 0x00000000}, | ||
757 | {0x0000a440, 0x00000000}, | ||
758 | {0x0000a444, 0x00000000}, | ||
759 | {0x0000a448, 0x06000080}, | ||
760 | {0x0000a44c, 0x00000001}, | ||
761 | {0x0000a450, 0x00010000}, | ||
762 | {0x0000a458, 0x00000000}, | ||
763 | {0x0000a600, 0x00000000}, | ||
764 | {0x0000a604, 0x00000000}, | ||
765 | {0x0000a608, 0x00000000}, | ||
766 | {0x0000a60c, 0x00000000}, | ||
767 | {0x0000a610, 0x00000000}, | ||
768 | {0x0000a614, 0x00000000}, | ||
769 | {0x0000a618, 0x00000000}, | ||
770 | {0x0000a61c, 0x00000000}, | ||
771 | {0x0000a620, 0x00000000}, | ||
772 | {0x0000a624, 0x00000000}, | ||
773 | {0x0000a628, 0x00000000}, | ||
774 | {0x0000a62c, 0x00000000}, | ||
775 | {0x0000a630, 0x00000000}, | ||
776 | {0x0000a634, 0x00000000}, | ||
777 | {0x0000a638, 0x00000000}, | ||
778 | {0x0000a63c, 0x00000000}, | ||
779 | {0x0000a640, 0x00000000}, | ||
780 | {0x0000a644, 0x3fad9d74}, | ||
781 | {0x0000a648, 0x0048060a}, | ||
782 | {0x0000a64c, 0x00000637}, | ||
783 | {0x0000a670, 0x03020100}, | ||
784 | {0x0000a674, 0x09080504}, | ||
785 | {0x0000a678, 0x0d0c0b0a}, | ||
786 | {0x0000a67c, 0x13121110}, | ||
787 | {0x0000a680, 0x31301514}, | ||
788 | {0x0000a684, 0x35343332}, | ||
789 | {0x0000a688, 0x00000036}, | ||
790 | {0x0000a690, 0x00000838}, | ||
791 | {0x0000a7c0, 0x00000000}, | ||
792 | {0x0000a7c4, 0xfffffffc}, | ||
793 | {0x0000a7c8, 0x00000000}, | ||
794 | {0x0000a7cc, 0x00000000}, | ||
795 | {0x0000a7d0, 0x00000000}, | ||
796 | {0x0000a7d4, 0x00000004}, | ||
797 | {0x0000a7dc, 0x00000001}, | ||
798 | {0x0000a8d0, 0x004b6a8e}, | ||
799 | {0x0000a8d4, 0x00000820}, | ||
800 | {0x0000a8dc, 0x00000000}, | ||
801 | {0x0000a8f0, 0x00000000}, | ||
802 | {0x0000a8f4, 0x00000000}, | ||
803 | {0x0000b2d0, 0x00000080}, | ||
804 | {0x0000b2d4, 0x00000000}, | ||
805 | {0x0000b2dc, 0x00000000}, | ||
806 | {0x0000b2e0, 0x00000000}, | ||
807 | {0x0000b2e4, 0x00000000}, | ||
808 | {0x0000b2e8, 0x00000000}, | ||
809 | {0x0000b2ec, 0x00000000}, | ||
810 | {0x0000b2f0, 0x00000000}, | ||
811 | {0x0000b2f4, 0x00000000}, | ||
812 | {0x0000b2f8, 0x00000000}, | ||
813 | {0x0000b408, 0x0e79e5c0}, | ||
814 | {0x0000b40c, 0x00820820}, | ||
815 | {0x0000b420, 0x00000000}, | ||
816 | {0x0000b8d0, 0x004b6a8e}, | ||
817 | {0x0000b8d4, 0x00000820}, | ||
818 | {0x0000b8dc, 0x00000000}, | ||
819 | {0x0000b8f0, 0x00000000}, | ||
820 | {0x0000b8f4, 0x00000000}, | ||
821 | {0x0000c2d0, 0x00000080}, | ||
822 | {0x0000c2d4, 0x00000000}, | ||
823 | {0x0000c2dc, 0x00000000}, | ||
824 | {0x0000c2e0, 0x00000000}, | ||
825 | {0x0000c2e4, 0x00000000}, | ||
826 | {0x0000c2e8, 0x00000000}, | ||
827 | {0x0000c2ec, 0x00000000}, | ||
828 | {0x0000c2f0, 0x00000000}, | ||
829 | {0x0000c2f4, 0x00000000}, | ||
830 | {0x0000c2f8, 0x00000000}, | ||
831 | {0x0000c408, 0x0e79e5c0}, | ||
832 | {0x0000c40c, 0x00820820}, | ||
833 | {0x0000c420, 0x00000000}, | ||
834 | }; | ||
835 | |||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | ||
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
838 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | ||
839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | ||
840 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | ||
841 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, | ||
842 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, | ||
843 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, | ||
844 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, | ||
845 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, | ||
846 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, | ||
847 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, | ||
848 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, | ||
849 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, | ||
850 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, | ||
851 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, | ||
852 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, | ||
853 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, | ||
854 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, | ||
855 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, | ||
856 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, | ||
857 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, | ||
858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | ||
859 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, | ||
860 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, | ||
861 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, | ||
862 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, | ||
863 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, | ||
864 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
865 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
866 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
867 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
868 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
869 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
870 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | ||
872 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, | ||
873 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, | ||
874 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, | ||
875 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, | ||
876 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, | ||
877 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, | ||
878 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, | ||
879 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, | ||
880 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, | ||
881 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, | ||
882 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, | ||
883 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, | ||
884 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, | ||
885 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, | ||
886 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, | ||
887 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, | ||
888 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, | ||
889 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, | ||
890 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, | ||
891 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, | ||
892 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, | ||
893 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, | ||
894 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, | ||
895 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, | ||
896 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
897 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
898 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
899 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
900 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
901 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
902 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | ||
904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | ||
905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | ||
906 | {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | ||
907 | {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | ||
908 | {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | ||
909 | {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | ||
910 | {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | ||
911 | {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | ||
912 | }; | ||
913 | |||
914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | ||
915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
916 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | ||
917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | ||
918 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | ||
919 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, | ||
920 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, | ||
921 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, | ||
922 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, | ||
923 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, | ||
924 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, | ||
925 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, | ||
926 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, | ||
927 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, | ||
928 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, | ||
929 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, | ||
930 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, | ||
931 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, | ||
932 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, | ||
933 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, | ||
934 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, | ||
935 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, | ||
936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | ||
937 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, | ||
938 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, | ||
939 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, | ||
940 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, | ||
941 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, | ||
942 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
943 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
944 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
945 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
946 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
947 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
948 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | ||
950 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, | ||
951 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, | ||
952 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, | ||
953 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, | ||
954 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, | ||
955 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, | ||
956 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, | ||
957 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, | ||
958 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, | ||
959 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, | ||
960 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, | ||
961 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, | ||
962 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, | ||
963 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, | ||
964 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, | ||
965 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, | ||
966 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, | ||
967 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, | ||
968 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, | ||
969 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, | ||
970 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, | ||
971 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, | ||
972 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, | ||
973 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, | ||
974 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
975 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
976 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
977 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
978 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
979 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
980 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | ||
982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | ||
983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
984 | {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | ||
985 | {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | ||
986 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
987 | {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | ||
988 | {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | ||
989 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
990 | }; | ||
991 | |||
992 | static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | ||
993 | /* Addr allmodes */ | ||
994 | {0x0000a000, 0x00010000}, | ||
995 | {0x0000a004, 0x00030002}, | ||
996 | {0x0000a008, 0x00050004}, | ||
997 | {0x0000a00c, 0x00810080}, | ||
998 | {0x0000a010, 0x00830082}, | ||
999 | {0x0000a014, 0x01810180}, | ||
1000 | {0x0000a018, 0x01830182}, | ||
1001 | {0x0000a01c, 0x01850184}, | ||
1002 | {0x0000a020, 0x01890188}, | ||
1003 | {0x0000a024, 0x018b018a}, | ||
1004 | {0x0000a028, 0x018d018c}, | ||
1005 | {0x0000a02c, 0x01910190}, | ||
1006 | {0x0000a030, 0x01930192}, | ||
1007 | {0x0000a034, 0x01950194}, | ||
1008 | {0x0000a038, 0x038a0196}, | ||
1009 | {0x0000a03c, 0x038c038b}, | ||
1010 | {0x0000a040, 0x0390038d}, | ||
1011 | {0x0000a044, 0x03920391}, | ||
1012 | {0x0000a048, 0x03940393}, | ||
1013 | {0x0000a04c, 0x03960395}, | ||
1014 | {0x0000a050, 0x00000000}, | ||
1015 | {0x0000a054, 0x00000000}, | ||
1016 | {0x0000a058, 0x00000000}, | ||
1017 | {0x0000a05c, 0x00000000}, | ||
1018 | {0x0000a060, 0x00000000}, | ||
1019 | {0x0000a064, 0x00000000}, | ||
1020 | {0x0000a068, 0x00000000}, | ||
1021 | {0x0000a06c, 0x00000000}, | ||
1022 | {0x0000a070, 0x00000000}, | ||
1023 | {0x0000a074, 0x00000000}, | ||
1024 | {0x0000a078, 0x00000000}, | ||
1025 | {0x0000a07c, 0x00000000}, | ||
1026 | {0x0000a080, 0x22222229}, | ||
1027 | {0x0000a084, 0x1d1d1d1d}, | ||
1028 | {0x0000a088, 0x1d1d1d1d}, | ||
1029 | {0x0000a08c, 0x1d1d1d1d}, | ||
1030 | {0x0000a090, 0x171d1d1d}, | ||
1031 | {0x0000a094, 0x11111717}, | ||
1032 | {0x0000a098, 0x00030311}, | ||
1033 | {0x0000a09c, 0x00000000}, | ||
1034 | {0x0000a0a0, 0x00000000}, | ||
1035 | {0x0000a0a4, 0x00000000}, | ||
1036 | {0x0000a0a8, 0x00000000}, | ||
1037 | {0x0000a0ac, 0x00000000}, | ||
1038 | {0x0000a0b0, 0x00000000}, | ||
1039 | {0x0000a0b4, 0x00000000}, | ||
1040 | {0x0000a0b8, 0x00000000}, | ||
1041 | {0x0000a0bc, 0x00000000}, | ||
1042 | {0x0000a0c0, 0x001f0000}, | ||
1043 | {0x0000a0c4, 0x01000101}, | ||
1044 | {0x0000a0c8, 0x011e011f}, | ||
1045 | {0x0000a0cc, 0x011c011d}, | ||
1046 | {0x0000a0d0, 0x02030204}, | ||
1047 | {0x0000a0d4, 0x02010202}, | ||
1048 | {0x0000a0d8, 0x021f0200}, | ||
1049 | {0x0000a0dc, 0x0302021e}, | ||
1050 | {0x0000a0e0, 0x03000301}, | ||
1051 | {0x0000a0e4, 0x031e031f}, | ||
1052 | {0x0000a0e8, 0x0402031d}, | ||
1053 | {0x0000a0ec, 0x04000401}, | ||
1054 | {0x0000a0f0, 0x041e041f}, | ||
1055 | {0x0000a0f4, 0x0502041d}, | ||
1056 | {0x0000a0f8, 0x05000501}, | ||
1057 | {0x0000a0fc, 0x051e051f}, | ||
1058 | {0x0000a100, 0x06010602}, | ||
1059 | {0x0000a104, 0x061f0600}, | ||
1060 | {0x0000a108, 0x061d061e}, | ||
1061 | {0x0000a10c, 0x07020703}, | ||
1062 | {0x0000a110, 0x07000701}, | ||
1063 | {0x0000a114, 0x00000000}, | ||
1064 | {0x0000a118, 0x00000000}, | ||
1065 | {0x0000a11c, 0x00000000}, | ||
1066 | {0x0000a120, 0x00000000}, | ||
1067 | {0x0000a124, 0x00000000}, | ||
1068 | {0x0000a128, 0x00000000}, | ||
1069 | {0x0000a12c, 0x00000000}, | ||
1070 | {0x0000a130, 0x00000000}, | ||
1071 | {0x0000a134, 0x00000000}, | ||
1072 | {0x0000a138, 0x00000000}, | ||
1073 | {0x0000a13c, 0x00000000}, | ||
1074 | {0x0000a140, 0x001f0000}, | ||
1075 | {0x0000a144, 0x01000101}, | ||
1076 | {0x0000a148, 0x011e011f}, | ||
1077 | {0x0000a14c, 0x011c011d}, | ||
1078 | {0x0000a150, 0x02030204}, | ||
1079 | {0x0000a154, 0x02010202}, | ||
1080 | {0x0000a158, 0x021f0200}, | ||
1081 | {0x0000a15c, 0x0302021e}, | ||
1082 | {0x0000a160, 0x03000301}, | ||
1083 | {0x0000a164, 0x031e031f}, | ||
1084 | {0x0000a168, 0x0402031d}, | ||
1085 | {0x0000a16c, 0x04000401}, | ||
1086 | {0x0000a170, 0x041e041f}, | ||
1087 | {0x0000a174, 0x0502041d}, | ||
1088 | {0x0000a178, 0x05000501}, | ||
1089 | {0x0000a17c, 0x051e051f}, | ||
1090 | {0x0000a180, 0x06010602}, | ||
1091 | {0x0000a184, 0x061f0600}, | ||
1092 | {0x0000a188, 0x061d061e}, | ||
1093 | {0x0000a18c, 0x07020703}, | ||
1094 | {0x0000a190, 0x07000701}, | ||
1095 | {0x0000a194, 0x00000000}, | ||
1096 | {0x0000a198, 0x00000000}, | ||
1097 | {0x0000a19c, 0x00000000}, | ||
1098 | {0x0000a1a0, 0x00000000}, | ||
1099 | {0x0000a1a4, 0x00000000}, | ||
1100 | {0x0000a1a8, 0x00000000}, | ||
1101 | {0x0000a1ac, 0x00000000}, | ||
1102 | {0x0000a1b0, 0x00000000}, | ||
1103 | {0x0000a1b4, 0x00000000}, | ||
1104 | {0x0000a1b8, 0x00000000}, | ||
1105 | {0x0000a1bc, 0x00000000}, | ||
1106 | {0x0000a1c0, 0x00000000}, | ||
1107 | {0x0000a1c4, 0x00000000}, | ||
1108 | {0x0000a1c8, 0x00000000}, | ||
1109 | {0x0000a1cc, 0x00000000}, | ||
1110 | {0x0000a1d0, 0x00000000}, | ||
1111 | {0x0000a1d4, 0x00000000}, | ||
1112 | {0x0000a1d8, 0x00000000}, | ||
1113 | {0x0000a1dc, 0x00000000}, | ||
1114 | {0x0000a1e0, 0x00000000}, | ||
1115 | {0x0000a1e4, 0x00000000}, | ||
1116 | {0x0000a1e8, 0x00000000}, | ||
1117 | {0x0000a1ec, 0x00000000}, | ||
1118 | {0x0000a1f0, 0x00000396}, | ||
1119 | {0x0000a1f4, 0x00000396}, | ||
1120 | {0x0000a1f8, 0x00000396}, | ||
1121 | {0x0000a1fc, 0x00000196}, | ||
1122 | {0x0000b000, 0x00010000}, | ||
1123 | {0x0000b004, 0x00030002}, | ||
1124 | {0x0000b008, 0x00050004}, | ||
1125 | {0x0000b00c, 0x00810080}, | ||
1126 | {0x0000b010, 0x00830082}, | ||
1127 | {0x0000b014, 0x01810180}, | ||
1128 | {0x0000b018, 0x01830182}, | ||
1129 | {0x0000b01c, 0x01850184}, | ||
1130 | {0x0000b020, 0x02810280}, | ||
1131 | {0x0000b024, 0x02830282}, | ||
1132 | {0x0000b028, 0x02850284}, | ||
1133 | {0x0000b02c, 0x02890288}, | ||
1134 | {0x0000b030, 0x028b028a}, | ||
1135 | {0x0000b034, 0x0388028c}, | ||
1136 | {0x0000b038, 0x038a0389}, | ||
1137 | {0x0000b03c, 0x038c038b}, | ||
1138 | {0x0000b040, 0x0390038d}, | ||
1139 | {0x0000b044, 0x03920391}, | ||
1140 | {0x0000b048, 0x03940393}, | ||
1141 | {0x0000b04c, 0x03960395}, | ||
1142 | {0x0000b050, 0x00000000}, | ||
1143 | {0x0000b054, 0x00000000}, | ||
1144 | {0x0000b058, 0x00000000}, | ||
1145 | {0x0000b05c, 0x00000000}, | ||
1146 | {0x0000b060, 0x00000000}, | ||
1147 | {0x0000b064, 0x00000000}, | ||
1148 | {0x0000b068, 0x00000000}, | ||
1149 | {0x0000b06c, 0x00000000}, | ||
1150 | {0x0000b070, 0x00000000}, | ||
1151 | {0x0000b074, 0x00000000}, | ||
1152 | {0x0000b078, 0x00000000}, | ||
1153 | {0x0000b07c, 0x00000000}, | ||
1154 | {0x0000b080, 0x32323232}, | ||
1155 | {0x0000b084, 0x2f2f3232}, | ||
1156 | {0x0000b088, 0x23282a2d}, | ||
1157 | {0x0000b08c, 0x1c1e2123}, | ||
1158 | {0x0000b090, 0x14171919}, | ||
1159 | {0x0000b094, 0x0e0e1214}, | ||
1160 | {0x0000b098, 0x03050707}, | ||
1161 | {0x0000b09c, 0x00030303}, | ||
1162 | {0x0000b0a0, 0x00000000}, | ||
1163 | {0x0000b0a4, 0x00000000}, | ||
1164 | {0x0000b0a8, 0x00000000}, | ||
1165 | {0x0000b0ac, 0x00000000}, | ||
1166 | {0x0000b0b0, 0x00000000}, | ||
1167 | {0x0000b0b4, 0x00000000}, | ||
1168 | {0x0000b0b8, 0x00000000}, | ||
1169 | {0x0000b0bc, 0x00000000}, | ||
1170 | {0x0000b0c0, 0x003f0020}, | ||
1171 | {0x0000b0c4, 0x00400041}, | ||
1172 | {0x0000b0c8, 0x0140005f}, | ||
1173 | {0x0000b0cc, 0x0160015f}, | ||
1174 | {0x0000b0d0, 0x017e017f}, | ||
1175 | {0x0000b0d4, 0x02410242}, | ||
1176 | {0x0000b0d8, 0x025f0240}, | ||
1177 | {0x0000b0dc, 0x027f0260}, | ||
1178 | {0x0000b0e0, 0x0341027e}, | ||
1179 | {0x0000b0e4, 0x035f0340}, | ||
1180 | {0x0000b0e8, 0x037f0360}, | ||
1181 | {0x0000b0ec, 0x04400441}, | ||
1182 | {0x0000b0f0, 0x0460045f}, | ||
1183 | {0x0000b0f4, 0x0541047f}, | ||
1184 | {0x0000b0f8, 0x055f0540}, | ||
1185 | {0x0000b0fc, 0x057f0560}, | ||
1186 | {0x0000b100, 0x06400641}, | ||
1187 | {0x0000b104, 0x0660065f}, | ||
1188 | {0x0000b108, 0x067e067f}, | ||
1189 | {0x0000b10c, 0x07410742}, | ||
1190 | {0x0000b110, 0x075f0740}, | ||
1191 | {0x0000b114, 0x077f0760}, | ||
1192 | {0x0000b118, 0x07800781}, | ||
1193 | {0x0000b11c, 0x07a0079f}, | ||
1194 | {0x0000b120, 0x07c107bf}, | ||
1195 | {0x0000b124, 0x000007c0}, | ||
1196 | {0x0000b128, 0x00000000}, | ||
1197 | {0x0000b12c, 0x00000000}, | ||
1198 | {0x0000b130, 0x00000000}, | ||
1199 | {0x0000b134, 0x00000000}, | ||
1200 | {0x0000b138, 0x00000000}, | ||
1201 | {0x0000b13c, 0x00000000}, | ||
1202 | {0x0000b140, 0x003f0020}, | ||
1203 | {0x0000b144, 0x00400041}, | ||
1204 | {0x0000b148, 0x0140005f}, | ||
1205 | {0x0000b14c, 0x0160015f}, | ||
1206 | {0x0000b150, 0x017e017f}, | ||
1207 | {0x0000b154, 0x02410242}, | ||
1208 | {0x0000b158, 0x025f0240}, | ||
1209 | {0x0000b15c, 0x027f0260}, | ||
1210 | {0x0000b160, 0x0341027e}, | ||
1211 | {0x0000b164, 0x035f0340}, | ||
1212 | {0x0000b168, 0x037f0360}, | ||
1213 | {0x0000b16c, 0x04400441}, | ||
1214 | {0x0000b170, 0x0460045f}, | ||
1215 | {0x0000b174, 0x0541047f}, | ||
1216 | {0x0000b178, 0x055f0540}, | ||
1217 | {0x0000b17c, 0x057f0560}, | ||
1218 | {0x0000b180, 0x06400641}, | ||
1219 | {0x0000b184, 0x0660065f}, | ||
1220 | {0x0000b188, 0x067e067f}, | ||
1221 | {0x0000b18c, 0x07410742}, | ||
1222 | {0x0000b190, 0x075f0740}, | ||
1223 | {0x0000b194, 0x077f0760}, | ||
1224 | {0x0000b198, 0x07800781}, | ||
1225 | {0x0000b19c, 0x07a0079f}, | ||
1226 | {0x0000b1a0, 0x07c107bf}, | ||
1227 | {0x0000b1a4, 0x000007c0}, | ||
1228 | {0x0000b1a8, 0x00000000}, | ||
1229 | {0x0000b1ac, 0x00000000}, | ||
1230 | {0x0000b1b0, 0x00000000}, | ||
1231 | {0x0000b1b4, 0x00000000}, | ||
1232 | {0x0000b1b8, 0x00000000}, | ||
1233 | {0x0000b1bc, 0x00000000}, | ||
1234 | {0x0000b1c0, 0x00000000}, | ||
1235 | {0x0000b1c4, 0x00000000}, | ||
1236 | {0x0000b1c8, 0x00000000}, | ||
1237 | {0x0000b1cc, 0x00000000}, | ||
1238 | {0x0000b1d0, 0x00000000}, | ||
1239 | {0x0000b1d4, 0x00000000}, | ||
1240 | {0x0000b1d8, 0x00000000}, | ||
1241 | {0x0000b1dc, 0x00000000}, | ||
1242 | {0x0000b1e0, 0x00000000}, | ||
1243 | {0x0000b1e4, 0x00000000}, | ||
1244 | {0x0000b1e8, 0x00000000}, | ||
1245 | {0x0000b1ec, 0x00000000}, | ||
1246 | {0x0000b1f0, 0x00000396}, | ||
1247 | {0x0000b1f4, 0x00000396}, | ||
1248 | {0x0000b1f8, 0x00000396}, | ||
1249 | {0x0000b1fc, 0x00000196}, | ||
1250 | }; | ||
1251 | |||
1252 | static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | ||
1253 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1254 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
1255 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1256 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
1257 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
1258 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
1259 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, | ||
1260 | {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, | ||
1261 | {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, | ||
1262 | {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, | ||
1263 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, | ||
1264 | {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, | ||
1265 | {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, | ||
1266 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, | ||
1267 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, | ||
1268 | {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, | ||
1269 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, | ||
1270 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, | ||
1271 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, | ||
1272 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, | ||
1273 | {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, | ||
1274 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, | ||
1275 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, | ||
1276 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, | ||
1277 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, | ||
1278 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, | ||
1279 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, | ||
1280 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1281 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1282 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1283 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1284 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1285 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1286 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | ||
1287 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
1288 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | ||
1289 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | ||
1290 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | ||
1291 | {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, | ||
1292 | {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, | ||
1293 | {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, | ||
1294 | {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, | ||
1295 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, | ||
1296 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, | ||
1297 | {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, | ||
1298 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, | ||
1299 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, | ||
1300 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, | ||
1301 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, | ||
1302 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, | ||
1303 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, | ||
1304 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, | ||
1305 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, | ||
1306 | {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, | ||
1307 | {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, | ||
1308 | {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, | ||
1309 | {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, | ||
1310 | {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, | ||
1311 | {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, | ||
1312 | {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1313 | {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1314 | {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1315 | {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1316 | {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1317 | {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1318 | {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | ||
1319 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
1320 | {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, | ||
1321 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
1322 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
1323 | {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, | ||
1324 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
1325 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
1326 | {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, | ||
1327 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
1328 | }; | ||
1329 | |||
1330 | static const u32 ar9300_2p2_mac_core[][2] = { | ||
1331 | /* Addr allmodes */ | ||
1332 | {0x00000008, 0x00000000}, | ||
1333 | {0x00000030, 0x00020085}, | ||
1334 | {0x00000034, 0x00000005}, | ||
1335 | {0x00000040, 0x00000000}, | ||
1336 | {0x00000044, 0x00000000}, | ||
1337 | {0x00000048, 0x00000008}, | ||
1338 | {0x0000004c, 0x00000010}, | ||
1339 | {0x00000050, 0x00000000}, | ||
1340 | {0x00001040, 0x002ffc0f}, | ||
1341 | {0x00001044, 0x002ffc0f}, | ||
1342 | {0x00001048, 0x002ffc0f}, | ||
1343 | {0x0000104c, 0x002ffc0f}, | ||
1344 | {0x00001050, 0x002ffc0f}, | ||
1345 | {0x00001054, 0x002ffc0f}, | ||
1346 | {0x00001058, 0x002ffc0f}, | ||
1347 | {0x0000105c, 0x002ffc0f}, | ||
1348 | {0x00001060, 0x002ffc0f}, | ||
1349 | {0x00001064, 0x002ffc0f}, | ||
1350 | {0x000010f0, 0x00000100}, | ||
1351 | {0x00001270, 0x00000000}, | ||
1352 | {0x000012b0, 0x00000000}, | ||
1353 | {0x000012f0, 0x00000000}, | ||
1354 | {0x0000143c, 0x00000000}, | ||
1355 | {0x0000147c, 0x00000000}, | ||
1356 | {0x00008000, 0x00000000}, | ||
1357 | {0x00008004, 0x00000000}, | ||
1358 | {0x00008008, 0x00000000}, | ||
1359 | {0x0000800c, 0x00000000}, | ||
1360 | {0x00008018, 0x00000000}, | ||
1361 | {0x00008020, 0x00000000}, | ||
1362 | {0x00008038, 0x00000000}, | ||
1363 | {0x0000803c, 0x00000000}, | ||
1364 | {0x00008040, 0x00000000}, | ||
1365 | {0x00008044, 0x00000000}, | ||
1366 | {0x00008048, 0x00000000}, | ||
1367 | {0x0000804c, 0xffffffff}, | ||
1368 | {0x00008054, 0x00000000}, | ||
1369 | {0x00008058, 0x00000000}, | ||
1370 | {0x0000805c, 0x000fc78f}, | ||
1371 | {0x00008060, 0x0000000f}, | ||
1372 | {0x00008064, 0x00000000}, | ||
1373 | {0x00008070, 0x00000310}, | ||
1374 | {0x00008074, 0x00000020}, | ||
1375 | {0x00008078, 0x00000000}, | ||
1376 | {0x0000809c, 0x0000000f}, | ||
1377 | {0x000080a0, 0x00000000}, | ||
1378 | {0x000080a4, 0x02ff0000}, | ||
1379 | {0x000080a8, 0x0e070605}, | ||
1380 | {0x000080ac, 0x0000000d}, | ||
1381 | {0x000080b0, 0x00000000}, | ||
1382 | {0x000080b4, 0x00000000}, | ||
1383 | {0x000080b8, 0x00000000}, | ||
1384 | {0x000080bc, 0x00000000}, | ||
1385 | {0x000080c0, 0x2a800000}, | ||
1386 | {0x000080c4, 0x06900168}, | ||
1387 | {0x000080c8, 0x13881c20}, | ||
1388 | {0x000080cc, 0x01f40000}, | ||
1389 | {0x000080d0, 0x00252500}, | ||
1390 | {0x000080d4, 0x00a00000}, | ||
1391 | {0x000080d8, 0x00400000}, | ||
1392 | {0x000080dc, 0x00000000}, | ||
1393 | {0x000080e0, 0xffffffff}, | ||
1394 | {0x000080e4, 0x0000ffff}, | ||
1395 | {0x000080e8, 0x3f3f3f3f}, | ||
1396 | {0x000080ec, 0x00000000}, | ||
1397 | {0x000080f0, 0x00000000}, | ||
1398 | {0x000080f4, 0x00000000}, | ||
1399 | {0x000080fc, 0x00020000}, | ||
1400 | {0x00008100, 0x00000000}, | ||
1401 | {0x00008108, 0x00000052}, | ||
1402 | {0x0000810c, 0x00000000}, | ||
1403 | {0x00008110, 0x00000000}, | ||
1404 | {0x00008114, 0x000007ff}, | ||
1405 | {0x00008118, 0x000000aa}, | ||
1406 | {0x0000811c, 0x00003210}, | ||
1407 | {0x00008124, 0x00000000}, | ||
1408 | {0x00008128, 0x00000000}, | ||
1409 | {0x0000812c, 0x00000000}, | ||
1410 | {0x00008130, 0x00000000}, | ||
1411 | {0x00008134, 0x00000000}, | ||
1412 | {0x00008138, 0x00000000}, | ||
1413 | {0x0000813c, 0x0000ffff}, | ||
1414 | {0x00008144, 0xffffffff}, | ||
1415 | {0x00008168, 0x00000000}, | ||
1416 | {0x0000816c, 0x00000000}, | ||
1417 | {0x00008170, 0x18486200}, | ||
1418 | {0x00008174, 0x33332210}, | ||
1419 | {0x00008178, 0x00000000}, | ||
1420 | {0x0000817c, 0x00020000}, | ||
1421 | {0x000081c0, 0x00000000}, | ||
1422 | {0x000081c4, 0x33332210}, | ||
1423 | {0x000081c8, 0x00000000}, | ||
1424 | {0x000081cc, 0x00000000}, | ||
1425 | {0x000081d4, 0x00000000}, | ||
1426 | {0x000081ec, 0x00000000}, | ||
1427 | {0x000081f0, 0x00000000}, | ||
1428 | {0x000081f4, 0x00000000}, | ||
1429 | {0x000081f8, 0x00000000}, | ||
1430 | {0x000081fc, 0x00000000}, | ||
1431 | {0x00008240, 0x00100000}, | ||
1432 | {0x00008244, 0x0010f424}, | ||
1433 | {0x00008248, 0x00000800}, | ||
1434 | {0x0000824c, 0x0001e848}, | ||
1435 | {0x00008250, 0x00000000}, | ||
1436 | {0x00008254, 0x00000000}, | ||
1437 | {0x00008258, 0x00000000}, | ||
1438 | {0x0000825c, 0x40000000}, | ||
1439 | {0x00008260, 0x00080922}, | ||
1440 | {0x00008264, 0x9bc00010}, | ||
1441 | {0x00008268, 0xffffffff}, | ||
1442 | {0x0000826c, 0x0000ffff}, | ||
1443 | {0x00008270, 0x00000000}, | ||
1444 | {0x00008274, 0x40000000}, | ||
1445 | {0x00008278, 0x003e4180}, | ||
1446 | {0x0000827c, 0x00000004}, | ||
1447 | {0x00008284, 0x0000002c}, | ||
1448 | {0x00008288, 0x0000002c}, | ||
1449 | {0x0000828c, 0x000000ff}, | ||
1450 | {0x00008294, 0x00000000}, | ||
1451 | {0x00008298, 0x00000000}, | ||
1452 | {0x0000829c, 0x00000000}, | ||
1453 | {0x00008300, 0x00000140}, | ||
1454 | {0x00008314, 0x00000000}, | ||
1455 | {0x0000831c, 0x0000010d}, | ||
1456 | {0x00008328, 0x00000000}, | ||
1457 | {0x0000832c, 0x00000007}, | ||
1458 | {0x00008330, 0x00000302}, | ||
1459 | {0x00008334, 0x00000700}, | ||
1460 | {0x00008338, 0x00ff0000}, | ||
1461 | {0x0000833c, 0x02400000}, | ||
1462 | {0x00008340, 0x000107ff}, | ||
1463 | {0x00008344, 0xaa48105b}, | ||
1464 | {0x00008348, 0x008f0000}, | ||
1465 | {0x0000835c, 0x00000000}, | ||
1466 | {0x00008360, 0xffffffff}, | ||
1467 | {0x00008364, 0xffffffff}, | ||
1468 | {0x00008368, 0x00000000}, | ||
1469 | {0x00008370, 0x00000000}, | ||
1470 | {0x00008374, 0x000000ff}, | ||
1471 | {0x00008378, 0x00000000}, | ||
1472 | {0x0000837c, 0x00000000}, | ||
1473 | {0x00008380, 0xffffffff}, | ||
1474 | {0x00008384, 0xffffffff}, | ||
1475 | {0x00008390, 0xffffffff}, | ||
1476 | {0x00008394, 0xffffffff}, | ||
1477 | {0x00008398, 0x00000000}, | ||
1478 | {0x0000839c, 0x00000000}, | ||
1479 | {0x000083a0, 0x00000000}, | ||
1480 | {0x000083a4, 0x0000fa14}, | ||
1481 | {0x000083a8, 0x000f0c00}, | ||
1482 | {0x000083ac, 0x33332210}, | ||
1483 | {0x000083b0, 0x33332210}, | ||
1484 | {0x000083b4, 0x33332210}, | ||
1485 | {0x000083b8, 0x33332210}, | ||
1486 | {0x000083bc, 0x00000000}, | ||
1487 | {0x000083c0, 0x00000000}, | ||
1488 | {0x000083c4, 0x00000000}, | ||
1489 | {0x000083c8, 0x00000000}, | ||
1490 | {0x000083cc, 0x00000200}, | ||
1491 | {0x000083d0, 0x000301ff}, | ||
1492 | }; | ||
1493 | |||
1494 | static const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = { | ||
1495 | /* Addr allmodes */ | ||
1496 | {0x0000a000, 0x00010000}, | ||
1497 | {0x0000a004, 0x00030002}, | ||
1498 | {0x0000a008, 0x00050004}, | ||
1499 | {0x0000a00c, 0x00810080}, | ||
1500 | {0x0000a010, 0x00830082}, | ||
1501 | {0x0000a014, 0x01810180}, | ||
1502 | {0x0000a018, 0x01830182}, | ||
1503 | {0x0000a01c, 0x01850184}, | ||
1504 | {0x0000a020, 0x01890188}, | ||
1505 | {0x0000a024, 0x018b018a}, | ||
1506 | {0x0000a028, 0x018d018c}, | ||
1507 | {0x0000a02c, 0x03820190}, | ||
1508 | {0x0000a030, 0x03840383}, | ||
1509 | {0x0000a034, 0x03880385}, | ||
1510 | {0x0000a038, 0x038a0389}, | ||
1511 | {0x0000a03c, 0x038c038b}, | ||
1512 | {0x0000a040, 0x0390038d}, | ||
1513 | {0x0000a044, 0x03920391}, | ||
1514 | {0x0000a048, 0x03940393}, | ||
1515 | {0x0000a04c, 0x03960395}, | ||
1516 | {0x0000a050, 0x00000000}, | ||
1517 | {0x0000a054, 0x00000000}, | ||
1518 | {0x0000a058, 0x00000000}, | ||
1519 | {0x0000a05c, 0x00000000}, | ||
1520 | {0x0000a060, 0x00000000}, | ||
1521 | {0x0000a064, 0x00000000}, | ||
1522 | {0x0000a068, 0x00000000}, | ||
1523 | {0x0000a06c, 0x00000000}, | ||
1524 | {0x0000a070, 0x00000000}, | ||
1525 | {0x0000a074, 0x00000000}, | ||
1526 | {0x0000a078, 0x00000000}, | ||
1527 | {0x0000a07c, 0x00000000}, | ||
1528 | {0x0000a080, 0x29292929}, | ||
1529 | {0x0000a084, 0x29292929}, | ||
1530 | {0x0000a088, 0x29292929}, | ||
1531 | {0x0000a08c, 0x29292929}, | ||
1532 | {0x0000a090, 0x22292929}, | ||
1533 | {0x0000a094, 0x1d1d2222}, | ||
1534 | {0x0000a098, 0x0c111117}, | ||
1535 | {0x0000a09c, 0x00030303}, | ||
1536 | {0x0000a0a0, 0x00000000}, | ||
1537 | {0x0000a0a4, 0x00000000}, | ||
1538 | {0x0000a0a8, 0x00000000}, | ||
1539 | {0x0000a0ac, 0x00000000}, | ||
1540 | {0x0000a0b0, 0x00000000}, | ||
1541 | {0x0000a0b4, 0x00000000}, | ||
1542 | {0x0000a0b8, 0x00000000}, | ||
1543 | {0x0000a0bc, 0x00000000}, | ||
1544 | {0x0000a0c0, 0x001f0000}, | ||
1545 | {0x0000a0c4, 0x01000101}, | ||
1546 | {0x0000a0c8, 0x011e011f}, | ||
1547 | {0x0000a0cc, 0x011c011d}, | ||
1548 | {0x0000a0d0, 0x02030204}, | ||
1549 | {0x0000a0d4, 0x02010202}, | ||
1550 | {0x0000a0d8, 0x021f0200}, | ||
1551 | {0x0000a0dc, 0x0302021e}, | ||
1552 | {0x0000a0e0, 0x03000301}, | ||
1553 | {0x0000a0e4, 0x031e031f}, | ||
1554 | {0x0000a0e8, 0x0402031d}, | ||
1555 | {0x0000a0ec, 0x04000401}, | ||
1556 | {0x0000a0f0, 0x041e041f}, | ||
1557 | {0x0000a0f4, 0x0502041d}, | ||
1558 | {0x0000a0f8, 0x05000501}, | ||
1559 | {0x0000a0fc, 0x051e051f}, | ||
1560 | {0x0000a100, 0x06010602}, | ||
1561 | {0x0000a104, 0x061f0600}, | ||
1562 | {0x0000a108, 0x061d061e}, | ||
1563 | {0x0000a10c, 0x07020703}, | ||
1564 | {0x0000a110, 0x07000701}, | ||
1565 | {0x0000a114, 0x00000000}, | ||
1566 | {0x0000a118, 0x00000000}, | ||
1567 | {0x0000a11c, 0x00000000}, | ||
1568 | {0x0000a120, 0x00000000}, | ||
1569 | {0x0000a124, 0x00000000}, | ||
1570 | {0x0000a128, 0x00000000}, | ||
1571 | {0x0000a12c, 0x00000000}, | ||
1572 | {0x0000a130, 0x00000000}, | ||
1573 | {0x0000a134, 0x00000000}, | ||
1574 | {0x0000a138, 0x00000000}, | ||
1575 | {0x0000a13c, 0x00000000}, | ||
1576 | {0x0000a140, 0x001f0000}, | ||
1577 | {0x0000a144, 0x01000101}, | ||
1578 | {0x0000a148, 0x011e011f}, | ||
1579 | {0x0000a14c, 0x011c011d}, | ||
1580 | {0x0000a150, 0x02030204}, | ||
1581 | {0x0000a154, 0x02010202}, | ||
1582 | {0x0000a158, 0x021f0200}, | ||
1583 | {0x0000a15c, 0x0302021e}, | ||
1584 | {0x0000a160, 0x03000301}, | ||
1585 | {0x0000a164, 0x031e031f}, | ||
1586 | {0x0000a168, 0x0402031d}, | ||
1587 | {0x0000a16c, 0x04000401}, | ||
1588 | {0x0000a170, 0x041e041f}, | ||
1589 | {0x0000a174, 0x0502041d}, | ||
1590 | {0x0000a178, 0x05000501}, | ||
1591 | {0x0000a17c, 0x051e051f}, | ||
1592 | {0x0000a180, 0x06010602}, | ||
1593 | {0x0000a184, 0x061f0600}, | ||
1594 | {0x0000a188, 0x061d061e}, | ||
1595 | {0x0000a18c, 0x07020703}, | ||
1596 | {0x0000a190, 0x07000701}, | ||
1597 | {0x0000a194, 0x00000000}, | ||
1598 | {0x0000a198, 0x00000000}, | ||
1599 | {0x0000a19c, 0x00000000}, | ||
1600 | {0x0000a1a0, 0x00000000}, | ||
1601 | {0x0000a1a4, 0x00000000}, | ||
1602 | {0x0000a1a8, 0x00000000}, | ||
1603 | {0x0000a1ac, 0x00000000}, | ||
1604 | {0x0000a1b0, 0x00000000}, | ||
1605 | {0x0000a1b4, 0x00000000}, | ||
1606 | {0x0000a1b8, 0x00000000}, | ||
1607 | {0x0000a1bc, 0x00000000}, | ||
1608 | {0x0000a1c0, 0x00000000}, | ||
1609 | {0x0000a1c4, 0x00000000}, | ||
1610 | {0x0000a1c8, 0x00000000}, | ||
1611 | {0x0000a1cc, 0x00000000}, | ||
1612 | {0x0000a1d0, 0x00000000}, | ||
1613 | {0x0000a1d4, 0x00000000}, | ||
1614 | {0x0000a1d8, 0x00000000}, | ||
1615 | {0x0000a1dc, 0x00000000}, | ||
1616 | {0x0000a1e0, 0x00000000}, | ||
1617 | {0x0000a1e4, 0x00000000}, | ||
1618 | {0x0000a1e8, 0x00000000}, | ||
1619 | {0x0000a1ec, 0x00000000}, | ||
1620 | {0x0000a1f0, 0x00000396}, | ||
1621 | {0x0000a1f4, 0x00000396}, | ||
1622 | {0x0000a1f8, 0x00000396}, | ||
1623 | {0x0000a1fc, 0x00000196}, | ||
1624 | {0x0000b000, 0x00010000}, | ||
1625 | {0x0000b004, 0x00030002}, | ||
1626 | {0x0000b008, 0x00050004}, | ||
1627 | {0x0000b00c, 0x00810080}, | ||
1628 | {0x0000b010, 0x00830082}, | ||
1629 | {0x0000b014, 0x01810180}, | ||
1630 | {0x0000b018, 0x01830182}, | ||
1631 | {0x0000b01c, 0x01850184}, | ||
1632 | {0x0000b020, 0x02810280}, | ||
1633 | {0x0000b024, 0x02830282}, | ||
1634 | {0x0000b028, 0x02850284}, | ||
1635 | {0x0000b02c, 0x02890288}, | ||
1636 | {0x0000b030, 0x028b028a}, | ||
1637 | {0x0000b034, 0x0388028c}, | ||
1638 | {0x0000b038, 0x038a0389}, | ||
1639 | {0x0000b03c, 0x038c038b}, | ||
1640 | {0x0000b040, 0x0390038d}, | ||
1641 | {0x0000b044, 0x03920391}, | ||
1642 | {0x0000b048, 0x03940393}, | ||
1643 | {0x0000b04c, 0x03960395}, | ||
1644 | {0x0000b050, 0x00000000}, | ||
1645 | {0x0000b054, 0x00000000}, | ||
1646 | {0x0000b058, 0x00000000}, | ||
1647 | {0x0000b05c, 0x00000000}, | ||
1648 | {0x0000b060, 0x00000000}, | ||
1649 | {0x0000b064, 0x00000000}, | ||
1650 | {0x0000b068, 0x00000000}, | ||
1651 | {0x0000b06c, 0x00000000}, | ||
1652 | {0x0000b070, 0x00000000}, | ||
1653 | {0x0000b074, 0x00000000}, | ||
1654 | {0x0000b078, 0x00000000}, | ||
1655 | {0x0000b07c, 0x00000000}, | ||
1656 | {0x0000b080, 0x32323232}, | ||
1657 | {0x0000b084, 0x2f2f3232}, | ||
1658 | {0x0000b088, 0x23282a2d}, | ||
1659 | {0x0000b08c, 0x1c1e2123}, | ||
1660 | {0x0000b090, 0x14171919}, | ||
1661 | {0x0000b094, 0x0e0e1214}, | ||
1662 | {0x0000b098, 0x03050707}, | ||
1663 | {0x0000b09c, 0x00030303}, | ||
1664 | {0x0000b0a0, 0x00000000}, | ||
1665 | {0x0000b0a4, 0x00000000}, | ||
1666 | {0x0000b0a8, 0x00000000}, | ||
1667 | {0x0000b0ac, 0x00000000}, | ||
1668 | {0x0000b0b0, 0x00000000}, | ||
1669 | {0x0000b0b4, 0x00000000}, | ||
1670 | {0x0000b0b8, 0x00000000}, | ||
1671 | {0x0000b0bc, 0x00000000}, | ||
1672 | {0x0000b0c0, 0x003f0020}, | ||
1673 | {0x0000b0c4, 0x00400041}, | ||
1674 | {0x0000b0c8, 0x0140005f}, | ||
1675 | {0x0000b0cc, 0x0160015f}, | ||
1676 | {0x0000b0d0, 0x017e017f}, | ||
1677 | {0x0000b0d4, 0x02410242}, | ||
1678 | {0x0000b0d8, 0x025f0240}, | ||
1679 | {0x0000b0dc, 0x027f0260}, | ||
1680 | {0x0000b0e0, 0x0341027e}, | ||
1681 | {0x0000b0e4, 0x035f0340}, | ||
1682 | {0x0000b0e8, 0x037f0360}, | ||
1683 | {0x0000b0ec, 0x04400441}, | ||
1684 | {0x0000b0f0, 0x0460045f}, | ||
1685 | {0x0000b0f4, 0x0541047f}, | ||
1686 | {0x0000b0f8, 0x055f0540}, | ||
1687 | {0x0000b0fc, 0x057f0560}, | ||
1688 | {0x0000b100, 0x06400641}, | ||
1689 | {0x0000b104, 0x0660065f}, | ||
1690 | {0x0000b108, 0x067e067f}, | ||
1691 | {0x0000b10c, 0x07410742}, | ||
1692 | {0x0000b110, 0x075f0740}, | ||
1693 | {0x0000b114, 0x077f0760}, | ||
1694 | {0x0000b118, 0x07800781}, | ||
1695 | {0x0000b11c, 0x07a0079f}, | ||
1696 | {0x0000b120, 0x07c107bf}, | ||
1697 | {0x0000b124, 0x000007c0}, | ||
1698 | {0x0000b128, 0x00000000}, | ||
1699 | {0x0000b12c, 0x00000000}, | ||
1700 | {0x0000b130, 0x00000000}, | ||
1701 | {0x0000b134, 0x00000000}, | ||
1702 | {0x0000b138, 0x00000000}, | ||
1703 | {0x0000b13c, 0x00000000}, | ||
1704 | {0x0000b140, 0x003f0020}, | ||
1705 | {0x0000b144, 0x00400041}, | ||
1706 | {0x0000b148, 0x0140005f}, | ||
1707 | {0x0000b14c, 0x0160015f}, | ||
1708 | {0x0000b150, 0x017e017f}, | ||
1709 | {0x0000b154, 0x02410242}, | ||
1710 | {0x0000b158, 0x025f0240}, | ||
1711 | {0x0000b15c, 0x027f0260}, | ||
1712 | {0x0000b160, 0x0341027e}, | ||
1713 | {0x0000b164, 0x035f0340}, | ||
1714 | {0x0000b168, 0x037f0360}, | ||
1715 | {0x0000b16c, 0x04400441}, | ||
1716 | {0x0000b170, 0x0460045f}, | ||
1717 | {0x0000b174, 0x0541047f}, | ||
1718 | {0x0000b178, 0x055f0540}, | ||
1719 | {0x0000b17c, 0x057f0560}, | ||
1720 | {0x0000b180, 0x06400641}, | ||
1721 | {0x0000b184, 0x0660065f}, | ||
1722 | {0x0000b188, 0x067e067f}, | ||
1723 | {0x0000b18c, 0x07410742}, | ||
1724 | {0x0000b190, 0x075f0740}, | ||
1725 | {0x0000b194, 0x077f0760}, | ||
1726 | {0x0000b198, 0x07800781}, | ||
1727 | {0x0000b19c, 0x07a0079f}, | ||
1728 | {0x0000b1a0, 0x07c107bf}, | ||
1729 | {0x0000b1a4, 0x000007c0}, | ||
1730 | {0x0000b1a8, 0x00000000}, | ||
1731 | {0x0000b1ac, 0x00000000}, | ||
1732 | {0x0000b1b0, 0x00000000}, | ||
1733 | {0x0000b1b4, 0x00000000}, | ||
1734 | {0x0000b1b8, 0x00000000}, | ||
1735 | {0x0000b1bc, 0x00000000}, | ||
1736 | {0x0000b1c0, 0x00000000}, | ||
1737 | {0x0000b1c4, 0x00000000}, | ||
1738 | {0x0000b1c8, 0x00000000}, | ||
1739 | {0x0000b1cc, 0x00000000}, | ||
1740 | {0x0000b1d0, 0x00000000}, | ||
1741 | {0x0000b1d4, 0x00000000}, | ||
1742 | {0x0000b1d8, 0x00000000}, | ||
1743 | {0x0000b1dc, 0x00000000}, | ||
1744 | {0x0000b1e0, 0x00000000}, | ||
1745 | {0x0000b1e4, 0x00000000}, | ||
1746 | {0x0000b1e8, 0x00000000}, | ||
1747 | {0x0000b1ec, 0x00000000}, | ||
1748 | {0x0000b1f0, 0x00000396}, | ||
1749 | {0x0000b1f4, 0x00000396}, | ||
1750 | {0x0000b1f8, 0x00000396}, | ||
1751 | {0x0000b1fc, 0x00000196}, | ||
1752 | }; | ||
1753 | |||
1754 | static const u32 ar9300_2p2_soc_preamble[][2] = { | ||
1755 | /* Addr allmodes */ | ||
1756 | {0x000040a4, 0x00a0c1c9}, | ||
1757 | {0x00007008, 0x00000000}, | ||
1758 | {0x00007020, 0x00000000}, | ||
1759 | {0x00007034, 0x00000002}, | ||
1760 | {0x00007038, 0x000004c2}, | ||
1761 | {0x00007048, 0x00000008}, | ||
1762 | }; | ||
1763 | |||
1764 | static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { | ||
1765 | /* Addr allmodes */ | ||
1766 | {0x00004040, 0x08212e5e}, | ||
1767 | {0x00004040, 0x0008003b}, | ||
1768 | {0x00004044, 0x00000000}, | ||
1769 | }; | ||
1770 | |||
1771 | static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { | ||
1772 | /* Addr allmodes */ | ||
1773 | {0x00004040, 0x08253e5e}, | ||
1774 | {0x00004040, 0x0008003b}, | ||
1775 | {0x00004044, 0x00000000}, | ||
1776 | }; | ||
1777 | |||
1778 | static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { | ||
1779 | /* Addr allmodes */ | ||
1780 | {0x00004040, 0x08213e5e}, | ||
1781 | {0x00004040, 0x0008003b}, | ||
1782 | {0x00004044, 0x00000000}, | ||
1783 | }; | ||
1784 | |||
1785 | #endif /* INITVALS_9003_2P2_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 56a9e5fa6d66..5a0650399136 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -739,6 +739,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
739 | */ | 739 | */ |
740 | ar9003_hw_set_chain_masks(ah, 0x7, 0x7); | 740 | ar9003_hw_set_chain_masks(ah, 0x7, 0x7); |
741 | 741 | ||
742 | /* Do Tx IQ Calibration */ | ||
743 | ar9003_hw_tx_iq_cal(ah); | ||
744 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | ||
745 | udelay(5); | ||
746 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
747 | |||
742 | /* Calibrate the AGC */ | 748 | /* Calibrate the AGC */ |
743 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 749 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
744 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | 750 | REG_READ(ah, AR_PHY_AGC_CONTROL) | |
@@ -753,10 +759,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
753 | return false; | 759 | return false; |
754 | } | 760 | } |
755 | 761 | ||
756 | /* Do Tx IQ Calibration */ | ||
757 | if (ah->config.tx_iq_calibration) | ||
758 | ar9003_hw_tx_iq_cal(ah); | ||
759 | |||
760 | /* Revert chainmasks to their original values before NF cal */ | 762 | /* Revert chainmasks to their original values before NF cal */ |
761 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | 763 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
762 | 764 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 23eb60ea5455..343c9a427acb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -67,6 +67,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
67 | * bit2 - enable fastClock - enabled | 67 | * bit2 - enable fastClock - enabled |
68 | * bit3 - enable doubling - enabled | 68 | * bit3 - enable doubling - enabled |
69 | * bit4 - enable internal regulator - disabled | 69 | * bit4 - enable internal regulator - disabled |
70 | * bit5 - enable pa predistortion - disabled | ||
70 | */ | 71 | */ |
71 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ | 72 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ |
72 | .eepromWriteEnableGpio = 3, | 73 | .eepromWriteEnableGpio = 3, |
@@ -129,9 +130,11 @@ static const struct ar9300_eeprom ar9300_default = { | |||
129 | .txEndToRxOn = 0x2, | 130 | .txEndToRxOn = 0x2, |
130 | .txFrameToXpaOn = 0xe, | 131 | .txFrameToXpaOn = 0xe, |
131 | .thresh62 = 28, | 132 | .thresh62 = 28, |
132 | .futureModal = { /* [32] */ | 133 | .papdRateMaskHt20 = LE32(0x80c080), |
134 | .papdRateMaskHt40 = LE32(0x80c080), | ||
135 | .futureModal = { | ||
133 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
134 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 137 | 0, 0, 0, 0, 0, 0, 0, 0 |
135 | }, | 138 | }, |
136 | }, | 139 | }, |
137 | .calFreqPier2G = { | 140 | .calFreqPier2G = { |
@@ -326,9 +329,11 @@ static const struct ar9300_eeprom ar9300_default = { | |||
326 | .txEndToRxOn = 0x2, | 329 | .txEndToRxOn = 0x2, |
327 | .txFrameToXpaOn = 0xe, | 330 | .txFrameToXpaOn = 0xe, |
328 | .thresh62 = 28, | 331 | .thresh62 = 28, |
332 | .papdRateMaskHt20 = LE32(0xf0e0e0), | ||
333 | .papdRateMaskHt40 = LE32(0xf0e0e0), | ||
329 | .futureModal = { | 334 | .futureModal = { |
330 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 335 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
331 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 336 | 0, 0, 0, 0, 0, 0, 0, 0 |
332 | }, | 337 | }, |
333 | }, | 338 | }, |
334 | .calFreqPier5G = { | 339 | .calFreqPier5G = { |
@@ -644,6 +649,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
644 | return (pBase->featureEnable & 0x10) >> 4; | 649 | return (pBase->featureEnable & 0x10) >> 4; |
645 | case EEP_SWREG: | 650 | case EEP_SWREG: |
646 | return le32_to_cpu(pBase->swreg); | 651 | return le32_to_cpu(pBase->swreg); |
652 | case EEP_PAPRD: | ||
653 | return !!(pBase->featureEnable & BIT(5)); | ||
647 | default: | 654 | default: |
648 | return 0; | 655 | return 0; |
649 | } | 656 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 23fb353c3bba..3c533bb983c7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -234,7 +234,9 @@ struct ar9300_modal_eep_header { | |||
234 | u8 txEndToRxOn; | 234 | u8 txEndToRxOn; |
235 | u8 txFrameToXpaOn; | 235 | u8 txFrameToXpaOn; |
236 | u8 thresh62; | 236 | u8 thresh62; |
237 | u8 futureModal[32]; | 237 | __le32 papdRateMaskHt20; |
238 | __le32 papdRateMaskHt40; | ||
239 | u8 futureModal[24]; | ||
238 | } __packed; | 240 | } __packed; |
239 | 241 | ||
240 | struct ar9300_cal_data_per_freq_op_loop { | 242 | struct ar9300_cal_data_per_freq_op_loop { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index b15309caf1da..064168909108 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -16,7 +16,8 @@ | |||
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9003_mac.h" | 18 | #include "ar9003_mac.h" |
19 | #include "ar9003_initvals.h" | 19 | #include "ar9003_2p0_initvals.h" |
20 | #include "ar9003_2p2_initvals.h" | ||
20 | 21 | ||
21 | /* General hardware code for the AR9003 hadware family */ | 22 | /* General hardware code for the AR9003 hadware family */ |
22 | 23 | ||
@@ -31,12 +32,8 @@ static bool ar9003_hw_macversion_supported(u32 macversion) | |||
31 | return false; | 32 | return false; |
32 | } | 33 | } |
33 | 34 | ||
34 | /* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ | 35 | /* AR9003 2.0 */ |
35 | /* | 36 | static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah) |
36 | * XXX: move TX/RX gain INI to its own init_mode_gain_regs after | ||
37 | * ensuring it does not affect hardware bring up | ||
38 | */ | ||
39 | static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | ||
40 | { | 37 | { |
41 | /* mac */ | 38 | /* mac */ |
42 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); | 39 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); |
@@ -106,27 +103,128 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
106 | 3); | 103 | 3); |
107 | } | 104 | } |
108 | 105 | ||
106 | /* AR9003 2.2 */ | ||
107 | static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah) | ||
108 | { | ||
109 | /* mac */ | ||
110 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); | ||
111 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
112 | ar9300_2p2_mac_core, | ||
113 | ARRAY_SIZE(ar9300_2p2_mac_core), 2); | ||
114 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
115 | ar9300_2p2_mac_postamble, | ||
116 | ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); | ||
117 | |||
118 | /* bb */ | ||
119 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); | ||
120 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
121 | ar9300_2p2_baseband_core, | ||
122 | ARRAY_SIZE(ar9300_2p2_baseband_core), 2); | ||
123 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
124 | ar9300_2p2_baseband_postamble, | ||
125 | ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); | ||
126 | |||
127 | /* radio */ | ||
128 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); | ||
129 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
130 | ar9300_2p2_radio_core, | ||
131 | ARRAY_SIZE(ar9300_2p2_radio_core), 2); | ||
132 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
133 | ar9300_2p2_radio_postamble, | ||
134 | ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); | ||
135 | |||
136 | /* soc */ | ||
137 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
138 | ar9300_2p2_soc_preamble, | ||
139 | ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); | ||
140 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); | ||
141 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
142 | ar9300_2p2_soc_postamble, | ||
143 | ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); | ||
144 | |||
145 | /* rx/tx gain */ | ||
146 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
147 | ar9300Common_rx_gain_table_2p2, | ||
148 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); | ||
149 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
150 | ar9300Modes_lowest_ob_db_tx_gain_table_2p2, | ||
151 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), | ||
152 | 5); | ||
153 | |||
154 | /* Load PCIE SERDES settings from INI */ | ||
155 | |||
156 | /* Awake Setting */ | ||
157 | |||
158 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
159 | ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, | ||
160 | ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), | ||
161 | 2); | ||
162 | |||
163 | /* Sleep Setting */ | ||
164 | |||
165 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
166 | ar9300PciePhy_clkreq_enable_L1_2p2, | ||
167 | ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), | ||
168 | 2); | ||
169 | |||
170 | /* Fast clock modal settings */ | ||
171 | INIT_INI_ARRAY(&ah->iniModesAdditional, | ||
172 | ar9300Modes_fast_clock_2p2, | ||
173 | ARRAY_SIZE(ar9300Modes_fast_clock_2p2), | ||
174 | 3); | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * The AR9003 family uses a new INI format (pre, core, post | ||
179 | * arrays per subsystem). | ||
180 | */ | ||
181 | static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | ||
182 | { | ||
183 | if (AR_SREV_9300_20(ah)) | ||
184 | ar9003_2p0_hw_init_mode_regs(ah); | ||
185 | else | ||
186 | ar9003_2p2_hw_init_mode_regs(ah); | ||
187 | } | ||
188 | |||
109 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | 189 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) |
110 | { | 190 | { |
111 | switch (ar9003_hw_get_tx_gain_idx(ah)) { | 191 | switch (ar9003_hw_get_tx_gain_idx(ah)) { |
112 | case 0: | 192 | case 0: |
113 | default: | 193 | default: |
114 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 194 | if (AR_SREV_9300_20(ah)) |
115 | ar9300Modes_lowest_ob_db_tx_gain_table_2p0, | 195 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
116 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), | 196 | ar9300Modes_lowest_ob_db_tx_gain_table_2p0, |
117 | 5); | 197 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), |
198 | 5); | ||
199 | else | ||
200 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
201 | ar9300Modes_lowest_ob_db_tx_gain_table_2p2, | ||
202 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), | ||
203 | 5); | ||
118 | break; | 204 | break; |
119 | case 1: | 205 | case 1: |
120 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 206 | if (AR_SREV_9300_20(ah)) |
121 | ar9300Modes_high_ob_db_tx_gain_table_2p0, | 207 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
122 | ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), | 208 | ar9300Modes_high_ob_db_tx_gain_table_2p0, |
123 | 5); | 209 | ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), |
210 | 5); | ||
211 | else | ||
212 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
213 | ar9300Modes_high_ob_db_tx_gain_table_2p2, | ||
214 | ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), | ||
215 | 5); | ||
124 | break; | 216 | break; |
125 | case 2: | 217 | case 2: |
126 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 218 | if (AR_SREV_9300_20(ah)) |
127 | ar9300Modes_low_ob_db_tx_gain_table_2p0, | 219 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
128 | ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), | 220 | ar9300Modes_low_ob_db_tx_gain_table_2p0, |
129 | 5); | 221 | ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), |
222 | 5); | ||
223 | else | ||
224 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
225 | ar9300Modes_low_ob_db_tx_gain_table_2p2, | ||
226 | ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), | ||
227 | 5); | ||
130 | break; | 228 | break; |
131 | } | 229 | } |
132 | } | 230 | } |
@@ -136,15 +234,28 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) | |||
136 | switch (ar9003_hw_get_rx_gain_idx(ah)) { | 234 | switch (ar9003_hw_get_rx_gain_idx(ah)) { |
137 | case 0: | 235 | case 0: |
138 | default: | 236 | default: |
139 | INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p0, | 237 | if (AR_SREV_9300_20(ah)) |
140 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), | 238 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
141 | 2); | 239 | ar9300Common_rx_gain_table_2p0, |
240 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), | ||
241 | 2); | ||
242 | else | ||
243 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
244 | ar9300Common_rx_gain_table_2p2, | ||
245 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), | ||
246 | 2); | ||
142 | break; | 247 | break; |
143 | case 1: | 248 | case 1: |
144 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 249 | if (AR_SREV_9300_20(ah)) |
145 | ar9300Common_wo_xlna_rx_gain_table_2p0, | 250 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
146 | ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), | 251 | ar9300Common_wo_xlna_rx_gain_table_2p0, |
147 | 2); | 252 | ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), |
253 | 2); | ||
254 | else | ||
255 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
256 | ar9300Common_wo_xlna_rx_gain_table_2p2, | ||
257 | ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), | ||
258 | 2); | ||
148 | break; | 259 | break; |
149 | } | 260 | } |
150 | } | 261 | } |
@@ -184,6 +295,26 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, | |||
184 | /* Several PCIe massages to ensure proper behaviour */ | 295 | /* Several PCIe massages to ensure proper behaviour */ |
185 | if (ah->config.pcie_waen) | 296 | if (ah->config.pcie_waen) |
186 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); | 297 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); |
298 | else | ||
299 | REG_WRITE(ah, AR_WA, ah->WARegVal); | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Configire PCIE after Ini init. SERDES values now come from ini file | ||
304 | * This enables PCIe low power mode. | ||
305 | */ | ||
306 | if (ah->config.pcieSerDesWrite) { | ||
307 | unsigned int i; | ||
308 | struct ar5416IniArray *array; | ||
309 | |||
310 | array = power_off ? &ah->iniPcieSerdes : | ||
311 | &ah->iniPcieSerdesLowPower; | ||
312 | |||
313 | for (i = 0; i < array->ia_rows; i++) { | ||
314 | REG_WRITE(ah, | ||
315 | INI_RA(array, i, 0), | ||
316 | INI_RA(array, i, 1)); | ||
317 | } | ||
187 | } | 318 | } |
188 | } | 319 | } |
189 | 320 | ||
@@ -202,4 +333,6 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
202 | ar9003_hw_attach_phy_ops(ah); | 333 | ar9003_hw_attach_phy_ops(ah); |
203 | ar9003_hw_attach_calib_ops(ah); | 334 | ar9003_hw_attach_calib_ops(ah); |
204 | ar9003_hw_attach_mac_ops(ah); | 335 | ar9003_hw_attach_mac_ops(ah); |
336 | |||
337 | ath9k_hw_attach_ani_ops_new(ah); | ||
205 | } | 338 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 37ba37481a47..06ef71019c12 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -90,6 +90,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
90 | MAP_ISR_S2_CST); | 90 | MAP_ISR_S2_CST); |
91 | mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> | 91 | mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> |
92 | MAP_ISR_S2_TSFOOR); | 92 | MAP_ISR_S2_TSFOOR); |
93 | mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >> | ||
94 | MAP_ISR_S2_BB_WATCHDOG); | ||
93 | 95 | ||
94 | if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { | 96 | if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { |
95 | REG_WRITE(ah, AR_ISR_S2, isr2); | 97 | REG_WRITE(ah, AR_ISR_S2, isr2); |
@@ -167,6 +169,9 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
167 | 169 | ||
168 | (void) REG_READ(ah, AR_ISR); | 170 | (void) REG_READ(ah, AR_ISR); |
169 | } | 171 | } |
172 | |||
173 | if (*masked & ATH9K_INT_BB_WATCHDOG) | ||
174 | ar9003_hw_bb_watchdog_read(ah); | ||
170 | } | 175 | } |
171 | 176 | ||
172 | if (sync_cause) { | 177 | if (sync_cause) { |
@@ -465,6 +470,14 @@ static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | |||
465 | ads->ctl11 &= ~AR_VirtMoreFrag; | 470 | ads->ctl11 &= ~AR_VirtMoreFrag; |
466 | } | 471 | } |
467 | 472 | ||
473 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) | ||
474 | { | ||
475 | struct ar9003_txc *ads = ds; | ||
476 | |||
477 | ads->ctl12 |= SM(chains, AR_PAPRDChainMask); | ||
478 | } | ||
479 | EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); | ||
480 | |||
468 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 481 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
469 | { | 482 | { |
470 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 483 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index f17558b14539..f76f27d16f77 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h | |||
@@ -40,6 +40,10 @@ | |||
40 | 40 | ||
41 | #define AR_Not_Sounding 0x20000000 | 41 | #define AR_Not_Sounding 0x20000000 |
42 | 42 | ||
43 | /* ctl 12 */ | ||
44 | #define AR_PAPRDChainMask 0x00000e00 | ||
45 | #define AR_PAPRDChainMask_S 9 | ||
46 | |||
43 | #define MAP_ISR_S2_CST 6 | 47 | #define MAP_ISR_S2_CST 6 |
44 | #define MAP_ISR_S2_GTT 6 | 48 | #define MAP_ISR_S2_GTT 6 |
45 | #define MAP_ISR_S2_TIM 3 | 49 | #define MAP_ISR_S2_TIM 3 |
@@ -47,6 +51,7 @@ | |||
47 | #define MAP_ISR_S2_DTIMSYNC 7 | 51 | #define MAP_ISR_S2_DTIMSYNC 7 |
48 | #define MAP_ISR_S2_DTIM 7 | 52 | #define MAP_ISR_S2_DTIM 7 |
49 | #define MAP_ISR_S2_TSFOOR 4 | 53 | #define MAP_ISR_S2_TSFOOR 4 |
54 | #define MAP_ISR_S2_BB_WATCHDOG 6 | ||
50 | 55 | ||
51 | #define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds) | 56 | #define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds) |
52 | 57 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c new file mode 100644 index 000000000000..49e0c865ce5c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -0,0 +1,714 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "hw.h" | ||
18 | #include "ar9003_phy.h" | ||
19 | |||
20 | void ar9003_paprd_enable(struct ath_hw *ah, bool val) | ||
21 | { | ||
22 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, | ||
23 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
24 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, | ||
25 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
26 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, | ||
27 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
28 | } | ||
29 | EXPORT_SYMBOL(ar9003_paprd_enable); | ||
30 | |||
31 | static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | ||
32 | { | ||
33 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
34 | struct ar9300_modal_eep_header *hdr; | ||
35 | const u32 ctrl0[3] = { | ||
36 | AR_PHY_PAPRD_CTRL0_B0, | ||
37 | AR_PHY_PAPRD_CTRL0_B1, | ||
38 | AR_PHY_PAPRD_CTRL0_B2 | ||
39 | }; | ||
40 | const u32 ctrl1[3] = { | ||
41 | AR_PHY_PAPRD_CTRL1_B0, | ||
42 | AR_PHY_PAPRD_CTRL1_B1, | ||
43 | AR_PHY_PAPRD_CTRL1_B2 | ||
44 | }; | ||
45 | u32 am_mask, ht40_mask; | ||
46 | int i; | ||
47 | |||
48 | if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) | ||
49 | hdr = &eep->modalHeader5G; | ||
50 | else | ||
51 | hdr = &eep->modalHeader2G; | ||
52 | |||
53 | am_mask = le32_to_cpu(hdr->papdRateMaskHt20); | ||
54 | ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); | ||
55 | |||
56 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); | ||
57 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); | ||
58 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); | ||
59 | |||
60 | for (i = 0; i < 3; i++) { | ||
61 | REG_RMW_FIELD(ah, ctrl0[i], | ||
62 | AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); | ||
63 | REG_RMW_FIELD(ah, ctrl1[i], | ||
64 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1); | ||
65 | REG_RMW_FIELD(ah, ctrl1[i], | ||
66 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1); | ||
67 | REG_RMW_FIELD(ah, ctrl1[i], | ||
68 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | ||
69 | REG_RMW_FIELD(ah, ctrl1[i], | ||
70 | AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK, 181); | ||
71 | REG_RMW_FIELD(ah, ctrl1[i], | ||
72 | AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT, 361); | ||
73 | REG_RMW_FIELD(ah, ctrl1[i], | ||
74 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | ||
75 | REG_RMW_FIELD(ah, ctrl0[i], | ||
76 | AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH, 3); | ||
77 | } | ||
78 | |||
79 | ar9003_paprd_enable(ah, false); | ||
80 | |||
81 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
82 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30); | ||
83 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
84 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1); | ||
85 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
86 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1); | ||
87 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
88 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0); | ||
89 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
90 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0); | ||
91 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
92 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28); | ||
93 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
94 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1); | ||
95 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2, | ||
96 | AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147); | ||
97 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
98 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4); | ||
99 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
100 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4); | ||
101 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
102 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); | ||
103 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
104 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); | ||
105 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
106 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6); | ||
107 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
108 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, | ||
109 | -15); | ||
110 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
111 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1); | ||
112 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
113 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0); | ||
114 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
115 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400); | ||
116 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
117 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES, | ||
118 | 100); | ||
119 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0, | ||
120 | AR_PHY_PAPRD_PRE_POST_SCALING, 261376); | ||
121 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0, | ||
122 | AR_PHY_PAPRD_PRE_POST_SCALING, 248079); | ||
123 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0, | ||
124 | AR_PHY_PAPRD_PRE_POST_SCALING, 233759); | ||
125 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0, | ||
126 | AR_PHY_PAPRD_PRE_POST_SCALING, 220464); | ||
127 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0, | ||
128 | AR_PHY_PAPRD_PRE_POST_SCALING, 208194); | ||
129 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0, | ||
130 | AR_PHY_PAPRD_PRE_POST_SCALING, 196949); | ||
131 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0, | ||
132 | AR_PHY_PAPRD_PRE_POST_SCALING, 185706); | ||
133 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, | ||
134 | AR_PHY_PAPRD_PRE_POST_SCALING, 175487); | ||
135 | } | ||
136 | |||
137 | static void ar9003_paprd_get_gain_table(struct ath_hw *ah) | ||
138 | { | ||
139 | u32 *entry = ah->paprd_gain_table_entries; | ||
140 | u8 *index = ah->paprd_gain_table_index; | ||
141 | u32 reg = AR_PHY_TXGAIN_TABLE; | ||
142 | int i; | ||
143 | |||
144 | memset(entry, 0, sizeof(ah->paprd_gain_table_entries)); | ||
145 | memset(index, 0, sizeof(ah->paprd_gain_table_index)); | ||
146 | |||
147 | for (i = 0; i < 32; i++) { | ||
148 | entry[i] = REG_READ(ah, reg); | ||
149 | index[i] = (entry[i] >> 24) & 0xff; | ||
150 | reg += 4; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain, | ||
155 | int target_power) | ||
156 | { | ||
157 | int olpc_gain_delta = 0; | ||
158 | int alpha_therm, alpha_volt; | ||
159 | int therm_cal_value, volt_cal_value; | ||
160 | int therm_value, volt_value; | ||
161 | int thermal_gain_corr, voltage_gain_corr; | ||
162 | int desired_scale, desired_gain = 0; | ||
163 | u32 reg; | ||
164 | |||
165 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
166 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
167 | desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12, | ||
168 | AR_PHY_TPC_12_DESIRED_SCALE_HT40_5); | ||
169 | alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19, | ||
170 | AR_PHY_TPC_19_ALPHA_THERM); | ||
171 | alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19, | ||
172 | AR_PHY_TPC_19_ALPHA_VOLT); | ||
173 | therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, | ||
174 | AR_PHY_TPC_18_THERM_CAL_VALUE); | ||
175 | volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, | ||
176 | AR_PHY_TPC_18_VOLT_CAL_VALUE); | ||
177 | therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, | ||
178 | AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE); | ||
179 | volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, | ||
180 | AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE); | ||
181 | |||
182 | if (chain == 0) | ||
183 | reg = AR_PHY_TPC_11_B0; | ||
184 | else if (chain == 1) | ||
185 | reg = AR_PHY_TPC_11_B1; | ||
186 | else | ||
187 | reg = AR_PHY_TPC_11_B2; | ||
188 | |||
189 | olpc_gain_delta = REG_READ_FIELD(ah, reg, | ||
190 | AR_PHY_TPC_11_OLPC_GAIN_DELTA); | ||
191 | |||
192 | if (olpc_gain_delta >= 128) | ||
193 | olpc_gain_delta = olpc_gain_delta - 256; | ||
194 | |||
195 | thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) + | ||
196 | (256 / 2)) / 256; | ||
197 | voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) + | ||
198 | (128 / 2)) / 128; | ||
199 | desired_gain = target_power - olpc_gain_delta - thermal_gain_corr - | ||
200 | voltage_gain_corr + desired_scale; | ||
201 | |||
202 | return desired_gain; | ||
203 | } | ||
204 | |||
205 | static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index) | ||
206 | { | ||
207 | int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain; | ||
208 | int padrvgnA, padrvgnB, padrvgnC, padrvgnD; | ||
209 | u32 *gain_table_entries = ah->paprd_gain_table_entries; | ||
210 | |||
211 | selected_gain_entry = gain_table_entries[gain_index]; | ||
212 | txbb1dbgain = selected_gain_entry & 0x7; | ||
213 | txbb6dbgain = (selected_gain_entry >> 3) & 0x3; | ||
214 | txmxrgain = (selected_gain_entry >> 5) & 0xf; | ||
215 | padrvgnA = (selected_gain_entry >> 9) & 0xf; | ||
216 | padrvgnB = (selected_gain_entry >> 13) & 0xf; | ||
217 | padrvgnC = (selected_gain_entry >> 17) & 0xf; | ||
218 | padrvgnD = (selected_gain_entry >> 21) & 0x3; | ||
219 | |||
220 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
221 | AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain); | ||
222 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
223 | AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain); | ||
224 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
225 | AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain); | ||
226 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
227 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgnA); | ||
228 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
229 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgnB); | ||
230 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
231 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgnC); | ||
232 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
233 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgnD); | ||
234 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
235 | AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0); | ||
236 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
237 | AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0); | ||
238 | REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0); | ||
239 | REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0); | ||
240 | } | ||
241 | |||
242 | static inline int find_expn(int num) | ||
243 | { | ||
244 | return fls(num) - 1; | ||
245 | } | ||
246 | |||
247 | static inline int find_proper_scale(int expn, int N) | ||
248 | { | ||
249 | return (expn > N) ? expn - 10 : 0; | ||
250 | } | ||
251 | |||
252 | #define NUM_BIN 23 | ||
253 | |||
254 | static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | ||
255 | { | ||
256 | unsigned int thresh_accum_cnt; | ||
257 | int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1]; | ||
258 | int PA_in[NUM_BIN + 1]; | ||
259 | int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1]; | ||
260 | unsigned int B1_abs_max, B2_abs_max; | ||
261 | int max_index, scale_factor; | ||
262 | int y_est[NUM_BIN + 1]; | ||
263 | int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1]; | ||
264 | unsigned int x_tilde_abs; | ||
265 | int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad; | ||
266 | int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B; | ||
267 | int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2; | ||
268 | int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem; | ||
269 | int y5, y3, tmp; | ||
270 | int theta_low_bin = 0; | ||
271 | int i; | ||
272 | |||
273 | /* disregard any bin that contains <= 16 samples */ | ||
274 | thresh_accum_cnt = 16; | ||
275 | scale_factor = 5; | ||
276 | max_index = 0; | ||
277 | memset(theta, 0, sizeof(theta)); | ||
278 | memset(x_est, 0, sizeof(x_est)); | ||
279 | memset(Y, 0, sizeof(Y)); | ||
280 | memset(y_est, 0, sizeof(y_est)); | ||
281 | memset(x_tilde, 0, sizeof(x_tilde)); | ||
282 | |||
283 | for (i = 0; i < NUM_BIN; i++) { | ||
284 | s32 accum_cnt, accum_tx, accum_rx, accum_ang; | ||
285 | |||
286 | /* number of samples */ | ||
287 | accum_cnt = data_L[i] & 0xffff; | ||
288 | |||
289 | if (accum_cnt <= thresh_accum_cnt) | ||
290 | continue; | ||
291 | |||
292 | /* sum(tx amplitude) */ | ||
293 | accum_tx = ((data_L[i] >> 16) & 0xffff) | | ||
294 | ((data_U[i] & 0x7ff) << 16); | ||
295 | |||
296 | /* sum(rx amplitude distance to lower bin edge) */ | ||
297 | accum_rx = ((data_U[i] >> 11) & 0x1f) | | ||
298 | ((data_L[i + 23] & 0xffff) << 5); | ||
299 | |||
300 | /* sum(angles) */ | ||
301 | accum_ang = ((data_L[i + 23] >> 16) & 0xffff) | | ||
302 | ((data_U[i + 23] & 0x7ff) << 16); | ||
303 | |||
304 | accum_tx <<= scale_factor; | ||
305 | accum_rx <<= scale_factor; | ||
306 | x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >> | ||
307 | scale_factor; | ||
308 | |||
309 | Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >> | ||
310 | scale_factor) + | ||
311 | (1 << scale_factor) * max_index + 16; | ||
312 | |||
313 | if (accum_ang >= (1 << 26)) | ||
314 | accum_ang -= 1 << 27; | ||
315 | |||
316 | theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) / | ||
317 | accum_cnt; | ||
318 | |||
319 | max_index++; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Find average theta of first 5 bin and all of those to same value. | ||
324 | * Curve is linear at that range. | ||
325 | */ | ||
326 | for (i = 1; i < 6; i++) | ||
327 | theta_low_bin += theta[i]; | ||
328 | |||
329 | theta_low_bin = theta_low_bin / 5; | ||
330 | for (i = 1; i < 6; i++) | ||
331 | theta[i] = theta_low_bin; | ||
332 | |||
333 | /* Set values at origin */ | ||
334 | theta[0] = theta_low_bin; | ||
335 | for (i = 0; i <= max_index; i++) | ||
336 | theta[i] -= theta_low_bin; | ||
337 | |||
338 | x_est[0] = 0; | ||
339 | Y[0] = 0; | ||
340 | scale_factor = 8; | ||
341 | |||
342 | /* low signal gain */ | ||
343 | if (x_est[6] == x_est[3]) | ||
344 | return false; | ||
345 | |||
346 | G_fxp = | ||
347 | (((Y[6] - Y[3]) * 1 << scale_factor) + | ||
348 | (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]); | ||
349 | |||
350 | Y_intercept = | ||
351 | (G_fxp * (x_est[0] - x_est[3]) + | ||
352 | (1 << scale_factor)) / (1 << scale_factor) + Y[3]; | ||
353 | |||
354 | for (i = 0; i <= max_index; i++) | ||
355 | y_est[i] = Y[i] - Y_intercept; | ||
356 | |||
357 | for (i = 0; i <= 3; i++) { | ||
358 | y_est[i] = i * 32; | ||
359 | |||
360 | /* prevent division by zero */ | ||
361 | if (G_fxp == 0) | ||
362 | return false; | ||
363 | |||
364 | x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp; | ||
365 | } | ||
366 | |||
367 | x_est_fxp1_nonlin = | ||
368 | x_est[max_index] - ((1 << scale_factor) * y_est[max_index] + | ||
369 | G_fxp) / G_fxp; | ||
370 | |||
371 | order_x_by_y = | ||
372 | (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index]; | ||
373 | |||
374 | if (order_x_by_y == 0) | ||
375 | M = 10; | ||
376 | else if (order_x_by_y == 1) | ||
377 | M = 9; | ||
378 | else | ||
379 | M = 8; | ||
380 | |||
381 | I = (max_index > 15) ? 7 : max_index >> 1; | ||
382 | L = max_index - I; | ||
383 | scale_factor = 8; | ||
384 | sum_y_sqr = 0; | ||
385 | sum_y_quad = 0; | ||
386 | x_tilde_abs = 0; | ||
387 | |||
388 | for (i = 0; i <= L; i++) { | ||
389 | unsigned int y_sqr; | ||
390 | unsigned int y_quad; | ||
391 | unsigned int tmp_abs; | ||
392 | |||
393 | /* prevent division by zero */ | ||
394 | if (y_est[i + I] == 0) | ||
395 | return false; | ||
396 | |||
397 | x_est_fxp1_nonlin = | ||
398 | x_est[i + I] - ((1 << scale_factor) * y_est[i + I] + | ||
399 | G_fxp) / G_fxp; | ||
400 | |||
401 | x_tilde[i] = | ||
402 | (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i + | ||
403 | I]; | ||
404 | x_tilde[i] = | ||
405 | (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; | ||
406 | x_tilde[i] = | ||
407 | (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; | ||
408 | y_sqr = | ||
409 | (y_est[i + I] * y_est[i + I] + | ||
410 | (scale_factor * scale_factor)) / (scale_factor * | ||
411 | scale_factor); | ||
412 | tmp_abs = abs(x_tilde[i]); | ||
413 | if (tmp_abs > x_tilde_abs) | ||
414 | x_tilde_abs = tmp_abs; | ||
415 | |||
416 | y_quad = y_sqr * y_sqr; | ||
417 | sum_y_sqr = sum_y_sqr + y_sqr; | ||
418 | sum_y_quad = sum_y_quad + y_quad; | ||
419 | B1_tmp[i] = y_sqr * (L + 1); | ||
420 | B2_tmp[i] = y_sqr; | ||
421 | } | ||
422 | |||
423 | B1_abs_max = 0; | ||
424 | B2_abs_max = 0; | ||
425 | for (i = 0; i <= L; i++) { | ||
426 | int abs_val; | ||
427 | |||
428 | B1_tmp[i] -= sum_y_sqr; | ||
429 | B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i]; | ||
430 | |||
431 | abs_val = abs(B1_tmp[i]); | ||
432 | if (abs_val > B1_abs_max) | ||
433 | B1_abs_max = abs_val; | ||
434 | |||
435 | abs_val = abs(B2_tmp[i]); | ||
436 | if (abs_val > B2_abs_max) | ||
437 | B2_abs_max = abs_val; | ||
438 | } | ||
439 | |||
440 | Q_x = find_proper_scale(find_expn(x_tilde_abs), 10); | ||
441 | Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10); | ||
442 | Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10); | ||
443 | |||
444 | beta_raw = 0; | ||
445 | alpha_raw = 0; | ||
446 | for (i = 0; i <= L; i++) { | ||
447 | x_tilde[i] = x_tilde[i] / (1 << Q_x); | ||
448 | B1_tmp[i] = B1_tmp[i] / (1 << Q_B1); | ||
449 | B2_tmp[i] = B2_tmp[i] / (1 << Q_B2); | ||
450 | beta_raw = beta_raw + B1_tmp[i] * x_tilde[i]; | ||
451 | alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i]; | ||
452 | } | ||
453 | |||
454 | scale_B = | ||
455 | ((sum_y_quad / scale_factor) * (L + 1) - | ||
456 | (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor; | ||
457 | |||
458 | Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10); | ||
459 | scale_B = scale_B / (1 << Q_scale_B); | ||
460 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | ||
461 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | ||
462 | beta_raw = beta_raw / (1 << Q_beta); | ||
463 | alpha_raw = alpha_raw / (1 << Q_alpha); | ||
464 | alpha = (alpha_raw << 10) / scale_B; | ||
465 | beta = (beta_raw << 10) / scale_B; | ||
466 | order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B; | ||
467 | order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B; | ||
468 | order1_5x = order_1 / 5; | ||
469 | order2_3x = order_2 / 3; | ||
470 | order1_5x_rem = order_1 - 5 * order1_5x; | ||
471 | order2_3x_rem = order_2 - 3 * order2_3x; | ||
472 | |||
473 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
474 | tmp = i * 32; | ||
475 | y5 = ((beta * tmp) >> 6) >> order1_5x; | ||
476 | y5 = (y5 * tmp) >> order1_5x; | ||
477 | y5 = (y5 * tmp) >> order1_5x; | ||
478 | y5 = (y5 * tmp) >> order1_5x; | ||
479 | y5 = (y5 * tmp) >> order1_5x; | ||
480 | y5 = y5 >> order1_5x_rem; | ||
481 | y3 = (alpha * tmp) >> order2_3x; | ||
482 | y3 = (y3 * tmp) >> order2_3x; | ||
483 | y3 = (y3 * tmp) >> order2_3x; | ||
484 | y3 = y3 >> order2_3x_rem; | ||
485 | PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp; | ||
486 | |||
487 | if (i >= 2) { | ||
488 | tmp = PA_in[i] - PA_in[i - 1]; | ||
489 | if (tmp < 0) | ||
490 | PA_in[i] = | ||
491 | PA_in[i - 1] + (PA_in[i - 1] - | ||
492 | PA_in[i - 2]); | ||
493 | } | ||
494 | |||
495 | PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400; | ||
496 | } | ||
497 | |||
498 | beta_raw = 0; | ||
499 | alpha_raw = 0; | ||
500 | |||
501 | for (i = 0; i <= L; i++) { | ||
502 | int theta_tilde = | ||
503 | ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I]; | ||
504 | theta_tilde = | ||
505 | ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; | ||
506 | theta_tilde = | ||
507 | ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; | ||
508 | beta_raw = beta_raw + B1_tmp[i] * theta_tilde; | ||
509 | alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde; | ||
510 | } | ||
511 | |||
512 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | ||
513 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | ||
514 | beta_raw = beta_raw / (1 << Q_beta); | ||
515 | alpha_raw = alpha_raw / (1 << Q_alpha); | ||
516 | |||
517 | alpha = (alpha_raw << 10) / scale_B; | ||
518 | beta = (beta_raw << 10) / scale_B; | ||
519 | order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5; | ||
520 | order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5; | ||
521 | order1_5x = order_1 / 5; | ||
522 | order2_3x = order_2 / 3; | ||
523 | order1_5x_rem = order_1 - 5 * order1_5x; | ||
524 | order2_3x_rem = order_2 - 3 * order2_3x; | ||
525 | |||
526 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
527 | int PA_angle; | ||
528 | |||
529 | /* pa_table[4] is calculated from PA_angle for i=5 */ | ||
530 | if (i == 4) | ||
531 | continue; | ||
532 | |||
533 | tmp = i * 32; | ||
534 | if (beta > 0) | ||
535 | y5 = (((beta * tmp - 64) >> 6) - | ||
536 | (1 << order1_5x)) / (1 << order1_5x); | ||
537 | else | ||
538 | y5 = ((((beta * tmp - 64) >> 6) + | ||
539 | (1 << order1_5x)) / (1 << order1_5x)); | ||
540 | |||
541 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
542 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
543 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
544 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
545 | y5 = y5 / (1 << order1_5x_rem); | ||
546 | |||
547 | if (beta > 0) | ||
548 | y3 = (alpha * tmp - | ||
549 | (1 << order2_3x)) / (1 << order2_3x); | ||
550 | else | ||
551 | y3 = (alpha * tmp + | ||
552 | (1 << order2_3x)) / (1 << order2_3x); | ||
553 | y3 = (y3 * tmp) / (1 << order2_3x); | ||
554 | y3 = (y3 * tmp) / (1 << order2_3x); | ||
555 | y3 = y3 / (1 << order2_3x_rem); | ||
556 | |||
557 | if (i < 4) { | ||
558 | PA_angle = 0; | ||
559 | } else { | ||
560 | PA_angle = y5 + y3; | ||
561 | if (PA_angle < -150) | ||
562 | PA_angle = -150; | ||
563 | else if (PA_angle > 150) | ||
564 | PA_angle = 150; | ||
565 | } | ||
566 | |||
567 | pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff); | ||
568 | if (i == 5) { | ||
569 | PA_angle = (PA_angle + 2) >> 1; | ||
570 | pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) + | ||
571 | (PA_angle & 0x7ff); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | *gain = G_fxp; | ||
576 | return true; | ||
577 | } | ||
578 | |||
579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | ||
580 | struct ath9k_channel *chan, int chain) | ||
581 | { | ||
582 | u32 *paprd_table_val = chan->pa_table[chain]; | ||
583 | u32 small_signal_gain = chan->small_signal_gain[chain]; | ||
584 | u32 training_power; | ||
585 | u32 reg = 0; | ||
586 | int i; | ||
587 | |||
588 | training_power = | ||
589 | REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
590 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
591 | training_power -= 4; | ||
592 | |||
593 | if (chain == 0) | ||
594 | reg = AR_PHY_PAPRD_MEM_TAB_B0; | ||
595 | else if (chain == 1) | ||
596 | reg = AR_PHY_PAPRD_MEM_TAB_B1; | ||
597 | else if (chain == 2) | ||
598 | reg = AR_PHY_PAPRD_MEM_TAB_B2; | ||
599 | |||
600 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
601 | REG_WRITE(ah, reg, paprd_table_val[i]); | ||
602 | reg = reg + 4; | ||
603 | } | ||
604 | |||
605 | if (chain == 0) | ||
606 | reg = AR_PHY_PA_GAIN123_B0; | ||
607 | else if (chain == 1) | ||
608 | reg = AR_PHY_PA_GAIN123_B1; | ||
609 | else | ||
610 | reg = AR_PHY_PA_GAIN123_B2; | ||
611 | |||
612 | REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain); | ||
613 | |||
614 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B0, | ||
615 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
616 | training_power); | ||
617 | |||
618 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, | ||
619 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
620 | training_power); | ||
621 | |||
622 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, | ||
623 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
624 | training_power); | ||
625 | } | ||
626 | EXPORT_SYMBOL(ar9003_paprd_populate_single_table); | ||
627 | |||
628 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | ||
629 | { | ||
630 | |||
631 | unsigned int i, desired_gain, gain_index; | ||
632 | unsigned int train_power; | ||
633 | |||
634 | train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
635 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
636 | |||
637 | train_power = train_power - 4; | ||
638 | |||
639 | desired_gain = ar9003_get_desired_gain(ah, chain, train_power); | ||
640 | |||
641 | gain_index = 0; | ||
642 | for (i = 0; i < 32; i++) { | ||
643 | if (ah->paprd_gain_table_index[i] >= desired_gain) | ||
644 | break; | ||
645 | gain_index++; | ||
646 | } | ||
647 | |||
648 | ar9003_tx_force_gain(ah, gain_index); | ||
649 | |||
650 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
651 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); | ||
656 | |||
657 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | ||
658 | int chain) | ||
659 | { | ||
660 | u16 *small_signal_gain = &chan->small_signal_gain[chain]; | ||
661 | u32 *pa_table = chan->pa_table[chain]; | ||
662 | u32 *data_L, *data_U; | ||
663 | int i, status = 0; | ||
664 | u32 *buf; | ||
665 | u32 reg; | ||
666 | |||
667 | memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); | ||
668 | |||
669 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); | ||
670 | if (!buf) | ||
671 | return -ENOMEM; | ||
672 | |||
673 | data_L = &buf[0]; | ||
674 | data_U = &buf[48]; | ||
675 | |||
676 | REG_CLR_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, | ||
677 | AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); | ||
678 | |||
679 | reg = AR_PHY_CHAN_INFO_TAB_0; | ||
680 | for (i = 0; i < 48; i++) | ||
681 | data_L[i] = REG_READ(ah, reg + (i << 2)); | ||
682 | |||
683 | REG_SET_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, | ||
684 | AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); | ||
685 | |||
686 | for (i = 0; i < 48; i++) | ||
687 | data_U[i] = REG_READ(ah, reg + (i << 2)); | ||
688 | |||
689 | if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) | ||
690 | status = -2; | ||
691 | |||
692 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
693 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
694 | |||
695 | kfree(buf); | ||
696 | |||
697 | return status; | ||
698 | } | ||
699 | EXPORT_SYMBOL(ar9003_paprd_create_curve); | ||
700 | |||
701 | int ar9003_paprd_init_table(struct ath_hw *ah) | ||
702 | { | ||
703 | ar9003_paprd_setup_single_table(ah); | ||
704 | ar9003_paprd_get_gain_table(ah); | ||
705 | return 0; | ||
706 | } | ||
707 | EXPORT_SYMBOL(ar9003_paprd_init_table); | ||
708 | |||
709 | bool ar9003_paprd_is_done(struct ath_hw *ah) | ||
710 | { | ||
711 | return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
712 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
713 | } | ||
714 | EXPORT_SYMBOL(ar9003_paprd_is_done); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 80431a2f6dc1..19bc05c41136 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -17,6 +17,28 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9003_phy.h" | 18 | #include "ar9003_phy.h" |
19 | 19 | ||
20 | static const int firstep_table[] = | ||
21 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
22 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ | ||
23 | |||
24 | static const int cycpwrThr1_table[] = | ||
25 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
26 | { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ | ||
27 | |||
28 | /* | ||
29 | * register values to turn OFDM weak signal detection OFF | ||
30 | */ | ||
31 | static const int m1ThreshLow_off = 127; | ||
32 | static const int m2ThreshLow_off = 127; | ||
33 | static const int m1Thresh_off = 127; | ||
34 | static const int m2Thresh_off = 127; | ||
35 | static const int m2CountThr_off = 31; | ||
36 | static const int m2CountThrLow_off = 63; | ||
37 | static const int m1ThreshLowExt_off = 127; | ||
38 | static const int m2ThreshLowExt_off = 127; | ||
39 | static const int m1ThreshExt_off = 127; | ||
40 | static const int m2ThreshExt_off = 127; | ||
41 | |||
20 | /** | 42 | /** |
21 | * ar9003_hw_set_channel - set channel on single-chip device | 43 | * ar9003_hw_set_channel - set channel on single-chip device |
22 | * @ah: atheros hardware structure | 44 | * @ah: atheros hardware structure |
@@ -94,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
94 | } | 116 | } |
95 | 117 | ||
96 | /** | 118 | /** |
97 | * ar9003_hw_spur_mitigate - convert baseband spur frequency | 119 | * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency |
98 | * @ah: atheros hardware structure | 120 | * @ah: atheros hardware structure |
99 | * @chan: | 121 | * @chan: |
100 | * | 122 | * |
@@ -521,15 +543,6 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, | |||
521 | u32 val = INI_RA(iniArr, i, column); | 543 | u32 val = INI_RA(iniArr, i, column); |
522 | 544 | ||
523 | REG_WRITE(ah, reg, val); | 545 | REG_WRITE(ah, reg, val); |
524 | |||
525 | /* | ||
526 | * Determine if this is a shift register value, and insert the | ||
527 | * configured delay if so. | ||
528 | */ | ||
529 | if (reg >= 0x16000 && reg < 0x17000 | ||
530 | && ah->config.analog_shiftreg) | ||
531 | udelay(100); | ||
532 | |||
533 | DO_DELAY(regWrites); | 546 | DO_DELAY(regWrites); |
534 | } | 547 | } |
535 | } | 548 | } |
@@ -732,71 +745,68 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
732 | { | 745 | { |
733 | struct ar5416AniState *aniState = ah->curani; | 746 | struct ar5416AniState *aniState = ah->curani; |
734 | struct ath_common *common = ath9k_hw_common(ah); | 747 | struct ath_common *common = ath9k_hw_common(ah); |
748 | struct ath9k_channel *chan = ah->curchan; | ||
749 | s32 value, value2; | ||
735 | 750 | ||
736 | switch (cmd & ah->ani_function) { | 751 | switch (cmd & ah->ani_function) { |
737 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ | ||
738 | u32 level = param; | ||
739 | |||
740 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { | ||
741 | ath_print(common, ATH_DBG_ANI, | ||
742 | "level out of range (%u > %u)\n", | ||
743 | level, | ||
744 | (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); | ||
745 | return false; | ||
746 | } | ||
747 | |||
748 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
749 | AR_PHY_DESIRED_SZ_TOT_DES, | ||
750 | ah->totalSizeDesired[level]); | ||
751 | REG_RMW_FIELD(ah, AR_PHY_AGC, | ||
752 | AR_PHY_AGC_COARSE_LOW, | ||
753 | ah->coarse_low[level]); | ||
754 | REG_RMW_FIELD(ah, AR_PHY_AGC, | ||
755 | AR_PHY_AGC_COARSE_HIGH, | ||
756 | ah->coarse_high[level]); | ||
757 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
758 | AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]); | ||
759 | |||
760 | if (level > aniState->noiseImmunityLevel) | ||
761 | ah->stats.ast_ani_niup++; | ||
762 | else if (level < aniState->noiseImmunityLevel) | ||
763 | ah->stats.ast_ani_nidown++; | ||
764 | aniState->noiseImmunityLevel = level; | ||
765 | break; | ||
766 | } | ||
767 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | 752 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ |
768 | const int m1ThreshLow[] = { 127, 50 }; | 753 | /* |
769 | const int m2ThreshLow[] = { 127, 40 }; | 754 | * on == 1 means ofdm weak signal detection is ON |
770 | const int m1Thresh[] = { 127, 0x4d }; | 755 | * on == 1 is the default, for less noise immunity |
771 | const int m2Thresh[] = { 127, 0x40 }; | 756 | * |
772 | const int m2CountThr[] = { 31, 16 }; | 757 | * on == 0 means ofdm weak signal detection is OFF |
773 | const int m2CountThrLow[] = { 63, 48 }; | 758 | * on == 0 means more noise imm |
759 | */ | ||
774 | u32 on = param ? 1 : 0; | 760 | u32 on = param ? 1 : 0; |
761 | /* | ||
762 | * make register setting for default | ||
763 | * (weak sig detect ON) come from INI file | ||
764 | */ | ||
765 | int m1ThreshLow = on ? | ||
766 | aniState->iniDef.m1ThreshLow : m1ThreshLow_off; | ||
767 | int m2ThreshLow = on ? | ||
768 | aniState->iniDef.m2ThreshLow : m2ThreshLow_off; | ||
769 | int m1Thresh = on ? | ||
770 | aniState->iniDef.m1Thresh : m1Thresh_off; | ||
771 | int m2Thresh = on ? | ||
772 | aniState->iniDef.m2Thresh : m2Thresh_off; | ||
773 | int m2CountThr = on ? | ||
774 | aniState->iniDef.m2CountThr : m2CountThr_off; | ||
775 | int m2CountThrLow = on ? | ||
776 | aniState->iniDef.m2CountThrLow : m2CountThrLow_off; | ||
777 | int m1ThreshLowExt = on ? | ||
778 | aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; | ||
779 | int m2ThreshLowExt = on ? | ||
780 | aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; | ||
781 | int m1ThreshExt = on ? | ||
782 | aniState->iniDef.m1ThreshExt : m1ThreshExt_off; | ||
783 | int m2ThreshExt = on ? | ||
784 | aniState->iniDef.m2ThreshExt : m2ThreshExt_off; | ||
775 | 785 | ||
776 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 786 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
777 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | 787 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, |
778 | m1ThreshLow[on]); | 788 | m1ThreshLow); |
779 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 789 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
780 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | 790 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, |
781 | m2ThreshLow[on]); | 791 | m2ThreshLow); |
782 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | 792 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, |
783 | AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); | 793 | AR_PHY_SFCORR_M1_THRESH, m1Thresh); |
784 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | 794 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, |
785 | AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); | 795 | AR_PHY_SFCORR_M2_THRESH, m2Thresh); |
786 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | 796 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, |
787 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); | 797 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); |
788 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 798 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
789 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | 799 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, |
790 | m2CountThrLow[on]); | 800 | m2CountThrLow); |
791 | 801 | ||
792 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 802 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
793 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); | 803 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); |
794 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 804 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
795 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); | 805 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); |
796 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 806 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
797 | AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); | 807 | AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); |
798 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 808 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
799 | AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); | 809 | AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); |
800 | 810 | ||
801 | if (on) | 811 | if (on) |
802 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | 812 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, |
@@ -806,6 +816,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
806 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 816 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
807 | 817 | ||
808 | if (!on != aniState->ofdmWeakSigDetectOff) { | 818 | if (!on != aniState->ofdmWeakSigDetectOff) { |
819 | ath_print(common, ATH_DBG_ANI, | ||
820 | "** ch %d: ofdm weak signal: %s=>%s\n", | ||
821 | chan->channel, | ||
822 | !aniState->ofdmWeakSigDetectOff ? | ||
823 | "on" : "off", | ||
824 | on ? "on" : "off"); | ||
809 | if (on) | 825 | if (on) |
810 | ah->stats.ast_ani_ofdmon++; | 826 | ah->stats.ast_ani_ofdmon++; |
811 | else | 827 | else |
@@ -814,64 +830,167 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
814 | } | 830 | } |
815 | break; | 831 | break; |
816 | } | 832 | } |
817 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ | ||
818 | const int weakSigThrCck[] = { 8, 6 }; | ||
819 | u32 high = param ? 1 : 0; | ||
820 | |||
821 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, | ||
822 | AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, | ||
823 | weakSigThrCck[high]); | ||
824 | if (high != aniState->cckWeakSigThreshold) { | ||
825 | if (high) | ||
826 | ah->stats.ast_ani_cckhigh++; | ||
827 | else | ||
828 | ah->stats.ast_ani_ccklow++; | ||
829 | aniState->cckWeakSigThreshold = high; | ||
830 | } | ||
831 | break; | ||
832 | } | ||
833 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | 833 | case ATH9K_ANI_FIRSTEP_LEVEL:{ |
834 | const int firstep[] = { 0, 4, 8 }; | ||
835 | u32 level = param; | 834 | u32 level = param; |
836 | 835 | ||
837 | if (level >= ARRAY_SIZE(firstep)) { | 836 | if (level >= ARRAY_SIZE(firstep_table)) { |
838 | ath_print(common, ATH_DBG_ANI, | 837 | ath_print(common, ATH_DBG_ANI, |
839 | "level out of range (%u > %u)\n", | 838 | "ATH9K_ANI_FIRSTEP_LEVEL: level " |
839 | "out of range (%u > %u)\n", | ||
840 | level, | 840 | level, |
841 | (unsigned) ARRAY_SIZE(firstep)); | 841 | (unsigned) ARRAY_SIZE(firstep_table)); |
842 | return false; | 842 | return false; |
843 | } | 843 | } |
844 | |||
845 | /* | ||
846 | * make register setting relative to default | ||
847 | * from INI file & cap value | ||
848 | */ | ||
849 | value = firstep_table[level] - | ||
850 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
851 | aniState->iniDef.firstep; | ||
852 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
853 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
854 | if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
855 | value = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
844 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | 856 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, |
845 | AR_PHY_FIND_SIG_FIRSTEP, | 857 | AR_PHY_FIND_SIG_FIRSTEP, |
846 | firstep[level]); | 858 | value); |
847 | if (level > aniState->firstepLevel) | 859 | /* |
848 | ah->stats.ast_ani_stepup++; | 860 | * we need to set first step low register too |
849 | else if (level < aniState->firstepLevel) | 861 | * make register setting relative to default |
850 | ah->stats.ast_ani_stepdown++; | 862 | * from INI file & cap value |
851 | aniState->firstepLevel = level; | 863 | */ |
864 | value2 = firstep_table[level] - | ||
865 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
866 | aniState->iniDef.firstepLow; | ||
867 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
868 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
869 | if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
870 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
871 | |||
872 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, | ||
873 | AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); | ||
874 | |||
875 | if (level != aniState->firstepLevel) { | ||
876 | ath_print(common, ATH_DBG_ANI, | ||
877 | "** ch %d: level %d=>%d[def:%d] " | ||
878 | "firstep[level]=%d ini=%d\n", | ||
879 | chan->channel, | ||
880 | aniState->firstepLevel, | ||
881 | level, | ||
882 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
883 | value, | ||
884 | aniState->iniDef.firstep); | ||
885 | ath_print(common, ATH_DBG_ANI, | ||
886 | "** ch %d: level %d=>%d[def:%d] " | ||
887 | "firstep_low[level]=%d ini=%d\n", | ||
888 | chan->channel, | ||
889 | aniState->firstepLevel, | ||
890 | level, | ||
891 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
892 | value2, | ||
893 | aniState->iniDef.firstepLow); | ||
894 | if (level > aniState->firstepLevel) | ||
895 | ah->stats.ast_ani_stepup++; | ||
896 | else if (level < aniState->firstepLevel) | ||
897 | ah->stats.ast_ani_stepdown++; | ||
898 | aniState->firstepLevel = level; | ||
899 | } | ||
852 | break; | 900 | break; |
853 | } | 901 | } |
854 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | 902 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ |
855 | const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
856 | u32 level = param; | 903 | u32 level = param; |
857 | 904 | ||
858 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | 905 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { |
859 | ath_print(common, ATH_DBG_ANI, | 906 | ath_print(common, ATH_DBG_ANI, |
860 | "level out of range (%u > %u)\n", | 907 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " |
908 | "out of range (%u > %u)\n", | ||
861 | level, | 909 | level, |
862 | (unsigned) ARRAY_SIZE(cycpwrThr1)); | 910 | (unsigned) ARRAY_SIZE(cycpwrThr1_table)); |
863 | return false; | 911 | return false; |
864 | } | 912 | } |
913 | /* | ||
914 | * make register setting relative to default | ||
915 | * from INI file & cap value | ||
916 | */ | ||
917 | value = cycpwrThr1_table[level] - | ||
918 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
919 | aniState->iniDef.cycpwrThr1; | ||
920 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
921 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
922 | if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
923 | value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
865 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | 924 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, |
866 | AR_PHY_TIMING5_CYCPWR_THR1, | 925 | AR_PHY_TIMING5_CYCPWR_THR1, |
867 | cycpwrThr1[level]); | 926 | value); |
868 | if (level > aniState->spurImmunityLevel) | 927 | |
869 | ah->stats.ast_ani_spurup++; | 928 | /* |
870 | else if (level < aniState->spurImmunityLevel) | 929 | * set AR_PHY_EXT_CCA for extension channel |
871 | ah->stats.ast_ani_spurdown++; | 930 | * make register setting relative to default |
872 | aniState->spurImmunityLevel = level; | 931 | * from INI file & cap value |
932 | */ | ||
933 | value2 = cycpwrThr1_table[level] - | ||
934 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
935 | aniState->iniDef.cycpwrThr1Ext; | ||
936 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
937 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
938 | if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
939 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
940 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
941 | AR_PHY_EXT_CYCPWR_THR1, value2); | ||
942 | |||
943 | if (level != aniState->spurImmunityLevel) { | ||
944 | ath_print(common, ATH_DBG_ANI, | ||
945 | "** ch %d: level %d=>%d[def:%d] " | ||
946 | "cycpwrThr1[level]=%d ini=%d\n", | ||
947 | chan->channel, | ||
948 | aniState->spurImmunityLevel, | ||
949 | level, | ||
950 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
951 | value, | ||
952 | aniState->iniDef.cycpwrThr1); | ||
953 | ath_print(common, ATH_DBG_ANI, | ||
954 | "** ch %d: level %d=>%d[def:%d] " | ||
955 | "cycpwrThr1Ext[level]=%d ini=%d\n", | ||
956 | chan->channel, | ||
957 | aniState->spurImmunityLevel, | ||
958 | level, | ||
959 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
960 | value2, | ||
961 | aniState->iniDef.cycpwrThr1Ext); | ||
962 | if (level > aniState->spurImmunityLevel) | ||
963 | ah->stats.ast_ani_spurup++; | ||
964 | else if (level < aniState->spurImmunityLevel) | ||
965 | ah->stats.ast_ani_spurdown++; | ||
966 | aniState->spurImmunityLevel = level; | ||
967 | } | ||
873 | break; | 968 | break; |
874 | } | 969 | } |
970 | case ATH9K_ANI_MRC_CCK:{ | ||
971 | /* | ||
972 | * is_on == 1 means MRC CCK ON (default, less noise imm) | ||
973 | * is_on == 0 means MRC CCK is OFF (more noise imm) | ||
974 | */ | ||
975 | bool is_on = param ? 1 : 0; | ||
976 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | ||
977 | AR_PHY_MRC_CCK_ENABLE, is_on); | ||
978 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | ||
979 | AR_PHY_MRC_CCK_MUX_REG, is_on); | ||
980 | if (!is_on != aniState->mrcCCKOff) { | ||
981 | ath_print(common, ATH_DBG_ANI, | ||
982 | "** ch %d: MRC CCK: %s=>%s\n", | ||
983 | chan->channel, | ||
984 | !aniState->mrcCCKOff ? "on" : "off", | ||
985 | is_on ? "on" : "off"); | ||
986 | if (is_on) | ||
987 | ah->stats.ast_ani_ccklow++; | ||
988 | else | ||
989 | ah->stats.ast_ani_cckhigh++; | ||
990 | aniState->mrcCCKOff = !is_on; | ||
991 | } | ||
992 | break; | ||
993 | } | ||
875 | case ATH9K_ANI_PRESENT: | 994 | case ATH9K_ANI_PRESENT: |
876 | break; | 995 | break; |
877 | default: | 996 | default: |
@@ -880,25 +999,19 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
880 | return false; | 999 | return false; |
881 | } | 1000 | } |
882 | 1001 | ||
883 | ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); | ||
884 | ath_print(common, ATH_DBG_ANI, | 1002 | ath_print(common, ATH_DBG_ANI, |
885 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " | 1003 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " |
886 | "ofdmWeakSigDetectOff=%d\n", | 1004 | "MRCcck=%s listenTime=%d CC=%d listen=%d " |
887 | aniState->noiseImmunityLevel, | 1005 | "ofdmErrs=%d cckErrs=%d\n", |
888 | aniState->spurImmunityLevel, | 1006 | aniState->spurImmunityLevel, |
889 | !aniState->ofdmWeakSigDetectOff); | 1007 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", |
890 | ath_print(common, ATH_DBG_ANI, | ||
891 | "cckWeakSigThreshold=%d, " | ||
892 | "firstepLevel=%d, listenTime=%d\n", | ||
893 | aniState->cckWeakSigThreshold, | ||
894 | aniState->firstepLevel, | 1008 | aniState->firstepLevel, |
895 | aniState->listenTime); | 1009 | !aniState->mrcCCKOff ? "on" : "off", |
896 | ath_print(common, ATH_DBG_ANI, | 1010 | aniState->listenTime, |
897 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | 1011 | aniState->cycleCount, |
898 | aniState->cycleCount, | 1012 | aniState->listenTime, |
899 | aniState->ofdmPhyErrCount, | 1013 | aniState->ofdmPhyErrCount, |
900 | aniState->cckPhyErrCount); | 1014 | aniState->cckPhyErrCount); |
901 | |||
902 | return true; | 1015 | return true; |
903 | } | 1016 | } |
904 | 1017 | ||
@@ -1111,6 +1224,70 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1111 | } | 1224 | } |
1112 | } | 1225 | } |
1113 | 1226 | ||
1227 | /* | ||
1228 | * Initialize the ANI register values with default (ini) values. | ||
1229 | * This routine is called during a (full) hardware reset after | ||
1230 | * all the registers are initialised from the INI. | ||
1231 | */ | ||
1232 | static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
1233 | { | ||
1234 | struct ar5416AniState *aniState; | ||
1235 | struct ath_common *common = ath9k_hw_common(ah); | ||
1236 | struct ath9k_channel *chan = ah->curchan; | ||
1237 | struct ath9k_ani_default *iniDef; | ||
1238 | int index; | ||
1239 | u32 val; | ||
1240 | |||
1241 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
1242 | aniState = &ah->ani[index]; | ||
1243 | ah->curani = aniState; | ||
1244 | iniDef = &aniState->iniDef; | ||
1245 | |||
1246 | ath_print(common, ATH_DBG_ANI, | ||
1247 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | ||
1248 | ah->hw_version.macVersion, | ||
1249 | ah->hw_version.macRev, | ||
1250 | ah->opmode, | ||
1251 | chan->channel, | ||
1252 | chan->channelFlags); | ||
1253 | |||
1254 | val = REG_READ(ah, AR_PHY_SFCORR); | ||
1255 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | ||
1256 | iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH); | ||
1257 | iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR); | ||
1258 | |||
1259 | val = REG_READ(ah, AR_PHY_SFCORR_LOW); | ||
1260 | iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); | ||
1261 | iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); | ||
1262 | iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); | ||
1263 | |||
1264 | val = REG_READ(ah, AR_PHY_SFCORR_EXT); | ||
1265 | iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH); | ||
1266 | iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH); | ||
1267 | iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW); | ||
1268 | iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW); | ||
1269 | iniDef->firstep = REG_READ_FIELD(ah, | ||
1270 | AR_PHY_FIND_SIG, | ||
1271 | AR_PHY_FIND_SIG_FIRSTEP); | ||
1272 | iniDef->firstepLow = REG_READ_FIELD(ah, | ||
1273 | AR_PHY_FIND_SIG_LOW, | ||
1274 | AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW); | ||
1275 | iniDef->cycpwrThr1 = REG_READ_FIELD(ah, | ||
1276 | AR_PHY_TIMING5, | ||
1277 | AR_PHY_TIMING5_CYCPWR_THR1); | ||
1278 | iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah, | ||
1279 | AR_PHY_EXT_CCA, | ||
1280 | AR_PHY_EXT_CYCPWR_THR1); | ||
1281 | |||
1282 | /* these levels just got reset to defaults by the INI */ | ||
1283 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1284 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1285 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | ||
1286 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; | ||
1287 | |||
1288 | aniState->cycleCount = 0; | ||
1289 | } | ||
1290 | |||
1114 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1291 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
1115 | { | 1292 | { |
1116 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1293 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
@@ -1131,4 +1308,124 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1131 | priv_ops->ani_control = ar9003_hw_ani_control; | 1308 | priv_ops->ani_control = ar9003_hw_ani_control; |
1132 | priv_ops->do_getnf = ar9003_hw_do_getnf; | 1309 | priv_ops->do_getnf = ar9003_hw_do_getnf; |
1133 | priv_ops->loadnf = ar9003_hw_loadnf; | 1310 | priv_ops->loadnf = ar9003_hw_loadnf; |
1311 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; | ||
1312 | } | ||
1313 | |||
1314 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | ||
1315 | { | ||
1316 | struct ath_common *common = ath9k_hw_common(ah); | ||
1317 | u32 idle_tmo_ms = ah->bb_watchdog_timeout_ms; | ||
1318 | u32 val, idle_count; | ||
1319 | |||
1320 | if (!idle_tmo_ms) { | ||
1321 | /* disable IRQ, disable chip-reset for BB panic */ | ||
1322 | REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2, | ||
1323 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & | ||
1324 | ~(AR_PHY_WATCHDOG_RST_ENABLE | | ||
1325 | AR_PHY_WATCHDOG_IRQ_ENABLE)); | ||
1326 | |||
1327 | /* disable watchdog in non-IDLE mode, disable in IDLE mode */ | ||
1328 | REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1, | ||
1329 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_1) & | ||
1330 | ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE | | ||
1331 | AR_PHY_WATCHDOG_IDLE_ENABLE)); | ||
1332 | |||
1333 | ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n"); | ||
1334 | return; | ||
1335 | } | ||
1336 | |||
1337 | /* enable IRQ, disable chip-reset for BB watchdog */ | ||
1338 | val = REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & AR_PHY_WATCHDOG_CNTL2_MASK; | ||
1339 | REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2, | ||
1340 | (val | AR_PHY_WATCHDOG_IRQ_ENABLE) & | ||
1341 | ~AR_PHY_WATCHDOG_RST_ENABLE); | ||
1342 | |||
1343 | /* bound limit to 10 secs */ | ||
1344 | if (idle_tmo_ms > 10000) | ||
1345 | idle_tmo_ms = 10000; | ||
1346 | |||
1347 | /* | ||
1348 | * The time unit for watchdog event is 2^15 44/88MHz cycles. | ||
1349 | * | ||
1350 | * For HT20 we have a time unit of 2^15/44 MHz = .74 ms per tick | ||
1351 | * For HT40 we have a time unit of 2^15/88 MHz = .37 ms per tick | ||
1352 | * | ||
1353 | * Given we use fast clock now in 5 GHz, these time units should | ||
1354 | * be common for both 2 GHz and 5 GHz. | ||
1355 | */ | ||
1356 | idle_count = (100 * idle_tmo_ms) / 74; | ||
1357 | if (ah->curchan && IS_CHAN_HT40(ah->curchan)) | ||
1358 | idle_count = (100 * idle_tmo_ms) / 37; | ||
1359 | |||
1360 | /* | ||
1361 | * enable watchdog in non-IDLE mode, disable in IDLE mode, | ||
1362 | * set idle time-out. | ||
1363 | */ | ||
1364 | REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1, | ||
1365 | AR_PHY_WATCHDOG_NON_IDLE_ENABLE | | ||
1366 | AR_PHY_WATCHDOG_IDLE_MASK | | ||
1367 | (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2))); | ||
1368 | |||
1369 | ath_print(common, ATH_DBG_RESET, | ||
1370 | "Enabled BB Watchdog timeout (%u ms)\n", | ||
1371 | idle_tmo_ms); | ||
1372 | } | ||
1373 | |||
1374 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) | ||
1375 | { | ||
1376 | /* | ||
1377 | * we want to avoid printing in ISR context so we save the | ||
1378 | * watchdog status to be printed later in bottom half context. | ||
1379 | */ | ||
1380 | ah->bb_watchdog_last_status = REG_READ(ah, AR_PHY_WATCHDOG_STATUS); | ||
1381 | |||
1382 | /* | ||
1383 | * the watchdog timer should reset on status read but to be sure | ||
1384 | * sure we write 0 to the watchdog status bit. | ||
1385 | */ | ||
1386 | REG_WRITE(ah, AR_PHY_WATCHDOG_STATUS, | ||
1387 | ah->bb_watchdog_last_status & ~AR_PHY_WATCHDOG_STATUS_CLR); | ||
1388 | } | ||
1389 | |||
1390 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) | ||
1391 | { | ||
1392 | struct ath_common *common = ath9k_hw_common(ah); | ||
1393 | u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status; | ||
1394 | |||
1395 | if (likely(!(common->debug_mask & ATH_DBG_RESET))) | ||
1396 | return; | ||
1397 | |||
1398 | status = ah->bb_watchdog_last_status; | ||
1399 | ath_print(common, ATH_DBG_RESET, | ||
1400 | "\n==== BB update: BB status=0x%08x ====\n", status); | ||
1401 | ath_print(common, ATH_DBG_RESET, | ||
1402 | "** BB state: wd=%u det=%u rdar=%u rOFDM=%d " | ||
1403 | "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", | ||
1404 | MS(status, AR_PHY_WATCHDOG_INFO), | ||
1405 | MS(status, AR_PHY_WATCHDOG_DET_HANG), | ||
1406 | MS(status, AR_PHY_WATCHDOG_RADAR_SM), | ||
1407 | MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM), | ||
1408 | MS(status, AR_PHY_WATCHDOG_RX_CCK_SM), | ||
1409 | MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM), | ||
1410 | MS(status, AR_PHY_WATCHDOG_TX_CCK_SM), | ||
1411 | MS(status, AR_PHY_WATCHDOG_AGC_SM), | ||
1412 | MS(status,AR_PHY_WATCHDOG_SRCH_SM)); | ||
1413 | |||
1414 | ath_print(common, ATH_DBG_RESET, | ||
1415 | "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", | ||
1416 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_1), | ||
1417 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_2)); | ||
1418 | ath_print(common, ATH_DBG_RESET, | ||
1419 | "** BB mode: BB_gen_controls=0x%08x **\n", | ||
1420 | REG_READ(ah, AR_PHY_GEN_CTRL)); | ||
1421 | |||
1422 | if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt)) | ||
1423 | ath_print(common, ATH_DBG_RESET, | ||
1424 | "** BB busy times: rx_clear=%d%%, " | ||
1425 | "rx_frame=%d%%, tx_frame=%d%% **\n", | ||
1426 | rxc_pcnt, rxf_pcnt, txf_pcnt); | ||
1427 | |||
1428 | ath_print(common, ATH_DBG_RESET, | ||
1429 | "==== BB update: done ====\n\n"); | ||
1134 | } | 1430 | } |
1431 | EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index f08cc8bda005..3394dfe52b42 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -149,6 +149,8 @@ | |||
149 | #define AR_PHY_EXT_CCA_THRESH62_S 16 | 149 | #define AR_PHY_EXT_CCA_THRESH62_S 16 |
150 | #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 | 150 | #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 |
151 | #define AR_PHY_EXT_MINCCA_PWR_S 16 | 151 | #define AR_PHY_EXT_MINCCA_PWR_S 16 |
152 | #define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L | ||
153 | #define AR_PHY_EXT_CYCPWR_THR1_S 9 | ||
152 | #define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE | 154 | #define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE |
153 | #define AR_PHY_TIMING5_CYCPWR_THR1_S 1 | 155 | #define AR_PHY_TIMING5_CYCPWR_THR1_S 1 |
154 | #define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001 | 156 | #define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001 |
@@ -283,6 +285,12 @@ | |||
283 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00 | 285 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00 |
284 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9 | 286 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9 |
285 | 287 | ||
288 | #define AR_PHY_MRC_CCK_CTRL (AR_AGC_BASE + 0x1d0) | ||
289 | #define AR_PHY_MRC_CCK_ENABLE 0x00000001 | ||
290 | #define AR_PHY_MRC_CCK_ENABLE_S 0 | ||
291 | #define AR_PHY_MRC_CCK_MUX_REG 0x00000002 | ||
292 | #define AR_PHY_MRC_CCK_MUX_REG_S 1 | ||
293 | |||
286 | #define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200) | 294 | #define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200) |
287 | 295 | ||
288 | #define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110 | 296 | #define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110 |
@@ -451,7 +459,11 @@ | |||
451 | #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) | 459 | #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) |
452 | 460 | ||
453 | #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) | 461 | #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) |
454 | #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) | 462 | |
463 | #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) | ||
464 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008 | ||
465 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3 | ||
466 | |||
455 | #define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174) | 467 | #define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174) |
456 | #define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178) | 468 | #define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178) |
457 | #define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c) | 469 | #define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c) |
@@ -467,30 +479,86 @@ | |||
467 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) | 479 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) |
468 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) | 480 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) |
469 | 481 | ||
470 | #define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) | 482 | #define AR_PHY_TPC_1 (AR_SM_BASE + 0x1f8) |
471 | #define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) | 483 | #define AR_PHY_TPC_1_FORCED_DAC_GAIN 0x0000003e |
472 | #define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) | 484 | #define AR_PHY_TPC_1_FORCED_DAC_GAIN_S 1 |
473 | #define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) | 485 | #define AR_PHY_TPC_1_FORCE_DAC_GAIN 0x00000001 |
474 | #define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) | 486 | #define AR_PHY_TPC_1_FORCE_DAC_GAIN_S 0 |
475 | #define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) | 487 | |
488 | #define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) | ||
489 | #define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) | ||
490 | #define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) | ||
491 | |||
492 | #define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) | ||
493 | #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) | ||
494 | #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) | ||
495 | #define AR_PHY_TPC_11_OLPC_GAIN_DELTA 0x00ff0000 | ||
496 | #define AR_PHY_TPC_11_OLPC_GAIN_DELTA_S 16 | ||
497 | |||
498 | #define AR_PHY_TPC_12 (AR_SM_BASE + 0x224) | ||
499 | #define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5 0x3e000000 | ||
500 | #define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5_S 25 | ||
501 | |||
502 | #define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) | ||
503 | #define AR_PHY_TPC_18_THERM_CAL_VALUE 0x000000ff | ||
504 | #define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 | ||
505 | #define AR_PHY_TPC_18_VOLT_CAL_VALUE 0x0000ff00 | ||
506 | #define AR_PHY_TPC_18_VOLT_CAL_VALUE_S 8 | ||
507 | |||
508 | #define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) | ||
509 | #define AR_PHY_TPC_19_ALPHA_VOLT 0x001f0000 | ||
510 | #define AR_PHY_TPC_19_ALPHA_VOLT_S 16 | ||
511 | #define AR_PHY_TPC_19_ALPHA_THERM 0xff | ||
512 | #define AR_PHY_TPC_19_ALPHA_THERM_S 0 | ||
513 | |||
514 | #define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) | ||
515 | #define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN 0x00000001 | ||
516 | #define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN_S 0 | ||
517 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN 0x0000000e | ||
518 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN_S 1 | ||
519 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN 0x00000030 | ||
520 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN_S 4 | ||
521 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN 0x000003c0 | ||
522 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN_S 6 | ||
523 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA 0x00003c00 | ||
524 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA_S 10 | ||
525 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB 0x0003c000 | ||
526 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB_S 14 | ||
527 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC 0x003c0000 | ||
528 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC_S 18 | ||
529 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND 0x00c00000 | ||
530 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND_S 22 | ||
531 | #define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL 0x01000000 | ||
532 | #define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL_S 24 | ||
476 | 533 | ||
477 | #define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) | ||
478 | 534 | ||
479 | #define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280) | 535 | #define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280) |
480 | 536 | ||
537 | #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) | ||
538 | |||
481 | #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) | 539 | #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) |
482 | #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) | 540 | #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) |
483 | #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) | 541 | #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) |
484 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) | 542 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) |
485 | 543 | ||
486 | #define AR_PHY_PANIC_WD_STATUS (AR_SM_BASE + 0x5c0) | 544 | #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) |
487 | #define AR_PHY_PANIC_WD_CTL_1 (AR_SM_BASE + 0x5c4) | 545 | #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) |
488 | #define AR_PHY_PANIC_WD_CTL_2 (AR_SM_BASE + 0x5c8) | 546 | #define AR_PHY_WATCHDOG_CTL_2 (AR_SM_BASE + 0x5c8) |
489 | #define AR_PHY_BT_CTL (AR_SM_BASE + 0x5cc) | 547 | #define AR_PHY_WATCHDOG_CTL (AR_SM_BASE + 0x5cc) |
490 | #define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) | 548 | #define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) |
491 | #define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) | 549 | #define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) |
492 | #define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) | 550 | #define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) |
493 | #define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) | 551 | |
552 | #define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) | ||
553 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff | ||
554 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 | ||
555 | |||
556 | #define AR_PHY_BB_THERM_ADC_4 (AR_SM_BASE + 0x254) | ||
557 | #define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE 0x000000ff | ||
558 | #define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S 0 | ||
559 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00 | ||
560 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8 | ||
561 | |||
494 | 562 | ||
495 | #define AR_PHY_65NM_CH0_SYNTH4 0x1608c | 563 | #define AR_PHY_65NM_CH0_SYNTH4 0x1608c |
496 | #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 | 564 | #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 |
@@ -660,17 +728,9 @@ | |||
660 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff | 728 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff |
661 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 | 729 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 |
662 | 730 | ||
663 | #define AR_PHY_TPC_18_THERM_CAL_VALUE 0xff | ||
664 | #define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 | ||
665 | #define AR_PHY_TPC_19_ALPHA_THERM 0xff | ||
666 | #define AR_PHY_TPC_19_ALPHA_THERM_S 0 | ||
667 | |||
668 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 | 731 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 |
669 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 | 732 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 |
670 | 733 | ||
671 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff | ||
672 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 | ||
673 | |||
674 | /* | 734 | /* |
675 | * Channel 1 Register Map | 735 | * Channel 1 Register Map |
676 | */ | 736 | */ |
@@ -812,35 +872,173 @@ | |||
812 | #define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) | 872 | #define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) |
813 | #define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) | 873 | #define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) |
814 | 874 | ||
815 | #define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001 | 875 | #define AR_PHY_WATCHDOG_NON_IDLE_ENABLE 0x00000001 |
816 | #define AR_PHY_BB_PANIC_IDLE_ENABLE 0x00000002 | 876 | #define AR_PHY_WATCHDOG_IDLE_ENABLE 0x00000002 |
817 | #define AR_PHY_BB_PANIC_IDLE_MASK 0xFFFF0000 | 877 | #define AR_PHY_WATCHDOG_IDLE_MASK 0xFFFF0000 |
818 | #define AR_PHY_BB_PANIC_NON_IDLE_MASK 0x0000FFFC | 878 | #define AR_PHY_WATCHDOG_NON_IDLE_MASK 0x0000FFFC |
819 | 879 | ||
820 | #define AR_PHY_BB_PANIC_RST_ENABLE 0x00000002 | 880 | #define AR_PHY_WATCHDOG_RST_ENABLE 0x00000002 |
821 | #define AR_PHY_BB_PANIC_IRQ_ENABLE 0x00000004 | 881 | #define AR_PHY_WATCHDOG_IRQ_ENABLE 0x00000004 |
822 | #define AR_PHY_BB_PANIC_CNTL2_MASK 0xFFFFFFF9 | 882 | #define AR_PHY_WATCHDOG_CNTL2_MASK 0xFFFFFFF9 |
823 | 883 | ||
824 | #define AR_PHY_BB_WD_STATUS 0x00000007 | 884 | #define AR_PHY_WATCHDOG_INFO 0x00000007 |
825 | #define AR_PHY_BB_WD_STATUS_S 0 | 885 | #define AR_PHY_WATCHDOG_INFO_S 0 |
826 | #define AR_PHY_BB_WD_DET_HANG 0x00000008 | 886 | #define AR_PHY_WATCHDOG_DET_HANG 0x00000008 |
827 | #define AR_PHY_BB_WD_DET_HANG_S 3 | 887 | #define AR_PHY_WATCHDOG_DET_HANG_S 3 |
828 | #define AR_PHY_BB_WD_RADAR_SM 0x000000F0 | 888 | #define AR_PHY_WATCHDOG_RADAR_SM 0x000000F0 |
829 | #define AR_PHY_BB_WD_RADAR_SM_S 4 | 889 | #define AR_PHY_WATCHDOG_RADAR_SM_S 4 |
830 | #define AR_PHY_BB_WD_RX_OFDM_SM 0x00000F00 | 890 | #define AR_PHY_WATCHDOG_RX_OFDM_SM 0x00000F00 |
831 | #define AR_PHY_BB_WD_RX_OFDM_SM_S 8 | 891 | #define AR_PHY_WATCHDOG_RX_OFDM_SM_S 8 |
832 | #define AR_PHY_BB_WD_RX_CCK_SM 0x0000F000 | 892 | #define AR_PHY_WATCHDOG_RX_CCK_SM 0x0000F000 |
833 | #define AR_PHY_BB_WD_RX_CCK_SM_S 12 | 893 | #define AR_PHY_WATCHDOG_RX_CCK_SM_S 12 |
834 | #define AR_PHY_BB_WD_TX_OFDM_SM 0x000F0000 | 894 | #define AR_PHY_WATCHDOG_TX_OFDM_SM 0x000F0000 |
835 | #define AR_PHY_BB_WD_TX_OFDM_SM_S 16 | 895 | #define AR_PHY_WATCHDOG_TX_OFDM_SM_S 16 |
836 | #define AR_PHY_BB_WD_TX_CCK_SM 0x00F00000 | 896 | #define AR_PHY_WATCHDOG_TX_CCK_SM 0x00F00000 |
837 | #define AR_PHY_BB_WD_TX_CCK_SM_S 20 | 897 | #define AR_PHY_WATCHDOG_TX_CCK_SM_S 20 |
838 | #define AR_PHY_BB_WD_AGC_SM 0x0F000000 | 898 | #define AR_PHY_WATCHDOG_AGC_SM 0x0F000000 |
839 | #define AR_PHY_BB_WD_AGC_SM_S 24 | 899 | #define AR_PHY_WATCHDOG_AGC_SM_S 24 |
840 | #define AR_PHY_BB_WD_SRCH_SM 0xF0000000 | 900 | #define AR_PHY_WATCHDOG_SRCH_SM 0xF0000000 |
841 | #define AR_PHY_BB_WD_SRCH_SM_S 28 | 901 | #define AR_PHY_WATCHDOG_SRCH_SM_S 28 |
842 | 902 | ||
843 | #define AR_PHY_BB_WD_STATUS_CLR 0x00000008 | 903 | #define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008 |
904 | |||
905 | /* | ||
906 | * PAPRD registers | ||
907 | */ | ||
908 | #define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64) | ||
909 | |||
910 | #define AR_PHY_PAPRD_AM2AM (AR_CHAN_BASE + 0xe4) | ||
911 | #define AR_PHY_PAPRD_AM2AM_MASK 0x01ffffff | ||
912 | #define AR_PHY_PAPRD_AM2AM_MASK_S 0 | ||
913 | |||
914 | #define AR_PHY_PAPRD_AM2PM (AR_CHAN_BASE + 0xe8) | ||
915 | #define AR_PHY_PAPRD_AM2PM_MASK 0x01ffffff | ||
916 | #define AR_PHY_PAPRD_AM2PM_MASK_S 0 | ||
917 | |||
918 | #define AR_PHY_PAPRD_HT40 (AR_CHAN_BASE + 0xec) | ||
919 | #define AR_PHY_PAPRD_HT40_MASK 0x01ffffff | ||
920 | #define AR_PHY_PAPRD_HT40_MASK_S 0 | ||
921 | |||
922 | #define AR_PHY_PAPRD_CTRL0_B0 (AR_CHAN_BASE + 0xf0) | ||
923 | #define AR_PHY_PAPRD_CTRL0_B1 (AR_CHAN1_BASE + 0xf0) | ||
924 | #define AR_PHY_PAPRD_CTRL0_B2 (AR_CHAN2_BASE + 0xf0) | ||
925 | #define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE 0x00000001 | ||
926 | #define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE_S 0 | ||
927 | #define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK 0x00000002 | ||
928 | #define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK_S 1 | ||
929 | #define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH 0xf8000000 | ||
930 | #define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH_S 27 | ||
931 | |||
932 | #define AR_PHY_PAPRD_CTRL1_B0 (AR_CHAN_BASE + 0xf4) | ||
933 | #define AR_PHY_PAPRD_CTRL1_B1 (AR_CHAN1_BASE + 0xf4) | ||
934 | #define AR_PHY_PAPRD_CTRL1_B2 (AR_CHAN2_BASE + 0xf4) | ||
935 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA 0x00000001 | ||
936 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA_S 0 | ||
937 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE 0x00000002 | ||
938 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE_S 1 | ||
939 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE 0x00000004 | ||
940 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE_S 2 | ||
941 | #define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL 0x000001f8 | ||
942 | #define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL_S 3 | ||
943 | #define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK 0x0001fe00 | ||
944 | #define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK_S 9 | ||
945 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000 | ||
946 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17 | ||
947 | |||
948 | #define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + 0x490) | ||
949 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001 | ||
950 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0 | ||
951 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e | ||
952 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING_S 1 | ||
953 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE 0x00000100 | ||
954 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE_S 8 | ||
955 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE 0x00000200 | ||
956 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE_S 9 | ||
957 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE 0x00000400 | ||
958 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE_S 10 | ||
959 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE 0x00000800 | ||
960 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE_S 11 | ||
961 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000 | ||
962 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12 | ||
963 | |||
964 | #define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + 0x494) | ||
965 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF | ||
966 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0 | ||
967 | |||
968 | #define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + 0x498) | ||
969 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f | ||
970 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0 | ||
971 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0 | ||
972 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP_S 6 | ||
973 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL 0x0001f000 | ||
974 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL_S 12 | ||
975 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES 0x000e0000 | ||
976 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES_S 17 | ||
977 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN 0x00f00000 | ||
978 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN_S 20 | ||
979 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN 0x0f000000 | ||
980 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN_S 24 | ||
981 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000 | ||
982 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29 | ||
983 | |||
984 | #define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + 0x49c) | ||
985 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000 | ||
986 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16 | ||
987 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000 | ||
988 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA_S 12 | ||
989 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR 0x00000fff | ||
990 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR_S 0 | ||
991 | |||
992 | #define AR_PHY_PAPRD_PRE_POST_SCALE_0_B0 (AR_CHAN_BASE + 0x100) | ||
993 | #define AR_PHY_PAPRD_PRE_POST_SCALE_1_B0 (AR_CHAN_BASE + 0x104) | ||
994 | #define AR_PHY_PAPRD_PRE_POST_SCALE_2_B0 (AR_CHAN_BASE + 0x108) | ||
995 | #define AR_PHY_PAPRD_PRE_POST_SCALE_3_B0 (AR_CHAN_BASE + 0x10c) | ||
996 | #define AR_PHY_PAPRD_PRE_POST_SCALE_4_B0 (AR_CHAN_BASE + 0x110) | ||
997 | #define AR_PHY_PAPRD_PRE_POST_SCALE_5_B0 (AR_CHAN_BASE + 0x114) | ||
998 | #define AR_PHY_PAPRD_PRE_POST_SCALE_6_B0 (AR_CHAN_BASE + 0x118) | ||
999 | #define AR_PHY_PAPRD_PRE_POST_SCALE_7_B0 (AR_CHAN_BASE + 0x11c) | ||
1000 | #define AR_PHY_PAPRD_PRE_POST_SCALING 0x3FFFF | ||
1001 | #define AR_PHY_PAPRD_PRE_POST_SCALING_S 0 | ||
1002 | |||
1003 | #define AR_PHY_PAPRD_TRAINER_STAT1 (AR_SM_BASE + 0x4a0) | ||
1004 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE 0x00000001 | ||
1005 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE_S 0 | ||
1006 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE 0x00000002 | ||
1007 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE_S 1 | ||
1008 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR 0x00000004 | ||
1009 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR_S 2 | ||
1010 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE 0x00000008 | ||
1011 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE_S 3 | ||
1012 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX 0x000001f0 | ||
1013 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX_S 4 | ||
1014 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR 0x0001fe00 | ||
1015 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR_S 9 | ||
1016 | |||
1017 | #define AR_PHY_PAPRD_TRAINER_STAT2 (AR_SM_BASE + 0x4a4) | ||
1018 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL 0x0000ffff | ||
1019 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL_S 0 | ||
1020 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX 0x001f0000 | ||
1021 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX_S 16 | ||
1022 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX 0x00600000 | ||
1023 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX_S 21 | ||
1024 | |||
1025 | #define AR_PHY_PAPRD_TRAINER_STAT3 (AR_SM_BASE + 0x4a8) | ||
1026 | #define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT 0x000fffff | ||
1027 | #define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT_S 0 | ||
1028 | |||
1029 | #define AR_PHY_PAPRD_MEM_TAB_B0 (AR_CHAN_BASE + 0x120) | ||
1030 | #define AR_PHY_PAPRD_MEM_TAB_B1 (AR_CHAN1_BASE + 0x120) | ||
1031 | #define AR_PHY_PAPRD_MEM_TAB_B2 (AR_CHAN2_BASE + 0x120) | ||
1032 | |||
1033 | #define AR_PHY_PA_GAIN123_B0 (AR_CHAN_BASE + 0xf8) | ||
1034 | #define AR_PHY_PA_GAIN123_B1 (AR_CHAN1_BASE + 0xf8) | ||
1035 | #define AR_PHY_PA_GAIN123_B2 (AR_CHAN2_BASE + 0xf8) | ||
1036 | #define AR_PHY_PA_GAIN123_PA_GAIN1 0x3FF | ||
1037 | #define AR_PHY_PA_GAIN123_PA_GAIN1_S 0 | ||
1038 | |||
1039 | #define AR_PHY_POWERTX_RATE5 (AR_SM_BASE + 0x1d0) | ||
1040 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F | ||
1041 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0 | ||
844 | 1042 | ||
845 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); | 1043 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); |
846 | 1044 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 5ea87736a6ae..72d5e52abb8f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/leds.h> | 22 | #include <linux/leds.h> |
23 | #include <linux/completion.h> | ||
23 | 24 | ||
24 | #include "debug.h" | 25 | #include "debug.h" |
25 | #include "common.h" | 26 | #include "common.h" |
@@ -136,6 +137,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
136 | #define ATH_MAX_ANTENNA 3 | 137 | #define ATH_MAX_ANTENNA 3 |
137 | #define ATH_RXBUF 512 | 138 | #define ATH_RXBUF 512 |
138 | #define ATH_TXBUF 512 | 139 | #define ATH_TXBUF 512 |
140 | #define ATH_TXBUF_RESERVE 5 | ||
141 | #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) | ||
139 | #define ATH_TXMAXTRY 13 | 142 | #define ATH_TXMAXTRY 13 |
140 | #define ATH_MGT_TXMAXTRY 4 | 143 | #define ATH_MGT_TXMAXTRY 4 |
141 | 144 | ||
@@ -192,6 +195,7 @@ enum ATH_AGGR_STATUS { | |||
192 | 195 | ||
193 | #define ATH_TXFIFO_DEPTH 8 | 196 | #define ATH_TXFIFO_DEPTH 8 |
194 | struct ath_txq { | 197 | struct ath_txq { |
198 | int axq_class; | ||
195 | u32 axq_qnum; | 199 | u32 axq_qnum; |
196 | u32 *axq_link; | 200 | u32 *axq_link; |
197 | struct list_head axq_q; | 201 | struct list_head axq_q; |
@@ -206,6 +210,71 @@ struct ath_txq { | |||
206 | u8 txq_tailidx; | 210 | u8 txq_tailidx; |
207 | }; | 211 | }; |
208 | 212 | ||
213 | struct ath_atx_ac { | ||
214 | int sched; | ||
215 | int qnum; | ||
216 | struct list_head list; | ||
217 | struct list_head tid_q; | ||
218 | }; | ||
219 | |||
220 | struct ath_buf_state { | ||
221 | int bfs_nframes; | ||
222 | u16 bfs_al; | ||
223 | u16 bfs_frmlen; | ||
224 | int bfs_seqno; | ||
225 | int bfs_tidno; | ||
226 | int bfs_retries; | ||
227 | u8 bf_type; | ||
228 | u8 bfs_paprd; | ||
229 | unsigned long bfs_paprd_timestamp; | ||
230 | u32 bfs_keyix; | ||
231 | enum ath9k_key_type bfs_keytype; | ||
232 | }; | ||
233 | |||
234 | struct ath_buf { | ||
235 | struct list_head list; | ||
236 | struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or | ||
237 | an aggregate) */ | ||
238 | struct ath_buf *bf_next; /* next subframe in the aggregate */ | ||
239 | struct sk_buff *bf_mpdu; /* enclosing frame structure */ | ||
240 | void *bf_desc; /* virtual addr of desc */ | ||
241 | dma_addr_t bf_daddr; /* physical addr of desc */ | ||
242 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ | ||
243 | bool bf_stale; | ||
244 | bool bf_isnullfunc; | ||
245 | bool bf_tx_aborted; | ||
246 | u16 bf_flags; | ||
247 | struct ath_buf_state bf_state; | ||
248 | dma_addr_t bf_dmacontext; | ||
249 | struct ath_wiphy *aphy; | ||
250 | }; | ||
251 | |||
252 | struct ath_atx_tid { | ||
253 | struct list_head list; | ||
254 | struct list_head buf_q; | ||
255 | struct ath_node *an; | ||
256 | struct ath_atx_ac *ac; | ||
257 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; | ||
258 | u16 seq_start; | ||
259 | u16 seq_next; | ||
260 | u16 baw_size; | ||
261 | int tidno; | ||
262 | int baw_head; /* first un-acked tx buffer */ | ||
263 | int baw_tail; /* next unused tx buffer slot */ | ||
264 | int sched; | ||
265 | int paused; | ||
266 | u8 state; | ||
267 | }; | ||
268 | |||
269 | struct ath_node { | ||
270 | struct ath_common *common; | ||
271 | struct ath_atx_tid tid[WME_NUM_TID]; | ||
272 | struct ath_atx_ac ac[WME_NUM_AC]; | ||
273 | u16 maxampdu; | ||
274 | u8 mpdudensity; | ||
275 | int last_rssi; | ||
276 | }; | ||
277 | |||
209 | #define AGGR_CLEANUP BIT(1) | 278 | #define AGGR_CLEANUP BIT(1) |
210 | #define AGGR_ADDBA_COMPLETE BIT(2) | 279 | #define AGGR_ADDBA_COMPLETE BIT(2) |
211 | #define AGGR_ADDBA_PROGRESS BIT(3) | 280 | #define AGGR_ADDBA_PROGRESS BIT(3) |
@@ -214,6 +283,7 @@ struct ath_tx_control { | |||
214 | struct ath_txq *txq; | 283 | struct ath_txq *txq; |
215 | int if_id; | 284 | int if_id; |
216 | enum ath9k_internal_frame_type frame_type; | 285 | enum ath9k_internal_frame_type frame_type; |
286 | u8 paprd; | ||
217 | }; | 287 | }; |
218 | 288 | ||
219 | #define ATH_TX_ERROR 0x01 | 289 | #define ATH_TX_ERROR 0x01 |
@@ -223,11 +293,12 @@ struct ath_tx_control { | |||
223 | struct ath_tx { | 293 | struct ath_tx { |
224 | u16 seq_no; | 294 | u16 seq_no; |
225 | u32 txqsetup; | 295 | u32 txqsetup; |
226 | int hwq_map[ATH9K_WME_AC_VO+1]; | 296 | int hwq_map[WME_NUM_AC]; |
227 | spinlock_t txbuflock; | 297 | spinlock_t txbuflock; |
228 | struct list_head txbuf; | 298 | struct list_head txbuf; |
229 | struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; | 299 | struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; |
230 | struct ath_descdma txdma; | 300 | struct ath_descdma txdma; |
301 | int pending_frames[WME_NUM_AC]; | ||
231 | }; | 302 | }; |
232 | 303 | ||
233 | struct ath_rx_edma { | 304 | struct ath_rx_edma { |
@@ -267,7 +338,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); | |||
267 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); | 338 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); |
268 | int ath_tx_init(struct ath_softc *sc, int nbufs); | 339 | int ath_tx_init(struct ath_softc *sc, int nbufs); |
269 | void ath_tx_cleanup(struct ath_softc *sc); | 340 | void ath_tx_cleanup(struct ath_softc *sc); |
270 | struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); | ||
271 | int ath_txq_update(struct ath_softc *sc, int qnum, | 341 | int ath_txq_update(struct ath_softc *sc, int qnum, |
272 | struct ath9k_tx_queue_info *q); | 342 | struct ath9k_tx_queue_info *q); |
273 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | 343 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, |
@@ -351,10 +421,14 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
351 | 421 | ||
352 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ | 422 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ |
353 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | 423 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ |
354 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ | 424 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ |
425 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ | ||
355 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 426 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
356 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 427 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
357 | 428 | ||
429 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ | ||
430 | |||
431 | void ath_paprd_calibrate(struct work_struct *work); | ||
358 | void ath_ani_calibrate(unsigned long data); | 432 | void ath_ani_calibrate(unsigned long data); |
359 | 433 | ||
360 | /**********/ | 434 | /**********/ |
@@ -487,6 +561,8 @@ struct ath_softc { | |||
487 | spinlock_t sc_serial_rw; | 561 | spinlock_t sc_serial_rw; |
488 | spinlock_t sc_pm_lock; | 562 | spinlock_t sc_pm_lock; |
489 | struct mutex mutex; | 563 | struct mutex mutex; |
564 | struct work_struct paprd_work; | ||
565 | struct completion paprd_complete; | ||
490 | 566 | ||
491 | u32 intrstatus; | 567 | u32 intrstatus; |
492 | u32 sc_flags; /* SC_OP_* */ | 568 | u32 sc_flags; /* SC_OP_* */ |
@@ -545,7 +621,6 @@ struct ath_wiphy { | |||
545 | 621 | ||
546 | void ath9k_tasklet(unsigned long data); | 622 | void ath9k_tasklet(unsigned long data); |
547 | int ath_reset(struct ath_softc *sc, bool retry_tx); | 623 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
548 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | ||
549 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | 624 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); |
550 | int ath_cabq_update(struct ath_softc *); | 625 | int ath_cabq_update(struct ath_softc *); |
551 | 626 | ||
@@ -556,13 +631,12 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
556 | 631 | ||
557 | extern struct ieee80211_ops ath9k_ops; | 632 | extern struct ieee80211_ops ath9k_ops; |
558 | extern int modparam_nohwcrypt; | 633 | extern int modparam_nohwcrypt; |
634 | extern int led_blink; | ||
559 | 635 | ||
560 | irqreturn_t ath_isr(int irq, void *dev); | 636 | irqreturn_t ath_isr(int irq, void *dev); |
561 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | 637 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
562 | const struct ath_bus_ops *bus_ops); | 638 | const struct ath_bus_ops *bus_ops); |
563 | void ath9k_deinit_device(struct ath_softc *sc); | 639 | void ath9k_deinit_device(struct ath_softc *sc); |
564 | const char *ath_mac_bb_name(u32 mac_bb_version); | ||
565 | const char *ath_rf_name(u16 rf_version); | ||
566 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 640 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
567 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | 641 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, |
568 | struct ath9k_channel *ichan); | 642 | struct ath9k_channel *ichan); |
@@ -613,8 +687,6 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); | |||
613 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); | 687 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); |
614 | void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | 688 | void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); |
615 | 689 | ||
616 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | ||
617 | |||
618 | void ath_start_rfkill_poll(struct ath_softc *sc); | 690 | void ath_start_rfkill_poll(struct ath_softc *sc); |
619 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 691 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
620 | 692 | ||
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index f43d85a302c4..4d4b22d52dfd 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -38,8 +38,7 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
38 | qi.tqi_cwmax = 0; | 38 | qi.tqi_cwmax = 0; |
39 | } else { | 39 | } else { |
40 | /* Adhoc mode; important thing is to use 2x cwmin. */ | 40 | /* Adhoc mode; important thing is to use 2x cwmin. */ |
41 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, | 41 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
42 | ATH9K_WME_AC_BE); | ||
43 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | 42 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); |
44 | qi.tqi_aifs = qi_be.tqi_aifs; | 43 | qi.tqi_aifs = qi_be.tqi_aifs; |
45 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | 44 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 7707341cd0d3..16e2849f644d 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -27,270 +27,6 @@ MODULE_AUTHOR("Atheros Communications"); | |||
27 | MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); | 27 | MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); |
28 | MODULE_LICENSE("Dual BSD/GPL"); | 28 | MODULE_LICENSE("Dual BSD/GPL"); |
29 | 29 | ||
30 | /* Common RX processing */ | ||
31 | |||
32 | /* Assumes you've already done the endian to CPU conversion */ | ||
33 | static bool ath9k_rx_accept(struct ath_common *common, | ||
34 | struct sk_buff *skb, | ||
35 | struct ieee80211_rx_status *rxs, | ||
36 | struct ath_rx_status *rx_stats, | ||
37 | bool *decrypt_error) | ||
38 | { | ||
39 | struct ath_hw *ah = common->ah; | ||
40 | struct ieee80211_hdr *hdr; | ||
41 | __le16 fc; | ||
42 | |||
43 | hdr = (struct ieee80211_hdr *) skb->data; | ||
44 | fc = hdr->frame_control; | ||
45 | |||
46 | if (!rx_stats->rs_datalen) | ||
47 | return false; | ||
48 | /* | ||
49 | * rs_status follows rs_datalen so if rs_datalen is too large | ||
50 | * we can take a hint that hardware corrupted it, so ignore | ||
51 | * those frames. | ||
52 | */ | ||
53 | if (rx_stats->rs_datalen > common->rx_bufsize) | ||
54 | return false; | ||
55 | |||
56 | /* | ||
57 | * rs_more indicates chained descriptors which can be used | ||
58 | * to link buffers together for a sort of scatter-gather | ||
59 | * operation. | ||
60 | * reject the frame, we don't support scatter-gather yet and | ||
61 | * the frame is probably corrupt anyway | ||
62 | */ | ||
63 | if (rx_stats->rs_more) | ||
64 | return false; | ||
65 | |||
66 | /* | ||
67 | * The rx_stats->rs_status will not be set until the end of the | ||
68 | * chained descriptors so it can be ignored if rs_more is set. The | ||
69 | * rs_more will be false at the last element of the chained | ||
70 | * descriptors. | ||
71 | */ | ||
72 | if (rx_stats->rs_status != 0) { | ||
73 | if (rx_stats->rs_status & ATH9K_RXERR_CRC) | ||
74 | rxs->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
75 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) | ||
76 | return false; | ||
77 | |||
78 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { | ||
79 | *decrypt_error = true; | ||
80 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { | ||
81 | if (ieee80211_is_ctl(fc)) | ||
82 | /* | ||
83 | * Sometimes, we get invalid | ||
84 | * MIC failures on valid control frames. | ||
85 | * Remove these mic errors. | ||
86 | */ | ||
87 | rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | ||
88 | else | ||
89 | rxs->flag |= RX_FLAG_MMIC_ERROR; | ||
90 | } | ||
91 | /* | ||
92 | * Reject error frames with the exception of | ||
93 | * decryption and MIC failures. For monitor mode, | ||
94 | * we also ignore the CRC error. | ||
95 | */ | ||
96 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | ||
97 | if (rx_stats->rs_status & | ||
98 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | ||
99 | ATH9K_RXERR_CRC)) | ||
100 | return false; | ||
101 | } else { | ||
102 | if (rx_stats->rs_status & | ||
103 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { | ||
104 | return false; | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | return true; | ||
109 | } | ||
110 | |||
111 | static int ath9k_process_rate(struct ath_common *common, | ||
112 | struct ieee80211_hw *hw, | ||
113 | struct ath_rx_status *rx_stats, | ||
114 | struct ieee80211_rx_status *rxs, | ||
115 | struct sk_buff *skb) | ||
116 | { | ||
117 | struct ieee80211_supported_band *sband; | ||
118 | enum ieee80211_band band; | ||
119 | unsigned int i = 0; | ||
120 | |||
121 | band = hw->conf.channel->band; | ||
122 | sband = hw->wiphy->bands[band]; | ||
123 | |||
124 | if (rx_stats->rs_rate & 0x80) { | ||
125 | /* HT rate */ | ||
126 | rxs->flag |= RX_FLAG_HT; | ||
127 | if (rx_stats->rs_flags & ATH9K_RX_2040) | ||
128 | rxs->flag |= RX_FLAG_40MHZ; | ||
129 | if (rx_stats->rs_flags & ATH9K_RX_GI) | ||
130 | rxs->flag |= RX_FLAG_SHORT_GI; | ||
131 | rxs->rate_idx = rx_stats->rs_rate & 0x7f; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | for (i = 0; i < sband->n_bitrates; i++) { | ||
136 | if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { | ||
137 | rxs->rate_idx = i; | ||
138 | return 0; | ||
139 | } | ||
140 | if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { | ||
141 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
142 | rxs->rate_idx = i; | ||
143 | return 0; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * No valid hardware bitrate found -- we should not get here | ||
149 | * because hardware has already validated this frame as OK. | ||
150 | */ | ||
151 | ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " | ||
152 | "0x%02x using 1 Mbit\n", rx_stats->rs_rate); | ||
153 | if ((common->debug_mask & ATH_DBG_XMIT)) | ||
154 | print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len); | ||
155 | |||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | static void ath9k_process_rssi(struct ath_common *common, | ||
160 | struct ieee80211_hw *hw, | ||
161 | struct sk_buff *skb, | ||
162 | struct ath_rx_status *rx_stats) | ||
163 | { | ||
164 | struct ath_hw *ah = common->ah; | ||
165 | struct ieee80211_sta *sta; | ||
166 | struct ieee80211_hdr *hdr; | ||
167 | struct ath_node *an; | ||
168 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
169 | __le16 fc; | ||
170 | |||
171 | hdr = (struct ieee80211_hdr *)skb->data; | ||
172 | fc = hdr->frame_control; | ||
173 | |||
174 | rcu_read_lock(); | ||
175 | /* | ||
176 | * XXX: use ieee80211_find_sta! This requires quite a bit of work | ||
177 | * under the current ath9k virtual wiphy implementation as we have | ||
178 | * no way of tying a vif to wiphy. Typically vifs are attached to | ||
179 | * at least one sdata of a wiphy on mac80211 but with ath9k virtual | ||
180 | * wiphy you'd have to iterate over every wiphy and each sdata. | ||
181 | */ | ||
182 | sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); | ||
183 | if (sta) { | ||
184 | an = (struct ath_node *) sta->drv_priv; | ||
185 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && | ||
186 | !rx_stats->rs_moreaggr) | ||
187 | ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); | ||
188 | last_rssi = an->last_rssi; | ||
189 | } | ||
190 | rcu_read_unlock(); | ||
191 | |||
192 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
193 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, | ||
194 | ATH_RSSI_EP_MULTIPLIER); | ||
195 | if (rx_stats->rs_rssi < 0) | ||
196 | rx_stats->rs_rssi = 0; | ||
197 | |||
198 | /* Update Beacon RSSI, this is used by ANI. */ | ||
199 | if (ieee80211_is_beacon(fc)) | ||
200 | ah->stats.avgbrssi = rx_stats->rs_rssi; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * For Decrypt or Demic errors, we only mark packet status here and always push | ||
205 | * up the frame up to let mac80211 handle the actual error case, be it no | ||
206 | * decryption key or real decryption error. This let us keep statistics there. | ||
207 | */ | ||
208 | int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, | ||
209 | struct ieee80211_hw *hw, | ||
210 | struct sk_buff *skb, | ||
211 | struct ath_rx_status *rx_stats, | ||
212 | struct ieee80211_rx_status *rx_status, | ||
213 | bool *decrypt_error) | ||
214 | { | ||
215 | struct ath_hw *ah = common->ah; | ||
216 | |||
217 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | ||
218 | |||
219 | /* | ||
220 | * everything but the rate is checked here, the rate check is done | ||
221 | * separately to avoid doing two lookups for a rate for each frame. | ||
222 | */ | ||
223 | if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) | ||
224 | return -EINVAL; | ||
225 | |||
226 | ath9k_process_rssi(common, hw, skb, rx_stats); | ||
227 | |||
228 | if (ath9k_process_rate(common, hw, rx_stats, rx_status, skb)) | ||
229 | return -EINVAL; | ||
230 | |||
231 | rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); | ||
232 | rx_status->band = hw->conf.channel->band; | ||
233 | rx_status->freq = hw->conf.channel->center_freq; | ||
234 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; | ||
235 | rx_status->antenna = rx_stats->rs_antenna; | ||
236 | rx_status->flag |= RX_FLAG_TSFT; | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess); | ||
241 | |||
242 | void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | ||
243 | struct sk_buff *skb, | ||
244 | struct ath_rx_status *rx_stats, | ||
245 | struct ieee80211_rx_status *rxs, | ||
246 | bool decrypt_error) | ||
247 | { | ||
248 | struct ath_hw *ah = common->ah; | ||
249 | struct ieee80211_hdr *hdr; | ||
250 | int hdrlen, padpos, padsize; | ||
251 | u8 keyix; | ||
252 | __le16 fc; | ||
253 | |||
254 | /* see if any padding is done by the hw and remove it */ | ||
255 | hdr = (struct ieee80211_hdr *) skb->data; | ||
256 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
257 | fc = hdr->frame_control; | ||
258 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
259 | |||
260 | /* The MAC header is padded to have 32-bit boundary if the | ||
261 | * packet payload is non-zero. The general calculation for | ||
262 | * padsize would take into account odd header lengths: | ||
263 | * padsize = (4 - padpos % 4) % 4; However, since only | ||
264 | * even-length headers are used, padding can only be 0 or 2 | ||
265 | * bytes and we can optimize this a bit. In addition, we must | ||
266 | * not try to remove padding from short control frames that do | ||
267 | * not have payload. */ | ||
268 | padsize = padpos & 3; | ||
269 | if (padsize && skb->len>=padpos+padsize+FCS_LEN) { | ||
270 | memmove(skb->data + padsize, skb->data, padpos); | ||
271 | skb_pull(skb, padsize); | ||
272 | } | ||
273 | |||
274 | keyix = rx_stats->rs_keyix; | ||
275 | |||
276 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && | ||
277 | ieee80211_has_protected(fc)) { | ||
278 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
279 | } else if (ieee80211_has_protected(fc) | ||
280 | && !decrypt_error && skb->len >= hdrlen + 4) { | ||
281 | keyix = skb->data[hdrlen + 3] >> 6; | ||
282 | |||
283 | if (test_bit(keyix, common->keymap)) | ||
284 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
285 | } | ||
286 | if (ah->sw_mgmt_crypto && | ||
287 | (rxs->flag & RX_FLAG_DECRYPTED) && | ||
288 | ieee80211_is_mgmt(fc)) | ||
289 | /* Use software decrypt for management frames. */ | ||
290 | rxs->flag &= ~RX_FLAG_DECRYPTED; | ||
291 | } | ||
292 | EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); | ||
293 | |||
294 | int ath9k_cmn_padpos(__le16 frame_control) | 30 | int ath9k_cmn_padpos(__le16 frame_control) |
295 | { | 31 | { |
296 | int padpos = 24; | 32 | int padpos = 24; |
@@ -475,10 +211,14 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | |||
475 | return -1; | 211 | return -1; |
476 | } | 212 | } |
477 | 213 | ||
478 | static int ath_reserve_key_cache_slot(struct ath_common *common) | 214 | static int ath_reserve_key_cache_slot(struct ath_common *common, |
215 | enum ieee80211_key_alg alg) | ||
479 | { | 216 | { |
480 | int i; | 217 | int i; |
481 | 218 | ||
219 | if (alg == ALG_TKIP) | ||
220 | return ath_reserve_key_cache_slot_tkip(common); | ||
221 | |||
482 | /* First, try to find slots that would not be available for TKIP. */ | 222 | /* First, try to find slots that would not be available for TKIP. */ |
483 | if (common->splitmic) { | 223 | if (common->splitmic) { |
484 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | 224 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { |
@@ -547,6 +287,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
547 | struct ath_hw *ah = common->ah; | 287 | struct ath_hw *ah = common->ah; |
548 | struct ath9k_keyval hk; | 288 | struct ath9k_keyval hk; |
549 | const u8 *mac = NULL; | 289 | const u8 *mac = NULL; |
290 | u8 gmac[ETH_ALEN]; | ||
550 | int ret = 0; | 291 | int ret = 0; |
551 | int idx; | 292 | int idx; |
552 | 293 | ||
@@ -570,9 +311,23 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
570 | memcpy(hk.kv_val, key->key, key->keylen); | 311 | memcpy(hk.kv_val, key->key, key->keylen); |
571 | 312 | ||
572 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | 313 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
573 | /* For now, use the default keys for broadcast keys. This may | 314 | switch (vif->type) { |
574 | * need to change with virtual interfaces. */ | 315 | case NL80211_IFTYPE_AP: |
575 | idx = key->keyidx; | 316 | memcpy(gmac, vif->addr, ETH_ALEN); |
317 | gmac[0] |= 0x01; | ||
318 | mac = gmac; | ||
319 | idx = ath_reserve_key_cache_slot(common, key->alg); | ||
320 | break; | ||
321 | case NL80211_IFTYPE_ADHOC: | ||
322 | memcpy(gmac, sta->addr, ETH_ALEN); | ||
323 | gmac[0] |= 0x01; | ||
324 | mac = gmac; | ||
325 | idx = ath_reserve_key_cache_slot(common, key->alg); | ||
326 | break; | ||
327 | default: | ||
328 | idx = key->keyidx; | ||
329 | break; | ||
330 | } | ||
576 | } else if (key->keyidx) { | 331 | } else if (key->keyidx) { |
577 | if (WARN_ON(!sta)) | 332 | if (WARN_ON(!sta)) |
578 | return -EOPNOTSUPP; | 333 | return -EOPNOTSUPP; |
@@ -589,14 +344,12 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
589 | return -EOPNOTSUPP; | 344 | return -EOPNOTSUPP; |
590 | mac = sta->addr; | 345 | mac = sta->addr; |
591 | 346 | ||
592 | if (key->alg == ALG_TKIP) | 347 | idx = ath_reserve_key_cache_slot(common, key->alg); |
593 | idx = ath_reserve_key_cache_slot_tkip(common); | ||
594 | else | ||
595 | idx = ath_reserve_key_cache_slot(common); | ||
596 | if (idx < 0) | ||
597 | return -ENOSPC; /* no free key cache entries */ | ||
598 | } | 348 | } |
599 | 349 | ||
350 | if (idx < 0) | ||
351 | return -ENOSPC; /* no free key cache entries */ | ||
352 | |||
600 | if (key->alg == ALG_TKIP) | 353 | if (key->alg == ALG_TKIP) |
601 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | 354 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, |
602 | vif->type == NL80211_IFTYPE_AP); | 355 | vif->type == NL80211_IFTYPE_AP); |
@@ -644,6 +397,19 @@ void ath9k_cmn_key_delete(struct ath_common *common, | |||
644 | } | 397 | } |
645 | EXPORT_SYMBOL(ath9k_cmn_key_delete); | 398 | EXPORT_SYMBOL(ath9k_cmn_key_delete); |
646 | 399 | ||
400 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) | ||
401 | { | ||
402 | int streams = 0; | ||
403 | |||
404 | do { | ||
405 | if (++streams == max) | ||
406 | break; | ||
407 | } while ((chainmask = chainmask & (chainmask - 1))); | ||
408 | |||
409 | return streams; | ||
410 | } | ||
411 | EXPORT_SYMBOL(ath9k_cmn_count_streams); | ||
412 | |||
647 | static int __init ath9k_cmn_init(void) | 413 | static int __init ath9k_cmn_init(void) |
648 | { | 414 | { |
649 | return 0; | 415 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index e08f7e5a26e0..97809d39c73f 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -52,82 +52,6 @@ | |||
52 | #define ATH_EP_RND(x, mul) \ | 52 | #define ATH_EP_RND(x, mul) \ |
53 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | 53 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) |
54 | 54 | ||
55 | struct ath_atx_ac { | ||
56 | int sched; | ||
57 | int qnum; | ||
58 | struct list_head list; | ||
59 | struct list_head tid_q; | ||
60 | }; | ||
61 | |||
62 | struct ath_buf_state { | ||
63 | int bfs_nframes; | ||
64 | u16 bfs_al; | ||
65 | u16 bfs_frmlen; | ||
66 | int bfs_seqno; | ||
67 | int bfs_tidno; | ||
68 | int bfs_retries; | ||
69 | u8 bf_type; | ||
70 | u32 bfs_keyix; | ||
71 | enum ath9k_key_type bfs_keytype; | ||
72 | }; | ||
73 | |||
74 | struct ath_buf { | ||
75 | struct list_head list; | ||
76 | struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or | ||
77 | an aggregate) */ | ||
78 | struct ath_buf *bf_next; /* next subframe in the aggregate */ | ||
79 | struct sk_buff *bf_mpdu; /* enclosing frame structure */ | ||
80 | void *bf_desc; /* virtual addr of desc */ | ||
81 | dma_addr_t bf_daddr; /* physical addr of desc */ | ||
82 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ | ||
83 | bool bf_stale; | ||
84 | bool bf_isnullfunc; | ||
85 | bool bf_tx_aborted; | ||
86 | u16 bf_flags; | ||
87 | struct ath_buf_state bf_state; | ||
88 | dma_addr_t bf_dmacontext; | ||
89 | struct ath_wiphy *aphy; | ||
90 | }; | ||
91 | |||
92 | struct ath_atx_tid { | ||
93 | struct list_head list; | ||
94 | struct list_head buf_q; | ||
95 | struct ath_node *an; | ||
96 | struct ath_atx_ac *ac; | ||
97 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; | ||
98 | u16 seq_start; | ||
99 | u16 seq_next; | ||
100 | u16 baw_size; | ||
101 | int tidno; | ||
102 | int baw_head; /* first un-acked tx buffer */ | ||
103 | int baw_tail; /* next unused tx buffer slot */ | ||
104 | int sched; | ||
105 | int paused; | ||
106 | u8 state; | ||
107 | }; | ||
108 | |||
109 | struct ath_node { | ||
110 | struct ath_common *common; | ||
111 | struct ath_atx_tid tid[WME_NUM_TID]; | ||
112 | struct ath_atx_ac ac[WME_NUM_AC]; | ||
113 | u16 maxampdu; | ||
114 | u8 mpdudensity; | ||
115 | int last_rssi; | ||
116 | }; | ||
117 | |||
118 | int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, | ||
119 | struct ieee80211_hw *hw, | ||
120 | struct sk_buff *skb, | ||
121 | struct ath_rx_status *rx_stats, | ||
122 | struct ieee80211_rx_status *rx_status, | ||
123 | bool *decrypt_error); | ||
124 | |||
125 | void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | ||
126 | struct sk_buff *skb, | ||
127 | struct ath_rx_status *rx_stats, | ||
128 | struct ieee80211_rx_status *rxs, | ||
129 | bool decrypt_error); | ||
130 | |||
131 | int ath9k_cmn_padpos(__le16 frame_control); | 55 | int ath9k_cmn_padpos(__le16 frame_control); |
132 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 56 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
133 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | 57 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, |
@@ -140,3 +64,4 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
140 | struct ieee80211_key_conf *key); | 64 | struct ieee80211_key_conf *key); |
141 | void ath9k_cmn_key_delete(struct ath_common *common, | 65 | void ath9k_cmn_key_delete(struct ath_common *common, |
142 | struct ieee80211_key_conf *key); | 66 | struct ieee80211_key_conf *key); |
67 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 29898f8d1893..54aae931424e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -42,7 +42,7 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf, | |||
42 | char buf[32]; | 42 | char buf[32]; |
43 | unsigned int len; | 43 | unsigned int len; |
44 | 44 | ||
45 | len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask); | 45 | len = sprintf(buf, "0x%08x\n", common->debug_mask); |
46 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 46 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
47 | } | 47 | } |
48 | 48 | ||
@@ -57,7 +57,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, | |||
57 | 57 | ||
58 | len = min(count, sizeof(buf) - 1); | 58 | len = min(count, sizeof(buf) - 1); |
59 | if (copy_from_user(buf, user_buf, len)) | 59 | if (copy_from_user(buf, user_buf, len)) |
60 | return -EINVAL; | 60 | return -EFAULT; |
61 | 61 | ||
62 | buf[len] = '\0'; | 62 | buf[len] = '\0'; |
63 | if (strict_strtoul(buf, 0, &mask)) | 63 | if (strict_strtoul(buf, 0, &mask)) |
@@ -86,7 +86,7 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf, | |||
86 | char buf[32]; | 86 | char buf[32]; |
87 | unsigned int len; | 87 | unsigned int len; |
88 | 88 | ||
89 | len = snprintf(buf, sizeof(buf), "0x%08x\n", common->tx_chainmask); | 89 | len = sprintf(buf, "0x%08x\n", common->tx_chainmask); |
90 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 90 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
91 | } | 91 | } |
92 | 92 | ||
@@ -101,7 +101,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use | |||
101 | 101 | ||
102 | len = min(count, sizeof(buf) - 1); | 102 | len = min(count, sizeof(buf) - 1); |
103 | if (copy_from_user(buf, user_buf, len)) | 103 | if (copy_from_user(buf, user_buf, len)) |
104 | return -EINVAL; | 104 | return -EFAULT; |
105 | 105 | ||
106 | buf[len] = '\0'; | 106 | buf[len] = '\0'; |
107 | if (strict_strtoul(buf, 0, &mask)) | 107 | if (strict_strtoul(buf, 0, &mask)) |
@@ -128,7 +128,7 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf, | |||
128 | char buf[32]; | 128 | char buf[32]; |
129 | unsigned int len; | 129 | unsigned int len; |
130 | 130 | ||
131 | len = snprintf(buf, sizeof(buf), "0x%08x\n", common->rx_chainmask); | 131 | len = sprintf(buf, "0x%08x\n", common->rx_chainmask); |
132 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 132 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
133 | } | 133 | } |
134 | 134 | ||
@@ -143,7 +143,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use | |||
143 | 143 | ||
144 | len = min(count, sizeof(buf) - 1); | 144 | len = min(count, sizeof(buf) - 1); |
145 | if (copy_from_user(buf, user_buf, len)) | 145 | if (copy_from_user(buf, user_buf, len)) |
146 | return -EINVAL; | 146 | return -EFAULT; |
147 | 147 | ||
148 | buf[len] = '\0'; | 148 | buf[len] = '\0'; |
149 | if (strict_strtoul(buf, 0, &mask)) | 149 | if (strict_strtoul(buf, 0, &mask)) |
@@ -176,7 +176,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
176 | 176 | ||
177 | buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL); | 177 | buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL); |
178 | if (!buf) | 178 | if (!buf) |
179 | return 0; | 179 | return -ENOMEM; |
180 | 180 | ||
181 | ath9k_ps_wakeup(sc); | 181 | ath9k_ps_wakeup(sc); |
182 | 182 | ||
@@ -248,6 +248,9 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
248 | 248 | ||
249 | ath9k_ps_restore(sc); | 249 | ath9k_ps_restore(sc); |
250 | 250 | ||
251 | if (len > DMA_BUF_LEN) | ||
252 | len = DMA_BUF_LEN; | ||
253 | |||
251 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | 254 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
252 | kfree(buf); | 255 | kfree(buf); |
253 | return retval; | 256 | return retval; |
@@ -269,6 +272,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) | |||
269 | sc->debug.stats.istats.rxlp++; | 272 | sc->debug.stats.istats.rxlp++; |
270 | if (status & ATH9K_INT_RXHP) | 273 | if (status & ATH9K_INT_RXHP) |
271 | sc->debug.stats.istats.rxhp++; | 274 | sc->debug.stats.istats.rxhp++; |
275 | if (status & ATH9K_INT_BB_WATCHDOG) | ||
276 | sc->debug.stats.istats.bb_watchdog++; | ||
272 | } else { | 277 | } else { |
273 | if (status & ATH9K_INT_RX) | 278 | if (status & ATH9K_INT_RX) |
274 | sc->debug.stats.istats.rxok++; | 279 | sc->debug.stats.istats.rxok++; |
@@ -319,6 +324,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
319 | "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); | 324 | "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); |
320 | len += snprintf(buf + len, sizeof(buf) - len, | 325 | len += snprintf(buf + len, sizeof(buf) - len, |
321 | "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp); | 326 | "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp); |
327 | len += snprintf(buf + len, sizeof(buf) - len, | ||
328 | "%8s: %10u\n", "WATCHDOG", | ||
329 | sc->debug.stats.istats.bb_watchdog); | ||
322 | } else { | 330 | } else { |
323 | len += snprintf(buf + len, sizeof(buf) - len, | 331 | len += snprintf(buf + len, sizeof(buf) - len, |
324 | "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); | 332 | "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); |
@@ -358,6 +366,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
358 | len += snprintf(buf + len, sizeof(buf) - len, | 366 | len += snprintf(buf + len, sizeof(buf) - len, |
359 | "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); | 367 | "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); |
360 | 368 | ||
369 | if (len > sizeof(buf)) | ||
370 | len = sizeof(buf); | ||
371 | |||
361 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 372 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
362 | } | 373 | } |
363 | 374 | ||
@@ -397,11 +408,10 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | |||
397 | if (sc->cur_rate_table == NULL) | 408 | if (sc->cur_rate_table == NULL) |
398 | return 0; | 409 | return 0; |
399 | 410 | ||
400 | max = 80 + sc->cur_rate_table->rate_cnt * 1024; | 411 | max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1; |
401 | buf = kmalloc(max + 1, GFP_KERNEL); | 412 | buf = kmalloc(max, GFP_KERNEL); |
402 | if (buf == NULL) | 413 | if (buf == NULL) |
403 | return 0; | 414 | return -ENOMEM; |
404 | buf[max] = 0; | ||
405 | 415 | ||
406 | len += sprintf(buf, "%6s %6s %6s " | 416 | len += sprintf(buf, "%6s %6s %6s " |
407 | "%10s %10s %10s %10s\n", | 417 | "%10s %10s %10s %10s\n", |
@@ -443,6 +453,9 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | |||
443 | stats->per); | 453 | stats->per); |
444 | } | 454 | } |
445 | 455 | ||
456 | if (len > max) | ||
457 | len = max; | ||
458 | |||
446 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | 459 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
447 | kfree(buf); | 460 | kfree(buf); |
448 | return retval; | 461 | return retval; |
@@ -505,6 +518,9 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
505 | len += snprintf(buf + len, sizeof(buf) - len, | 518 | len += snprintf(buf + len, sizeof(buf) - len, |
506 | "addrmask: %pM\n", addr); | 519 | "addrmask: %pM\n", addr); |
507 | 520 | ||
521 | if (len > sizeof(buf)) | ||
522 | len = sizeof(buf); | ||
523 | |||
508 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 524 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
509 | } | 525 | } |
510 | 526 | ||
@@ -614,10 +630,10 @@ static const struct file_operations fops_wiphy = { | |||
614 | do { \ | 630 | do { \ |
615 | len += snprintf(buf + len, size - len, \ | 631 | len += snprintf(buf + len, size - len, \ |
616 | "%s%13u%11u%10u%10u\n", str, \ | 632 | "%s%13u%11u%10u%10u\n", str, \ |
617 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \ | 633 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \ |
618 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \ | 634 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \ |
619 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \ | 635 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \ |
620 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \ | 636 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \ |
621 | } while(0) | 637 | } while(0) |
622 | 638 | ||
623 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | 639 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, |
@@ -630,7 +646,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
630 | 646 | ||
631 | buf = kzalloc(size, GFP_KERNEL); | 647 | buf = kzalloc(size, GFP_KERNEL); |
632 | if (buf == NULL) | 648 | if (buf == NULL) |
633 | return 0; | 649 | return -ENOMEM; |
634 | 650 | ||
635 | len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); | 651 | len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); |
636 | 652 | ||
@@ -648,6 +664,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
648 | PR("DATA Underrun: ", data_underrun); | 664 | PR("DATA Underrun: ", data_underrun); |
649 | PR("DELIM Underrun: ", delim_underrun); | 665 | PR("DELIM Underrun: ", delim_underrun); |
650 | 666 | ||
667 | if (len > size) | ||
668 | len = size; | ||
669 | |||
651 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | 670 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
652 | kfree(buf); | 671 | kfree(buf); |
653 | 672 | ||
@@ -700,7 +719,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
700 | 719 | ||
701 | buf = kzalloc(size, GFP_KERNEL); | 720 | buf = kzalloc(size, GFP_KERNEL); |
702 | if (buf == NULL) | 721 | if (buf == NULL) |
703 | return 0; | 722 | return -ENOMEM; |
704 | 723 | ||
705 | len += snprintf(buf + len, size - len, | 724 | len += snprintf(buf + len, size - len, |
706 | "%18s : %10u\n", "CRC ERR", | 725 | "%18s : %10u\n", "CRC ERR", |
@@ -751,6 +770,9 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
751 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | 770 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); |
752 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | 771 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); |
753 | 772 | ||
773 | if (len > size) | ||
774 | len = size; | ||
775 | |||
754 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | 776 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); |
755 | kfree(buf); | 777 | kfree(buf); |
756 | 778 | ||
@@ -802,7 +824,7 @@ static ssize_t read_file_regidx(struct file *file, char __user *user_buf, | |||
802 | char buf[32]; | 824 | char buf[32]; |
803 | unsigned int len; | 825 | unsigned int len; |
804 | 826 | ||
805 | len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.regidx); | 827 | len = sprintf(buf, "0x%08x\n", sc->debug.regidx); |
806 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 828 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
807 | } | 829 | } |
808 | 830 | ||
@@ -816,7 +838,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, | |||
816 | 838 | ||
817 | len = min(count, sizeof(buf) - 1); | 839 | len = min(count, sizeof(buf) - 1); |
818 | if (copy_from_user(buf, user_buf, len)) | 840 | if (copy_from_user(buf, user_buf, len)) |
819 | return -EINVAL; | 841 | return -EFAULT; |
820 | 842 | ||
821 | buf[len] = '\0'; | 843 | buf[len] = '\0'; |
822 | if (strict_strtoul(buf, 0, ®idx)) | 844 | if (strict_strtoul(buf, 0, ®idx)) |
@@ -843,7 +865,7 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf, | |||
843 | u32 regval; | 865 | u32 regval; |
844 | 866 | ||
845 | regval = REG_READ_D(ah, sc->debug.regidx); | 867 | regval = REG_READ_D(ah, sc->debug.regidx); |
846 | len = snprintf(buf, sizeof(buf), "0x%08x\n", regval); | 868 | len = sprintf(buf, "0x%08x\n", regval); |
847 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 869 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
848 | } | 870 | } |
849 | 871 | ||
@@ -858,7 +880,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, | |||
858 | 880 | ||
859 | len = min(count, sizeof(buf) - 1); | 881 | len = min(count, sizeof(buf) - 1); |
860 | if (copy_from_user(buf, user_buf, len)) | 882 | if (copy_from_user(buf, user_buf, len)) |
861 | return -EINVAL; | 883 | return -EFAULT; |
862 | 884 | ||
863 | buf[len] = '\0'; | 885 | buf[len] = '\0'; |
864 | if (strict_strtoul(buf, 0, ®val)) | 886 | if (strict_strtoul(buf, 0, ®val)) |
@@ -934,6 +956,10 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
934 | sc->debug.debugfs_phy, sc, &fops_regval)) | 956 | sc->debug.debugfs_phy, sc, &fops_regval)) |
935 | goto err; | 957 | goto err; |
936 | 958 | ||
959 | if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, | ||
960 | sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) | ||
961 | goto err; | ||
962 | |||
937 | sc->debug.regidx = 0; | 963 | sc->debug.regidx = 0; |
938 | return 0; | 964 | return 0; |
939 | err: | 965 | err: |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 5147b8709e10..5d21704e87ff 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -53,6 +53,7 @@ struct ath_buf; | |||
53 | * @cabend: RX End of CAB traffic | 53 | * @cabend: RX End of CAB traffic |
54 | * @dtimsync: DTIM sync lossage | 54 | * @dtimsync: DTIM sync lossage |
55 | * @dtim: RX Beacon with DTIM | 55 | * @dtim: RX Beacon with DTIM |
56 | * @bb_watchdog: Baseband watchdog | ||
56 | */ | 57 | */ |
57 | struct ath_interrupt_stats { | 58 | struct ath_interrupt_stats { |
58 | u32 total; | 59 | u32 total; |
@@ -76,6 +77,7 @@ struct ath_interrupt_stats { | |||
76 | u32 cabend; | 77 | u32 cabend; |
77 | u32 dtimsync; | 78 | u32 dtimsync; |
78 | u32 dtim; | 79 | u32 dtim; |
80 | u32 bb_watchdog; | ||
79 | }; | 81 | }; |
80 | 82 | ||
81 | struct ath_rc_stats { | 83 | struct ath_rc_stats { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index ca8704a9d7ac..1266333f586d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -24,6 +24,14 @@ static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | |||
24 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | 24 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); |
25 | } | 25 | } |
26 | 26 | ||
27 | void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val) | ||
28 | { | ||
29 | REG_WRITE(ah, reg, val); | ||
30 | |||
31 | if (ah->config.analog_shiftreg) | ||
32 | udelay(100); | ||
33 | } | ||
34 | |||
27 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, | 35 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, |
28 | u32 shift, u32 val) | 36 | u32 shift, u32 val) |
29 | { | 37 | { |
@@ -250,6 +258,27 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | |||
250 | return twiceMaxEdgePower; | 258 | return twiceMaxEdgePower; |
251 | } | 259 | } |
252 | 260 | ||
261 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) | ||
262 | { | ||
263 | struct ath_common *common = ath9k_hw_common(ah); | ||
264 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
265 | |||
266 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
267 | case 1: | ||
268 | break; | ||
269 | case 2: | ||
270 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
271 | break; | ||
272 | case 3: | ||
273 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
274 | break; | ||
275 | default: | ||
276 | ath_print(common, ATH_DBG_EEPROM, | ||
277 | "Invalid chainmask configuration\n"); | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | |||
253 | int ath9k_hw_eeprom_init(struct ath_hw *ah) | 282 | int ath9k_hw_eeprom_init(struct ath_hw *ah) |
254 | { | 283 | { |
255 | int status; | 284 | int status; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 21354c15a9a9..bdd8aa054b80 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -263,7 +263,8 @@ enum eeprom_param { | |||
263 | EEP_PWR_TABLE_OFFSET, | 263 | EEP_PWR_TABLE_OFFSET, |
264 | EEP_DRIVE_STRENGTH, | 264 | EEP_DRIVE_STRENGTH, |
265 | EEP_INTERNAL_REGULATOR, | 265 | EEP_INTERNAL_REGULATOR, |
266 | EEP_SWREG | 266 | EEP_SWREG, |
267 | EEP_PAPRD, | ||
267 | }; | 268 | }; |
268 | 269 | ||
269 | enum ar5416_rates { | 270 | enum ar5416_rates { |
@@ -679,6 +680,7 @@ struct eeprom_ops { | |||
679 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); | 680 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); |
680 | }; | 681 | }; |
681 | 682 | ||
683 | void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val); | ||
682 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, | 684 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, |
683 | u32 shift, u32 val); | 685 | u32 shift, u32 val); |
684 | int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, | 686 | int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, |
@@ -704,6 +706,7 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, | |||
704 | u16 numRates, bool isHt40Target); | 706 | u16 numRates, bool isHt40Target); |
705 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | 707 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, |
706 | bool is2GHz, int num_band_edges); | 708 | bool is2GHz, int num_band_edges); |
709 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); | ||
707 | int ath9k_hw_eeprom_init(struct ath_hw *ah); | 710 | int ath9k_hw_eeprom_init(struct ath_hw *ah); |
708 | 711 | ||
709 | #define ar5416_get_ntxchains(_txchainmask) \ | 712 | #define ar5416_get_ntxchains(_txchainmask) \ |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 41a77d1bd439..e25a2abbf561 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -249,6 +249,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
249 | struct chan_centers centers; | 249 | struct chan_centers centers; |
250 | #define PD_GAIN_BOUNDARY_DEFAULT 58; | 250 | #define PD_GAIN_BOUNDARY_DEFAULT 58; |
251 | 251 | ||
252 | memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); | ||
252 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 253 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
253 | 254 | ||
254 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | 255 | for (numPiers = 0; numPiers < availPiers; numPiers++) { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index b471db5fb82d..39a41053705f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -17,17 +17,19 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9002_phy.h" | 18 | #include "ar9002_phy.h" |
19 | 19 | ||
20 | static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) | 20 | #define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16)) |
21 | |||
22 | static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) | ||
21 | { | 23 | { |
22 | return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; | 24 | return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; |
23 | } | 25 | } |
24 | 26 | ||
25 | static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) | 27 | static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) |
26 | { | 28 | { |
27 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; | 29 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; |
28 | } | 30 | } |
29 | 31 | ||
30 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | 32 | static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) |
31 | { | 33 | { |
32 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 34 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
33 | struct ath_common *common = ath9k_hw_common(ah); | 35 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -40,20 +42,20 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | |||
40 | "Reading from EEPROM, not flash\n"); | 42 | "Reading from EEPROM, not flash\n"); |
41 | } | 43 | } |
42 | 44 | ||
43 | for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | 45 | for (addr = 0; addr < NUM_EEP_WORDS; addr++) { |
44 | addr++) { | 46 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, |
45 | if (!ath9k_hw_nvram_read(common, | 47 | eep_data)) { |
46 | addr + eep_start_loc, eep_data)) { | ||
47 | ath_print(common, ATH_DBG_EEPROM, | 48 | ath_print(common, ATH_DBG_EEPROM, |
48 | "Unable to read eeprom region\n"); | 49 | "Unable to read eeprom region\n"); |
49 | return false; | 50 | return false; |
50 | } | 51 | } |
51 | eep_data++; | 52 | eep_data++; |
52 | } | 53 | } |
54 | |||
53 | return true; | 55 | return true; |
54 | } | 56 | } |
55 | 57 | ||
56 | static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | 58 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) |
57 | { | 59 | { |
58 | u32 sum = 0, el, integer; | 60 | u32 sum = 0, el, integer; |
59 | u16 temp, word, magic, magic2, *eepdata; | 61 | u16 temp, word, magic, magic2, *eepdata; |
@@ -63,8 +65,8 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
63 | struct ath_common *common = ath9k_hw_common(ah); | 65 | struct ath_common *common = ath9k_hw_common(ah); |
64 | 66 | ||
65 | if (!ath9k_hw_use_flash(ah)) { | 67 | if (!ath9k_hw_use_flash(ah)) { |
66 | if (!ath9k_hw_nvram_read(common, | 68 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, |
67 | AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | 69 | &magic)) { |
68 | ath_print(common, ATH_DBG_FATAL, | 70 | ath_print(common, ATH_DBG_FATAL, |
69 | "Reading Magic # failed\n"); | 71 | "Reading Magic # failed\n"); |
70 | return false; | 72 | return false; |
@@ -72,6 +74,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
72 | 74 | ||
73 | ath_print(common, ATH_DBG_EEPROM, | 75 | ath_print(common, ATH_DBG_EEPROM, |
74 | "Read Magic = 0x%04X\n", magic); | 76 | "Read Magic = 0x%04X\n", magic); |
77 | |||
75 | if (magic != AR5416_EEPROM_MAGIC) { | 78 | if (magic != AR5416_EEPROM_MAGIC) { |
76 | magic2 = swab16(magic); | 79 | magic2 = swab16(magic); |
77 | 80 | ||
@@ -79,9 +82,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
79 | need_swap = true; | 82 | need_swap = true; |
80 | eepdata = (u16 *)(&ah->eeprom); | 83 | eepdata = (u16 *)(&ah->eeprom); |
81 | 84 | ||
82 | for (addr = 0; | 85 | for (addr = 0; addr < NUM_EEP_WORDS; addr++) { |
83 | addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
84 | addr++) { | ||
85 | temp = swab16(*eepdata); | 86 | temp = swab16(*eepdata); |
86 | *eepdata = temp; | 87 | *eepdata = temp; |
87 | eepdata++; | 88 | eepdata++; |
@@ -89,13 +90,14 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
89 | } else { | 90 | } else { |
90 | ath_print(common, ATH_DBG_FATAL, | 91 | ath_print(common, ATH_DBG_FATAL, |
91 | "Invalid EEPROM Magic. " | 92 | "Invalid EEPROM Magic. " |
92 | "endianness mismatch.\n"); | 93 | "Endianness mismatch.\n"); |
93 | return -EINVAL; | 94 | return -EINVAL; |
94 | } | 95 | } |
95 | } | 96 | } |
96 | } | 97 | } |
97 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? | 98 | |
98 | "True" : "False"); | 99 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", |
100 | need_swap ? "True" : "False"); | ||
99 | 101 | ||
100 | if (need_swap) | 102 | if (need_swap) |
101 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | 103 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); |
@@ -108,6 +110,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
108 | el = el / sizeof(u16); | 110 | el = el / sizeof(u16); |
109 | 111 | ||
110 | eepdata = (u16 *)(&ah->eeprom); | 112 | eepdata = (u16 *)(&ah->eeprom); |
113 | |||
111 | for (i = 0; i < el; i++) | 114 | for (i = 0; i < el; i++) |
112 | sum ^= *eepdata++; | 115 | sum ^= *eepdata++; |
113 | 116 | ||
@@ -161,7 +164,7 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
161 | return 0; | 164 | return 0; |
162 | } | 165 | } |
163 | 166 | ||
164 | static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | 167 | static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, |
165 | enum eeprom_param param) | 168 | enum eeprom_param param) |
166 | { | 169 | { |
167 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 170 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
@@ -170,6 +173,7 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | |||
170 | u16 ver_minor; | 173 | u16 ver_minor; |
171 | 174 | ||
172 | ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; | 175 | ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; |
176 | |||
173 | switch (param) { | 177 | switch (param) { |
174 | case EEP_NFTHRESH_2: | 178 | case EEP_NFTHRESH_2: |
175 | return pModal->noiseFloorThreshCh[0]; | 179 | return pModal->noiseFloorThreshCh[0]; |
@@ -214,29 +218,30 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | |||
214 | } | 218 | } |
215 | } | 219 | } |
216 | 220 | ||
217 | 221 | static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |
218 | static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | 222 | struct ath9k_channel *chan, |
219 | struct ath9k_channel *chan, | 223 | struct cal_data_per_freq_ar9287 *pRawDataSet, |
220 | struct cal_data_per_freq_ar9287 *pRawDataSet, | 224 | u8 *bChans, u16 availPiers, |
221 | u8 *bChans, u16 availPiers, | 225 | u16 tPdGainOverlap, |
222 | u16 tPdGainOverlap, int16_t *pMinCalPower, | 226 | int16_t *pMinCalPower, |
223 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | 227 | u16 *pPdGainBoundaries, |
224 | u16 numXpdGains) | 228 | u8 *pPDADCValues, |
229 | u16 numXpdGains) | ||
225 | { | 230 | { |
226 | #define TMP_VAL_VPD_TABLE \ | 231 | #define TMP_VAL_VPD_TABLE \ |
227 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | 232 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); |
228 | 233 | ||
229 | int i, j, k; | 234 | int i, j, k; |
230 | int16_t ss; | 235 | int16_t ss; |
231 | u16 idxL = 0, idxR = 0, numPiers; | 236 | u16 idxL = 0, idxR = 0, numPiers; |
232 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | 237 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; |
233 | u8 minPwrT4[AR9287_NUM_PD_GAINS]; | 238 | u8 minPwrT4[AR9287_NUM_PD_GAINS]; |
234 | u8 maxPwrT4[AR9287_NUM_PD_GAINS]; | 239 | u8 maxPwrT4[AR9287_NUM_PD_GAINS]; |
235 | int16_t vpdStep; | 240 | int16_t vpdStep; |
236 | int16_t tmpVal; | 241 | int16_t tmpVal; |
237 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | 242 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; |
238 | bool match; | 243 | bool match; |
239 | int16_t minDelta = 0; | 244 | int16_t minDelta = 0; |
240 | struct chan_centers centers; | 245 | struct chan_centers centers; |
241 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | 246 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] |
242 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | 247 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; |
@@ -245,6 +250,7 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
245 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | 250 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] |
246 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | 251 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; |
247 | 252 | ||
253 | memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); | ||
248 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 254 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
249 | 255 | ||
250 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | 256 | for (numPiers = 0; numPiers < availPiers; numPiers++) { |
@@ -253,18 +259,18 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
253 | } | 259 | } |
254 | 260 | ||
255 | match = ath9k_hw_get_lower_upper_index( | 261 | match = ath9k_hw_get_lower_upper_index( |
256 | (u8)FREQ2FBIN(centers.synth_center, | 262 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), |
257 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | 263 | bChans, numPiers, &idxL, &idxR); |
258 | &idxL, &idxR); | ||
259 | 264 | ||
260 | if (match) { | 265 | if (match) { |
261 | for (i = 0; i < numXpdGains; i++) { | 266 | for (i = 0; i < numXpdGains; i++) { |
262 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | 267 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; |
263 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | 268 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; |
264 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | 269 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], |
265 | pRawDataSet[idxL].pwrPdg[i], | 270 | pRawDataSet[idxL].pwrPdg[i], |
266 | pRawDataSet[idxL].vpdPdg[i], | 271 | pRawDataSet[idxL].vpdPdg[i], |
267 | AR9287_PD_GAIN_ICEPTS, vpdTableI[i]); | 272 | AR9287_PD_GAIN_ICEPTS, |
273 | vpdTableI[i]); | ||
268 | } | 274 | } |
269 | } else { | 275 | } else { |
270 | for (i = 0; i < numXpdGains; i++) { | 276 | for (i = 0; i < numXpdGains; i++) { |
@@ -275,61 +281,59 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
275 | 281 | ||
276 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | 282 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); |
277 | 283 | ||
278 | maxPwrT4[i] = | 284 | maxPwrT4[i] = min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], |
279 | min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], | 285 | pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); |
280 | pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); | ||
281 | 286 | ||
282 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | 287 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], |
283 | pPwrL, pVpdL, | 288 | pPwrL, pVpdL, |
284 | AR9287_PD_GAIN_ICEPTS, | 289 | AR9287_PD_GAIN_ICEPTS, |
285 | vpdTableL[i]); | 290 | vpdTableL[i]); |
286 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | 291 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], |
287 | pPwrR, pVpdR, | 292 | pPwrR, pVpdR, |
288 | AR9287_PD_GAIN_ICEPTS, | 293 | AR9287_PD_GAIN_ICEPTS, |
289 | vpdTableR[i]); | 294 | vpdTableR[i]); |
290 | 295 | ||
291 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | 296 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { |
292 | vpdTableI[i][j] = | 297 | vpdTableI[i][j] = (u8)(ath9k_hw_interpolate( |
293 | (u8)(ath9k_hw_interpolate((u16) | 298 | (u16)FREQ2FBIN(centers. synth_center, |
294 | FREQ2FBIN(centers. synth_center, | 299 | IS_CHAN_2GHZ(chan)), |
295 | IS_CHAN_2GHZ(chan)), | 300 | bChans[idxL], bChans[idxR], |
296 | bChans[idxL], bChans[idxR], | 301 | vpdTableL[i][j], vpdTableR[i][j])); |
297 | vpdTableL[i][j], vpdTableR[i][j])); | ||
298 | } | 302 | } |
299 | } | 303 | } |
300 | } | 304 | } |
301 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
302 | 305 | ||
306 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
303 | k = 0; | 307 | k = 0; |
308 | |||
304 | for (i = 0; i < numXpdGains; i++) { | 309 | for (i = 0; i < numXpdGains; i++) { |
305 | if (i == (numXpdGains - 1)) | 310 | if (i == (numXpdGains - 1)) |
306 | pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2); | 311 | pPdGainBoundaries[i] = |
312 | (u16)(maxPwrT4[i] / 2); | ||
307 | else | 313 | else |
308 | pPdGainBoundaries[i] = (u16)((maxPwrT4[i] + | 314 | pPdGainBoundaries[i] = |
309 | minPwrT4[i+1]) / 4); | 315 | (u16)((maxPwrT4[i] + minPwrT4[i+1]) / 4); |
310 | 316 | ||
311 | pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, | 317 | pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, |
312 | pPdGainBoundaries[i]); | 318 | pPdGainBoundaries[i]); |
313 | 319 | ||
314 | 320 | ||
315 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | 321 | minDelta = 0; |
316 | minDelta = pPdGainBoundaries[0] - 23; | ||
317 | pPdGainBoundaries[0] = 23; | ||
318 | } else | ||
319 | minDelta = 0; | ||
320 | 322 | ||
321 | if (i == 0) { | 323 | if (i == 0) { |
322 | if (AR_SREV_9280_10_OR_LATER(ah)) | 324 | if (AR_SREV_9280_10_OR_LATER(ah)) |
323 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | 325 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); |
324 | else | 326 | else |
325 | ss = 0; | 327 | ss = 0; |
326 | } else | 328 | } else { |
327 | ss = (int16_t)((pPdGainBoundaries[i-1] - | 329 | ss = (int16_t)((pPdGainBoundaries[i-1] - |
328 | (minPwrT4[i] / 2)) - | 330 | (minPwrT4[i] / 2)) - |
329 | tPdGainOverlap + 1 + minDelta); | 331 | tPdGainOverlap + 1 + minDelta); |
332 | } | ||
330 | 333 | ||
331 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | 334 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); |
332 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | 335 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); |
336 | |||
333 | while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { | 337 | while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { |
334 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | 338 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); |
335 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | 339 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); |
@@ -348,12 +352,13 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
348 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | 352 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - |
349 | vpdTableI[i][sizeCurrVpdTable - 2]); | 353 | vpdTableI[i][sizeCurrVpdTable - 2]); |
350 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | 354 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); |
355 | |||
351 | if (tgtIndex > maxIndex) { | 356 | if (tgtIndex > maxIndex) { |
352 | while ((ss <= tgtIndex) && | 357 | while ((ss <= tgtIndex) && |
353 | (k < (AR9287_NUM_PDADC_VALUES - 1))) { | 358 | (k < (AR9287_NUM_PDADC_VALUES - 1))) { |
354 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | 359 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; |
355 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | 360 | pPDADCValues[k++] = |
356 | 255 : tmpVal); | 361 | (u8)((tmpVal > 255) ? 255 : tmpVal); |
357 | ss++; | 362 | ss++; |
358 | } | 363 | } |
359 | } | 364 | } |
@@ -375,10 +380,9 @@ static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
375 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | 380 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, |
376 | struct ath9k_channel *chan, | 381 | struct ath9k_channel *chan, |
377 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, | 382 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, |
378 | u8 *pCalChans, u16 availPiers, | 383 | u8 *pCalChans, u16 availPiers, int8_t *pPwr) |
379 | int8_t *pPwr) | ||
380 | { | 384 | { |
381 | u16 idxL = 0, idxR = 0, numPiers; | 385 | u16 idxL = 0, idxR = 0, numPiers; |
382 | bool match; | 386 | bool match; |
383 | struct chan_centers centers; | 387 | struct chan_centers centers; |
384 | 388 | ||
@@ -390,15 +394,14 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | |||
390 | } | 394 | } |
391 | 395 | ||
392 | match = ath9k_hw_get_lower_upper_index( | 396 | match = ath9k_hw_get_lower_upper_index( |
393 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | 397 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), |
394 | pCalChans, numPiers, | 398 | pCalChans, numPiers, &idxL, &idxR); |
395 | &idxL, &idxR); | ||
396 | 399 | ||
397 | if (match) { | 400 | if (match) { |
398 | *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; | 401 | *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; |
399 | } else { | 402 | } else { |
400 | *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + | 403 | *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + |
401 | (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | 404 | (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; |
402 | } | 405 | } |
403 | 406 | ||
404 | } | 407 | } |
@@ -409,16 +412,22 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | |||
409 | u32 tmpVal; | 412 | u32 tmpVal; |
410 | u32 a; | 413 | u32 a; |
411 | 414 | ||
415 | /* Enable OLPC for chain 0 */ | ||
416 | |||
412 | tmpVal = REG_READ(ah, 0xa270); | 417 | tmpVal = REG_READ(ah, 0xa270); |
413 | tmpVal = tmpVal & 0xFCFFFFFF; | 418 | tmpVal = tmpVal & 0xFCFFFFFF; |
414 | tmpVal = tmpVal | (0x3 << 24); | 419 | tmpVal = tmpVal | (0x3 << 24); |
415 | REG_WRITE(ah, 0xa270, tmpVal); | 420 | REG_WRITE(ah, 0xa270, tmpVal); |
416 | 421 | ||
422 | /* Enable OLPC for chain 1 */ | ||
423 | |||
417 | tmpVal = REG_READ(ah, 0xb270); | 424 | tmpVal = REG_READ(ah, 0xb270); |
418 | tmpVal = tmpVal & 0xFCFFFFFF; | 425 | tmpVal = tmpVal & 0xFCFFFFFF; |
419 | tmpVal = tmpVal | (0x3 << 24); | 426 | tmpVal = tmpVal | (0x3 << 24); |
420 | REG_WRITE(ah, 0xb270, tmpVal); | 427 | REG_WRITE(ah, 0xb270, tmpVal); |
421 | 428 | ||
429 | /* Write the OLPC ref power for chain 0 */ | ||
430 | |||
422 | if (chain == 0) { | 431 | if (chain == 0) { |
423 | tmpVal = REG_READ(ah, 0xa398); | 432 | tmpVal = REG_READ(ah, 0xa398); |
424 | tmpVal = tmpVal & 0xff00ffff; | 433 | tmpVal = tmpVal & 0xff00ffff; |
@@ -427,6 +436,8 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | |||
427 | REG_WRITE(ah, 0xa398, tmpVal); | 436 | REG_WRITE(ah, 0xa398, tmpVal); |
428 | } | 437 | } |
429 | 438 | ||
439 | /* Write the OLPC ref power for chain 1 */ | ||
440 | |||
430 | if (chain == 1) { | 441 | if (chain == 1) { |
431 | tmpVal = REG_READ(ah, 0xb398); | 442 | tmpVal = REG_READ(ah, 0xb398); |
432 | tmpVal = tmpVal & 0xff00ffff; | 443 | tmpVal = tmpVal & 0xff00ffff; |
@@ -436,28 +447,29 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | |||
436 | } | 447 | } |
437 | } | 448 | } |
438 | 449 | ||
439 | static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | 450 | static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, |
440 | struct ath9k_channel *chan, | 451 | struct ath9k_channel *chan, |
441 | int16_t *pTxPowerIndexOffset) | 452 | int16_t *pTxPowerIndexOffset) |
442 | { | 453 | { |
443 | struct ath_common *common = ath9k_hw_common(ah); | ||
444 | struct cal_data_per_freq_ar9287 *pRawDataset; | 454 | struct cal_data_per_freq_ar9287 *pRawDataset; |
445 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; | 455 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; |
446 | u8 *pCalBChans = NULL; | 456 | u8 *pCalBChans = NULL; |
447 | u16 pdGainOverlap_t2; | 457 | u16 pdGainOverlap_t2; |
448 | u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; | 458 | u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; |
449 | u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; | 459 | u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; |
450 | u16 numPiers = 0, i, j; | 460 | u16 numPiers = 0, i, j; |
451 | int16_t tMinCalPower; | 461 | int16_t tMinCalPower; |
452 | u16 numXpdGain, xpdMask; | 462 | u16 numXpdGain, xpdMask; |
453 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | 463 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; |
454 | u32 reg32, regOffset, regChainOffset; | 464 | u32 reg32, regOffset, regChainOffset, regval; |
455 | int16_t modalIdx, diff = 0; | 465 | int16_t modalIdx, diff = 0; |
456 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 466 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
467 | |||
457 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | 468 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; |
458 | xpdMask = pEepData->modalHeader.xpdGain; | 469 | xpdMask = pEepData->modalHeader.xpdGain; |
470 | |||
459 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | 471 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= |
460 | AR9287_EEP_MINOR_VER_2) | 472 | AR9287_EEP_MINOR_VER_2) |
461 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; | 473 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; |
462 | else | 474 | else |
463 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | 475 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), |
@@ -466,15 +478,16 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | |||
466 | if (IS_CHAN_2GHZ(chan)) { | 478 | if (IS_CHAN_2GHZ(chan)) { |
467 | pCalBChans = pEepData->calFreqPier2G; | 479 | pCalBChans = pEepData->calFreqPier2G; |
468 | numPiers = AR9287_NUM_2G_CAL_PIERS; | 480 | numPiers = AR9287_NUM_2G_CAL_PIERS; |
469 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 481 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
470 | pRawDatasetOpenLoop = | 482 | pRawDatasetOpenLoop = |
471 | (struct cal_data_op_loop_ar9287 *) | 483 | (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; |
472 | pEepData->calPierData2G[0]; | ||
473 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; | 484 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; |
474 | } | 485 | } |
475 | } | 486 | } |
476 | 487 | ||
477 | numXpdGain = 0; | 488 | numXpdGain = 0; |
489 | |||
490 | /* Calculate the value of xpdgains from the xpdGain Mask */ | ||
478 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { | 491 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { |
479 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { | 492 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { |
480 | if (numXpdGain >= AR9287_NUM_PD_GAINS) | 493 | if (numXpdGain >= AR9287_NUM_PD_GAINS) |
@@ -496,99 +509,80 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | |||
496 | 509 | ||
497 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | 510 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { |
498 | regChainOffset = i * 0x1000; | 511 | regChainOffset = i * 0x1000; |
512 | |||
499 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | 513 | if (pEepData->baseEepHeader.txMask & (1 << i)) { |
500 | pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) | 514 | pRawDatasetOpenLoop = |
501 | pEepData->calPierData2G[i]; | 515 | (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; |
502 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 516 | |
517 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
503 | int8_t txPower; | 518 | int8_t txPower; |
504 | ar9287_eeprom_get_tx_gain_index(ah, chan, | 519 | ar9287_eeprom_get_tx_gain_index(ah, chan, |
505 | pRawDatasetOpenLoop, | 520 | pRawDatasetOpenLoop, |
506 | pCalBChans, numPiers, | 521 | pCalBChans, numPiers, |
507 | &txPower); | 522 | &txPower); |
508 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); | 523 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); |
509 | } else { | 524 | } else { |
510 | pRawDataset = | 525 | pRawDataset = |
511 | (struct cal_data_per_freq_ar9287 *) | 526 | (struct cal_data_per_freq_ar9287 *) |
512 | pEepData->calPierData2G[i]; | 527 | pEepData->calPierData2G[i]; |
513 | ath9k_hw_get_AR9287_gain_boundaries_pdadcs( | 528 | |
514 | ah, chan, pRawDataset, | 529 | ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan, |
515 | pCalBChans, numPiers, | 530 | pRawDataset, |
516 | pdGainOverlap_t2, | 531 | pCalBChans, numPiers, |
517 | &tMinCalPower, gainBoundaries, | 532 | pdGainOverlap_t2, |
518 | pdadcValues, numXpdGain); | 533 | &tMinCalPower, |
534 | gainBoundaries, | ||
535 | pdadcValues, | ||
536 | numXpdGain); | ||
519 | } | 537 | } |
520 | 538 | ||
521 | if (i == 0) { | 539 | if (i == 0) { |
522 | if (!ath9k_hw_AR9287_get_eeprom( | 540 | if (!ath9k_hw_ar9287_get_eeprom(ah, |
523 | ah, EEP_OL_PWRCTRL)) { | 541 | EEP_OL_PWRCTRL)) { |
524 | REG_WRITE(ah, AR_PHY_TPCRG5 + | 542 | |
525 | regChainOffset, | 543 | regval = SM(pdGainOverlap_t2, |
526 | SM(pdGainOverlap_t2, | 544 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
527 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | 545 | | SM(gainBoundaries[0], |
528 | SM(gainBoundaries[0], | 546 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
529 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 547 | | SM(gainBoundaries[1], |
530 | | SM(gainBoundaries[1], | 548 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
531 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 549 | | SM(gainBoundaries[2], |
532 | | SM(gainBoundaries[2], | 550 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
533 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 551 | | SM(gainBoundaries[3], |
534 | | SM(gainBoundaries[3], | 552 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4); |
535 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | 553 | |
554 | REG_WRITE(ah, | ||
555 | AR_PHY_TPCRG5 + regChainOffset, | ||
556 | regval); | ||
536 | } | 557 | } |
537 | } | 558 | } |
538 | 559 | ||
539 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != | 560 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != |
540 | pEepData->baseEepHeader.pwrTableOffset) { | 561 | pEepData->baseEepHeader.pwrTableOffset) { |
541 | diff = (u16) | 562 | diff = (u16)(pEepData->baseEepHeader.pwrTableOffset - |
542 | (pEepData->baseEepHeader.pwrTableOffset | 563 | (int32_t)AR9287_PWR_TABLE_OFFSET_DB); |
543 | - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); | ||
544 | diff *= 2; | 564 | diff *= 2; |
545 | 565 | ||
546 | for (j = 0; | 566 | for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++) |
547 | j < ((u16)AR9287_NUM_PDADC_VALUES-diff); | ||
548 | j++) | ||
549 | pdadcValues[j] = pdadcValues[j+diff]; | 567 | pdadcValues[j] = pdadcValues[j+diff]; |
550 | 568 | ||
551 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); | 569 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); |
552 | j < AR9287_NUM_PDADC_VALUES; j++) | 570 | j < AR9287_NUM_PDADC_VALUES; j++) |
553 | pdadcValues[j] = | 571 | pdadcValues[j] = |
554 | pdadcValues[ | 572 | pdadcValues[AR9287_NUM_PDADC_VALUES-diff]; |
555 | AR9287_NUM_PDADC_VALUES-diff]; | ||
556 | } | 573 | } |
557 | 574 | ||
558 | if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 575 | if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
559 | regOffset = AR_PHY_BASE + (672 << 2) + | 576 | regOffset = AR_PHY_BASE + |
560 | regChainOffset; | 577 | (672 << 2) + regChainOffset; |
561 | for (j = 0; j < 32; j++) { | ||
562 | reg32 = ((pdadcValues[4*j + 0] | ||
563 | & 0xFF) << 0) | | ||
564 | ((pdadcValues[4*j + 1] | ||
565 | & 0xFF) << 8) | | ||
566 | ((pdadcValues[4*j + 2] | ||
567 | & 0xFF) << 16) | | ||
568 | ((pdadcValues[4*j + 3] | ||
569 | & 0xFF) << 24) ; | ||
570 | REG_WRITE(ah, regOffset, reg32); | ||
571 | 578 | ||
572 | ath_print(common, ATH_DBG_EEPROM, | 579 | for (j = 0; j < 32; j++) { |
573 | "PDADC (%d,%4x): %4.4x " | 580 | reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) |
574 | "%8.8x\n", | 581 | | ((pdadcValues[4*j + 1] & 0xFF) << 8) |
575 | i, regChainOffset, regOffset, | 582 | | ((pdadcValues[4*j + 2] & 0xFF) << 16) |
576 | reg32); | 583 | | ((pdadcValues[4*j + 3] & 0xFF) << 24); |
577 | |||
578 | ath_print(common, ATH_DBG_EEPROM, | ||
579 | "PDADC: Chain %d | " | ||
580 | "PDADC %3d Value %3d | " | ||
581 | "PDADC %3d Value %3d | " | ||
582 | "PDADC %3d Value %3d | " | ||
583 | "PDADC %3d Value %3d |\n", | ||
584 | i, 4 * j, pdadcValues[4 * j], | ||
585 | 4 * j + 1, | ||
586 | pdadcValues[4 * j + 1], | ||
587 | 4 * j + 2, | ||
588 | pdadcValues[4 * j + 2], | ||
589 | 4 * j + 3, | ||
590 | pdadcValues[4 * j + 3]); | ||
591 | 584 | ||
585 | REG_WRITE(ah, regOffset, reg32); | ||
592 | regOffset += 4; | 586 | regOffset += 4; |
593 | } | 587 | } |
594 | } | 588 | } |
@@ -598,30 +592,45 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | |||
598 | *pTxPowerIndexOffset = 0; | 592 | *pTxPowerIndexOffset = 0; |
599 | } | 593 | } |
600 | 594 | ||
601 | static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | 595 | static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, |
602 | struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, | 596 | struct ath9k_channel *chan, |
603 | u16 AntennaReduction, u16 twiceMaxRegulatoryPower, | 597 | int16_t *ratesArray, |
604 | u16 powerLimit) | 598 | u16 cfgCtl, |
599 | u16 AntennaReduction, | ||
600 | u16 twiceMaxRegulatoryPower, | ||
601 | u16 powerLimit) | ||
605 | { | 602 | { |
603 | #define CMP_CTL \ | ||
604 | (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | ||
605 | pEepData->ctlIndex[i]) | ||
606 | |||
607 | #define CMP_NO_CTL \ | ||
608 | (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | ||
609 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) | ||
610 | |||
606 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | 611 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 |
607 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | 612 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 |
613 | |||
608 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 614 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
609 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 615 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; |
610 | static const u16 tpScaleReductionTable[5] = | 616 | static const u16 tpScaleReductionTable[5] = |
611 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | 617 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; |
612 | int i; | 618 | int i; |
613 | int16_t twiceLargestAntenna; | 619 | int16_t twiceLargestAntenna; |
614 | struct cal_ctl_data_ar9287 *rep; | 620 | struct cal_ctl_data_ar9287 *rep; |
615 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, | 621 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, |
616 | targetPowerCck = {0, {0, 0, 0, 0} }; | 622 | targetPowerCck = {0, {0, 0, 0, 0} }; |
617 | struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, | 623 | struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, |
618 | targetPowerCckExt = {0, {0, 0, 0, 0} }; | 624 | targetPowerCckExt = {0, {0, 0, 0, 0} }; |
619 | struct cal_target_power_ht targetPowerHt20, | 625 | struct cal_target_power_ht targetPowerHt20, |
620 | targetPowerHt40 = {0, {0, 0, 0, 0} }; | 626 | targetPowerHt40 = {0, {0, 0, 0, 0} }; |
621 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | 627 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; |
622 | u16 ctlModesFor11g[] = | 628 | u16 ctlModesFor11g[] = {CTL_11B, |
623 | {CTL_11B, CTL_11G, CTL_2GHT20, | 629 | CTL_11G, |
624 | CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40}; | 630 | CTL_2GHT20, |
631 | CTL_11B_EXT, | ||
632 | CTL_11G_EXT, | ||
633 | CTL_2GHT40}; | ||
625 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; | 634 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; |
626 | struct chan_centers centers; | 635 | struct chan_centers centers; |
627 | int tx_chainmask; | 636 | int tx_chainmask; |
@@ -631,19 +640,28 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
631 | 640 | ||
632 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 641 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
633 | 642 | ||
643 | /* Compute TxPower reduction due to Antenna Gain */ | ||
634 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], | 644 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], |
635 | pEepData->modalHeader.antennaGainCh[1]); | 645 | pEepData->modalHeader.antennaGainCh[1]); |
646 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - | ||
647 | twiceLargestAntenna, 0); | ||
636 | 648 | ||
637 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - | 649 | /* |
638 | twiceLargestAntenna, 0); | 650 | * scaledPower is the minimum of the user input power level |
639 | 651 | * and the regulatory allowed power level. | |
652 | */ | ||
640 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | 653 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; |
654 | |||
641 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) | 655 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) |
642 | maxRegAllowedPower -= | 656 | maxRegAllowedPower -= |
643 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); | 657 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); |
644 | 658 | ||
645 | scaledPower = min(powerLimit, maxRegAllowedPower); | 659 | scaledPower = min(powerLimit, maxRegAllowedPower); |
646 | 660 | ||
661 | /* | ||
662 | * Reduce scaled Power by number of chains active | ||
663 | * to get the per chain tx power level. | ||
664 | */ | ||
647 | switch (ar5416_get_ntxchains(tx_chainmask)) { | 665 | switch (ar5416_get_ntxchains(tx_chainmask)) { |
648 | case 1: | 666 | case 1: |
649 | break; | 667 | break; |
@@ -656,9 +674,14 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
656 | } | 674 | } |
657 | scaledPower = max((u16)0, scaledPower); | 675 | scaledPower = max((u16)0, scaledPower); |
658 | 676 | ||
677 | /* | ||
678 | * Get TX power from EEPROM. | ||
679 | */ | ||
659 | if (IS_CHAN_2GHZ(chan)) { | 680 | if (IS_CHAN_2GHZ(chan)) { |
681 | /* CTL_11B, CTL_11G, CTL_2GHT20 */ | ||
660 | numCtlModes = | 682 | numCtlModes = |
661 | ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; | 683 | ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; |
684 | |||
662 | pCtlMode = ctlModesFor11g; | 685 | pCtlMode = ctlModesFor11g; |
663 | 686 | ||
664 | ath9k_hw_get_legacy_target_powers(ah, chan, | 687 | ath9k_hw_get_legacy_target_powers(ah, chan, |
@@ -675,6 +698,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
675 | &targetPowerHt20, 8, false); | 698 | &targetPowerHt20, 8, false); |
676 | 699 | ||
677 | if (IS_CHAN_HT40(chan)) { | 700 | if (IS_CHAN_HT40(chan)) { |
701 | /* All 2G CTLs */ | ||
678 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | 702 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); |
679 | ath9k_hw_get_target_powers(ah, chan, | 703 | ath9k_hw_get_target_powers(ah, chan, |
680 | pEepData->calTargetPower2GHT40, | 704 | pEepData->calTargetPower2GHT40, |
@@ -692,8 +716,9 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
692 | } | 716 | } |
693 | 717 | ||
694 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | 718 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { |
695 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | 719 | bool isHt40CtlMode = |
696 | (pCtlMode[ctlMode] == CTL_2GHT40); | 720 | (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false; |
721 | |||
697 | if (isHt40CtlMode) | 722 | if (isHt40CtlMode) |
698 | freq = centers.synth_center; | 723 | freq = centers.synth_center; |
699 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | 724 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) |
@@ -701,31 +726,28 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
701 | else | 726 | else |
702 | freq = centers.ctl_center; | 727 | freq = centers.ctl_center; |
703 | 728 | ||
704 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | 729 | /* Walk through the CTL indices stored in EEPROM */ |
705 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
706 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
707 | |||
708 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | 730 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { |
709 | if ((((cfgCtl & ~CTL_MODE_M) | | 731 | struct cal_ctl_edges *pRdEdgesPower; |
710 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
711 | pEepData->ctlIndex[i]) || | ||
712 | (((cfgCtl & ~CTL_MODE_M) | | ||
713 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
714 | ((pEepData->ctlIndex[i] & | ||
715 | CTL_MODE_M) | SD_NO_CTL))) { | ||
716 | 732 | ||
733 | /* | ||
734 | * Compare test group from regulatory channel list | ||
735 | * with test mode from pCtlMode list | ||
736 | */ | ||
737 | if (CMP_CTL || CMP_NO_CTL) { | ||
717 | rep = &(pEepData->ctlData[i]); | 738 | rep = &(pEepData->ctlData[i]); |
718 | twiceMinEdgePower = ath9k_hw_get_max_edge_power( | 739 | pRdEdgesPower = |
719 | freq, | 740 | rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1]; |
720 | rep->ctlEdges[ar5416_get_ntxchains( | 741 | |
721 | tx_chainmask) - 1], | 742 | twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, |
722 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | 743 | pRdEdgesPower, |
723 | 744 | IS_CHAN_2GHZ(chan), | |
724 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | 745 | AR5416_NUM_BAND_EDGES); |
725 | twiceMaxEdgePower = min( | 746 | |
726 | twiceMaxEdgePower, | 747 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { |
727 | twiceMinEdgePower); | 748 | twiceMaxEdgePower = min(twiceMaxEdgePower, |
728 | else { | 749 | twiceMinEdgePower); |
750 | } else { | ||
729 | twiceMaxEdgePower = twiceMinEdgePower; | 751 | twiceMaxEdgePower = twiceMinEdgePower; |
730 | break; | 752 | break; |
731 | } | 753 | } |
@@ -734,55 +756,48 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
734 | 756 | ||
735 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | 757 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); |
736 | 758 | ||
759 | /* Apply ctl mode to correct target power set */ | ||
737 | switch (pCtlMode[ctlMode]) { | 760 | switch (pCtlMode[ctlMode]) { |
738 | case CTL_11B: | 761 | case CTL_11B: |
739 | for (i = 0; | 762 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { |
740 | i < ARRAY_SIZE(targetPowerCck.tPow2x); | 763 | targetPowerCck.tPow2x[i] = |
741 | i++) { | 764 | (u8)min((u16)targetPowerCck.tPow2x[i], |
742 | targetPowerCck.tPow2x[i] = (u8)min( | 765 | minCtlPower); |
743 | (u16)targetPowerCck.tPow2x[i], | ||
744 | minCtlPower); | ||
745 | } | 766 | } |
746 | break; | 767 | break; |
747 | case CTL_11A: | 768 | case CTL_11A: |
748 | case CTL_11G: | 769 | case CTL_11G: |
749 | for (i = 0; | 770 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { |
750 | i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | 771 | targetPowerOfdm.tPow2x[i] = |
751 | i++) { | 772 | (u8)min((u16)targetPowerOfdm.tPow2x[i], |
752 | targetPowerOfdm.tPow2x[i] = (u8)min( | 773 | minCtlPower); |
753 | (u16)targetPowerOfdm.tPow2x[i], | ||
754 | minCtlPower); | ||
755 | } | 774 | } |
756 | break; | 775 | break; |
757 | case CTL_5GHT20: | 776 | case CTL_5GHT20: |
758 | case CTL_2GHT20: | 777 | case CTL_2GHT20: |
759 | for (i = 0; | 778 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { |
760 | i < ARRAY_SIZE(targetPowerHt20.tPow2x); | 779 | targetPowerHt20.tPow2x[i] = |
761 | i++) { | 780 | (u8)min((u16)targetPowerHt20.tPow2x[i], |
762 | targetPowerHt20.tPow2x[i] = (u8)min( | 781 | minCtlPower); |
763 | (u16)targetPowerHt20.tPow2x[i], | ||
764 | minCtlPower); | ||
765 | } | 782 | } |
766 | break; | 783 | break; |
767 | case CTL_11B_EXT: | 784 | case CTL_11B_EXT: |
768 | targetPowerCckExt.tPow2x[0] = (u8)min( | 785 | targetPowerCckExt.tPow2x[0] = |
769 | (u16)targetPowerCckExt.tPow2x[0], | 786 | (u8)min((u16)targetPowerCckExt.tPow2x[0], |
770 | minCtlPower); | 787 | minCtlPower); |
771 | break; | 788 | break; |
772 | case CTL_11A_EXT: | 789 | case CTL_11A_EXT: |
773 | case CTL_11G_EXT: | 790 | case CTL_11G_EXT: |
774 | targetPowerOfdmExt.tPow2x[0] = (u8)min( | 791 | targetPowerOfdmExt.tPow2x[0] = |
775 | (u16)targetPowerOfdmExt.tPow2x[0], | 792 | (u8)min((u16)targetPowerOfdmExt.tPow2x[0], |
776 | minCtlPower); | 793 | minCtlPower); |
777 | break; | 794 | break; |
778 | case CTL_5GHT40: | 795 | case CTL_5GHT40: |
779 | case CTL_2GHT40: | 796 | case CTL_2GHT40: |
780 | for (i = 0; | 797 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { |
781 | i < ARRAY_SIZE(targetPowerHt40.tPow2x); | 798 | targetPowerHt40.tPow2x[i] = |
782 | i++) { | 799 | (u8)min((u16)targetPowerHt40.tPow2x[i], |
783 | targetPowerHt40.tPow2x[i] = (u8)min( | 800 | minCtlPower); |
784 | (u16)targetPowerHt40.tPow2x[i], | ||
785 | minCtlPower); | ||
786 | } | 801 | } |
787 | break; | 802 | break; |
788 | default: | 803 | default: |
@@ -790,12 +805,13 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
790 | } | 805 | } |
791 | } | 806 | } |
792 | 807 | ||
808 | /* Now set the rates array */ | ||
809 | |||
793 | ratesArray[rate6mb] = | 810 | ratesArray[rate6mb] = |
794 | ratesArray[rate9mb] = | 811 | ratesArray[rate9mb] = |
795 | ratesArray[rate12mb] = | 812 | ratesArray[rate12mb] = |
796 | ratesArray[rate18mb] = | 813 | ratesArray[rate18mb] = |
797 | ratesArray[rate24mb] = | 814 | ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; |
798 | targetPowerOfdm.tPow2x[0]; | ||
799 | 815 | ||
800 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | 816 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; |
801 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | 817 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; |
@@ -807,12 +823,12 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
807 | 823 | ||
808 | if (IS_CHAN_2GHZ(chan)) { | 824 | if (IS_CHAN_2GHZ(chan)) { |
809 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | 825 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; |
810 | ratesArray[rate2s] = ratesArray[rate2l] = | 826 | ratesArray[rate2s] = |
811 | targetPowerCck.tPow2x[1]; | 827 | ratesArray[rate2l] = targetPowerCck.tPow2x[1]; |
812 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | 828 | ratesArray[rate5_5s] = |
813 | targetPowerCck.tPow2x[2]; | 829 | ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; |
814 | ratesArray[rate11s] = ratesArray[rate11l] = | 830 | ratesArray[rate11s] = |
815 | targetPowerCck.tPow2x[3]; | 831 | ratesArray[rate11l] = targetPowerCck.tPow2x[3]; |
816 | } | 832 | } |
817 | if (IS_CHAN_HT40(chan)) { | 833 | if (IS_CHAN_HT40(chan)) { |
818 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) | 834 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) |
@@ -821,28 +837,28 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
821 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | 837 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; |
822 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | 838 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; |
823 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | 839 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; |
840 | |||
824 | if (IS_CHAN_2GHZ(chan)) | 841 | if (IS_CHAN_2GHZ(chan)) |
825 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | 842 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; |
826 | } | 843 | } |
827 | 844 | ||
845 | #undef CMP_CTL | ||
846 | #undef CMP_NO_CTL | ||
828 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN | 847 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN |
829 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN | 848 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN |
830 | } | 849 | } |
831 | 850 | ||
832 | static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | 851 | static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, |
833 | struct ath9k_channel *chan, u16 cfgCtl, | 852 | struct ath9k_channel *chan, u16 cfgCtl, |
834 | u8 twiceAntennaReduction, | 853 | u8 twiceAntennaReduction, |
835 | u8 twiceMaxRegulatoryPower, | 854 | u8 twiceMaxRegulatoryPower, |
836 | u8 powerLimit) | 855 | u8 powerLimit) |
837 | { | 856 | { |
838 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | ||
839 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | ||
840 | struct ath_common *common = ath9k_hw_common(ah); | ||
841 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 857 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
842 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 858 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
843 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | 859 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; |
844 | int16_t ratesArray[Ar5416RateSize]; | 860 | int16_t ratesArray[Ar5416RateSize]; |
845 | int16_t txPowerIndexOffset = 0; | 861 | int16_t txPowerIndexOffset = 0; |
846 | u8 ht40PowerIncForPdadc = 2; | 862 | u8 ht40PowerIncForPdadc = 2; |
847 | int i; | 863 | int i; |
848 | 864 | ||
@@ -852,13 +868,13 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
852 | AR9287_EEP_MINOR_VER_2) | 868 | AR9287_EEP_MINOR_VER_2) |
853 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | 869 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; |
854 | 870 | ||
855 | ath9k_hw_set_AR9287_power_per_rate_table(ah, chan, | 871 | ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, |
856 | &ratesArray[0], cfgCtl, | 872 | &ratesArray[0], cfgCtl, |
857 | twiceAntennaReduction, | 873 | twiceAntennaReduction, |
858 | twiceMaxRegulatoryPower, | 874 | twiceMaxRegulatoryPower, |
859 | powerLimit); | 875 | powerLimit); |
860 | 876 | ||
861 | ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset); | 877 | ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); |
862 | 878 | ||
863 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | 879 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
864 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | 880 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
@@ -871,6 +887,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
871 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | 887 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; |
872 | } | 888 | } |
873 | 889 | ||
890 | /* OFDM power per rate */ | ||
874 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | 891 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, |
875 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | 892 | ATH9K_POW_SM(ratesArray[rate18mb], 24) |
876 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | 893 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) |
@@ -883,6 +900,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
883 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | 900 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) |
884 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | 901 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); |
885 | 902 | ||
903 | /* CCK power per rate */ | ||
886 | if (IS_CHAN_2GHZ(chan)) { | 904 | if (IS_CHAN_2GHZ(chan)) { |
887 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | 905 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, |
888 | ATH9K_POW_SM(ratesArray[rate2s], 24) | 906 | ATH9K_POW_SM(ratesArray[rate2s], 24) |
@@ -896,6 +914,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
896 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | 914 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); |
897 | } | 915 | } |
898 | 916 | ||
917 | /* HT20 power per rate */ | ||
899 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | 918 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, |
900 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | 919 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
901 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | 920 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
@@ -908,8 +927,9 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
908 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | 927 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
909 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | 928 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); |
910 | 929 | ||
930 | /* HT40 power per rate */ | ||
911 | if (IS_CHAN_HT40(chan)) { | 931 | if (IS_CHAN_HT40(chan)) { |
912 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 932 | if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
913 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | 933 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, |
914 | ATH9K_POW_SM(ratesArray[rateHt40_3], 24) | 934 | ATH9K_POW_SM(ratesArray[rateHt40_3], 24) |
915 | | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) | 935 | | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) |
@@ -943,6 +963,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
943 | ht40PowerIncForPdadc, 0)); | 963 | ht40PowerIncForPdadc, 0)); |
944 | } | 964 | } |
945 | 965 | ||
966 | /* Dup/Ext power per rate */ | ||
946 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | 967 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, |
947 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | 968 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
948 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | 969 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
@@ -960,37 +981,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
960 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | 981 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; |
961 | else | 982 | else |
962 | regulatory->max_power_level = ratesArray[i]; | 983 | regulatory->max_power_level = ratesArray[i]; |
963 | |||
964 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
965 | case 1: | ||
966 | break; | ||
967 | case 2: | ||
968 | regulatory->max_power_level += | ||
969 | INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
970 | break; | ||
971 | case 3: | ||
972 | regulatory->max_power_level += | ||
973 | INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
974 | break; | ||
975 | default: | ||
976 | ath_print(common, ATH_DBG_EEPROM, | ||
977 | "Invalid chainmask configuration\n"); | ||
978 | break; | ||
979 | } | ||
980 | } | 984 | } |
981 | 985 | ||
982 | static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, | 986 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, |
983 | struct ath9k_channel *chan) | 987 | struct ath9k_channel *chan) |
984 | { | 988 | { |
985 | } | 989 | } |
986 | 990 | ||
987 | static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | 991 | static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, |
988 | struct ath9k_channel *chan) | 992 | struct ath9k_channel *chan) |
989 | { | 993 | { |
990 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 994 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
991 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | 995 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; |
992 | u16 antWrites[AR9287_ANT_16S]; | 996 | u16 antWrites[AR9287_ANT_16S]; |
993 | u32 regChainOffset; | 997 | u32 regChainOffset, regval; |
994 | u8 txRxAttenLocal; | 998 | u8 txRxAttenLocal; |
995 | int i, j, offset_num; | 999 | int i, j, offset_num; |
996 | 1000 | ||
@@ -1077,42 +1081,37 @@ static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | |||
1077 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | 1081 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, |
1078 | AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); | 1082 | AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); |
1079 | 1083 | ||
1080 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1, | 1084 | regval = REG_READ(ah, AR9287_AN_RF2G3_CH0); |
1081 | AR9287_AN_RF2G3_DB1_S, pModal->db1); | 1085 | regval &= ~(AR9287_AN_RF2G3_DB1 | |
1082 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2, | 1086 | AR9287_AN_RF2G3_DB2 | |
1083 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | 1087 | AR9287_AN_RF2G3_OB_CCK | |
1084 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | 1088 | AR9287_AN_RF2G3_OB_PSK | |
1085 | AR9287_AN_RF2G3_OB_CCK, | 1089 | AR9287_AN_RF2G3_OB_QAM | |
1086 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | 1090 | AR9287_AN_RF2G3_OB_PAL_OFF); |
1087 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | 1091 | regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | |
1088 | AR9287_AN_RF2G3_OB_PSK, | 1092 | SM(pModal->db2, AR9287_AN_RF2G3_DB2) | |
1089 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | 1093 | SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | |
1090 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | 1094 | SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | |
1091 | AR9287_AN_RF2G3_OB_QAM, | 1095 | SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | |
1092 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | 1096 | SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); |
1093 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | 1097 | |
1094 | AR9287_AN_RF2G3_OB_PAL_OFF, | 1098 | ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval); |
1095 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | 1099 | |
1096 | pModal->ob_pal_off); | 1100 | regval = REG_READ(ah, AR9287_AN_RF2G3_CH1); |
1097 | 1101 | regval &= ~(AR9287_AN_RF2G3_DB1 | | |
1098 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | 1102 | AR9287_AN_RF2G3_DB2 | |
1099 | AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S, | 1103 | AR9287_AN_RF2G3_OB_CCK | |
1100 | pModal->db1); | 1104 | AR9287_AN_RF2G3_OB_PSK | |
1101 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2, | 1105 | AR9287_AN_RF2G3_OB_QAM | |
1102 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | 1106 | AR9287_AN_RF2G3_OB_PAL_OFF); |
1103 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | 1107 | regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | |
1104 | AR9287_AN_RF2G3_OB_CCK, | 1108 | SM(pModal->db2, AR9287_AN_RF2G3_DB2) | |
1105 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | 1109 | SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | |
1106 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | 1110 | SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | |
1107 | AR9287_AN_RF2G3_OB_PSK, | 1111 | SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | |
1108 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | 1112 | SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); |
1109 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | 1113 | |
1110 | AR9287_AN_RF2G3_OB_QAM, | 1114 | ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval); |
1111 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
1112 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
1113 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
1114 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
1115 | pModal->ob_pal_off); | ||
1116 | 1115 | ||
1117 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | 1116 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, |
1118 | AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); | 1117 | AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); |
@@ -1125,13 +1124,13 @@ static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | |||
1125 | pModal->xpaBiasLvl); | 1124 | pModal->xpaBiasLvl); |
1126 | } | 1125 | } |
1127 | 1126 | ||
1128 | static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, | 1127 | static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, |
1129 | enum ieee80211_band freq_band) | 1128 | enum ieee80211_band freq_band) |
1130 | { | 1129 | { |
1131 | return 1; | 1130 | return 1; |
1132 | } | 1131 | } |
1133 | 1132 | ||
1134 | static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | 1133 | static u16 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah, |
1135 | struct ath9k_channel *chan) | 1134 | struct ath9k_channel *chan) |
1136 | { | 1135 | { |
1137 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 1136 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
@@ -1140,11 +1139,12 @@ static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | |||
1140 | return pModal->antCtrlCommon & 0xFFFF; | 1139 | return pModal->antCtrlCommon & 0xFFFF; |
1141 | } | 1140 | } |
1142 | 1141 | ||
1143 | static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, | 1142 | static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, |
1144 | u16 i, bool is2GHz) | 1143 | u16 i, bool is2GHz) |
1145 | { | 1144 | { |
1146 | #define EEP_MAP9287_SPURCHAN \ | 1145 | #define EEP_MAP9287_SPURCHAN \ |
1147 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) | 1146 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) |
1147 | |||
1148 | struct ath_common *common = ath9k_hw_common(ah); | 1148 | struct ath_common *common = ath9k_hw_common(ah); |
1149 | u16 spur_val = AR_NO_SPUR; | 1149 | u16 spur_val = AR_NO_SPUR; |
1150 | 1150 | ||
@@ -1171,15 +1171,15 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, | |||
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | const struct eeprom_ops eep_ar9287_ops = { | 1173 | const struct eeprom_ops eep_ar9287_ops = { |
1174 | .check_eeprom = ath9k_hw_AR9287_check_eeprom, | 1174 | .check_eeprom = ath9k_hw_ar9287_check_eeprom, |
1175 | .get_eeprom = ath9k_hw_AR9287_get_eeprom, | 1175 | .get_eeprom = ath9k_hw_ar9287_get_eeprom, |
1176 | .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, | 1176 | .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, |
1177 | .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver, | 1177 | .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, |
1178 | .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev, | 1178 | .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, |
1179 | .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config, | 1179 | .get_num_ant_config = ath9k_hw_ar9287_get_num_ant_config, |
1180 | .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg, | 1180 | .get_eeprom_antenna_cfg = ath9k_hw_ar9287_get_eeprom_antenna_cfg, |
1181 | .set_board_values = ath9k_hw_AR9287_set_board_values, | 1181 | .set_board_values = ath9k_hw_ar9287_set_board_values, |
1182 | .set_addac = ath9k_hw_AR9287_set_addac, | 1182 | .set_addac = ath9k_hw_ar9287_set_addac, |
1183 | .set_txpower = ath9k_hw_AR9287_set_txpower, | 1183 | .set_txpower = ath9k_hw_ar9287_set_txpower, |
1184 | .get_spur_channel = ath9k_hw_AR9287_get_spur_channel | 1184 | .get_spur_channel = ath9k_hw_ar9287_get_spur_channel |
1185 | }; | 1185 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 7e1ed78d0e64..77b1433312cc 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -617,6 +617,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
617 | int16_t minDelta = 0; | 617 | int16_t minDelta = 0; |
618 | struct chan_centers centers; | 618 | struct chan_centers centers; |
619 | 619 | ||
620 | memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); | ||
620 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 621 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
621 | 622 | ||
622 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | 623 | for (numPiers = 0; numPiers < availPiers; numPiers++) { |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 0ee75e79fe35..3a8ee999da5d 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -76,7 +76,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev, | |||
76 | case LED_FULL: | 76 | case LED_FULL: |
77 | if (led->led_type == ATH_LED_ASSOC) { | 77 | if (led->led_type == ATH_LED_ASSOC) { |
78 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | 78 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; |
79 | ieee80211_queue_delayed_work(sc->hw, | 79 | if (led_blink) |
80 | ieee80211_queue_delayed_work(sc->hw, | ||
80 | &sc->ath_led_blink_work, 0); | 81 | &sc->ath_led_blink_work, 0); |
81 | } else if (led->led_type == ATH_LED_RADIO) { | 82 | } else if (led->led_type == ATH_LED_RADIO) { |
82 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | 83 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); |
@@ -143,7 +144,8 @@ void ath_init_leds(struct ath_softc *sc) | |||
143 | /* LED off, active low */ | 144 | /* LED off, active low */ |
144 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 145 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
145 | 146 | ||
146 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | 147 | if (led_blink) |
148 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | ||
147 | 149 | ||
148 | trigger = ieee80211_get_radio_led_name(sc->hw); | 150 | trigger = ieee80211_get_radio_led_name(sc->hw); |
149 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | 151 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), |
@@ -180,7 +182,8 @@ void ath_init_leds(struct ath_softc *sc) | |||
180 | return; | 182 | return; |
181 | 183 | ||
182 | fail: | 184 | fail: |
183 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | 185 | if (led_blink) |
186 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
184 | ath_deinit_leds(sc); | 187 | ath_deinit_leds(sc); |
185 | } | 188 | } |
186 | 189 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 77b359162d6c..ad9134bddd1e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -16,12 +16,27 @@ | |||
16 | 16 | ||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | #define ATH9K_FW_USB_DEV(devid, fw) \ | 19 | /* identify firmware images */ |
20 | { USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw } | 20 | #define FIRMWARE_AR7010 "ar7010.fw" |
21 | #define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" | ||
22 | #define FIRMWARE_AR9271 "ar9271.fw" | ||
23 | |||
24 | MODULE_FIRMWARE(FIRMWARE_AR7010); | ||
25 | MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); | ||
26 | MODULE_FIRMWARE(FIRMWARE_AR9271); | ||
21 | 27 | ||
22 | static struct usb_device_id ath9k_hif_usb_ids[] = { | 28 | static struct usb_device_id ath9k_hif_usb_ids[] = { |
23 | ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), | 29 | { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ |
24 | ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"), | 30 | { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ |
31 | { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */ | ||
32 | { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */ | ||
33 | { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ | ||
34 | { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */ | ||
35 | { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ | ||
36 | { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ | ||
37 | { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ | ||
38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ | ||
39 | { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */ | ||
25 | { }, | 40 | { }, |
26 | }; | 41 | }; |
27 | 42 | ||
@@ -756,6 +771,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
756 | size_t len = hif_dev->firmware->size; | 771 | size_t len = hif_dev->firmware->size; |
757 | u32 addr = AR9271_FIRMWARE; | 772 | u32 addr = AR9271_FIRMWARE; |
758 | u8 *buf = kzalloc(4096, GFP_KERNEL); | 773 | u8 *buf = kzalloc(4096, GFP_KERNEL); |
774 | u32 firm_offset; | ||
759 | 775 | ||
760 | if (!buf) | 776 | if (!buf) |
761 | return -ENOMEM; | 777 | return -ENOMEM; |
@@ -779,32 +795,37 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
779 | } | 795 | } |
780 | kfree(buf); | 796 | kfree(buf); |
781 | 797 | ||
798 | if (hif_dev->device_id == 0x7010) | ||
799 | firm_offset = AR7010_FIRMWARE_TEXT; | ||
800 | else | ||
801 | firm_offset = AR9271_FIRMWARE_TEXT; | ||
802 | |||
782 | /* | 803 | /* |
783 | * Issue FW download complete command to firmware. | 804 | * Issue FW download complete command to firmware. |
784 | */ | 805 | */ |
785 | err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), | 806 | err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), |
786 | FIRMWARE_DOWNLOAD_COMP, | 807 | FIRMWARE_DOWNLOAD_COMP, |
787 | 0x40 | USB_DIR_OUT, | 808 | 0x40 | USB_DIR_OUT, |
788 | AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ); | 809 | firm_offset >> 8, 0, NULL, 0, HZ); |
789 | if (err) | 810 | if (err) |
790 | return -EIO; | 811 | return -EIO; |
791 | 812 | ||
792 | dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", | 813 | dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", |
793 | "ar9271.fw", (unsigned long) hif_dev->firmware->size); | 814 | hif_dev->fw_name, (unsigned long) hif_dev->firmware->size); |
794 | 815 | ||
795 | return 0; | 816 | return 0; |
796 | } | 817 | } |
797 | 818 | ||
798 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, | 819 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) |
799 | const char *fw_name) | ||
800 | { | 820 | { |
801 | int ret; | 821 | int ret; |
802 | 822 | ||
803 | /* Request firmware */ | 823 | /* Request firmware */ |
804 | ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev); | 824 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, |
825 | &hif_dev->udev->dev); | ||
805 | if (ret) { | 826 | if (ret) { |
806 | dev_err(&hif_dev->udev->dev, | 827 | dev_err(&hif_dev->udev->dev, |
807 | "ath9k_htc: Firmware - %s not found\n", fw_name); | 828 | "ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name); |
808 | goto err_fw_req; | 829 | goto err_fw_req; |
809 | } | 830 | } |
810 | 831 | ||
@@ -820,7 +841,8 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, | |||
820 | ret = ath9k_hif_usb_download_fw(hif_dev); | 841 | ret = ath9k_hif_usb_download_fw(hif_dev); |
821 | if (ret) { | 842 | if (ret) { |
822 | dev_err(&hif_dev->udev->dev, | 843 | dev_err(&hif_dev->udev->dev, |
823 | "ath9k_htc: Firmware - %s download failed\n", fw_name); | 844 | "ath9k_htc: Firmware - %s download failed\n", |
845 | hif_dev->fw_name); | ||
824 | goto err_fw_download; | 846 | goto err_fw_download; |
825 | } | 847 | } |
826 | 848 | ||
@@ -847,7 +869,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
847 | { | 869 | { |
848 | struct usb_device *udev = interface_to_usbdev(interface); | 870 | struct usb_device *udev = interface_to_usbdev(interface); |
849 | struct hif_device_usb *hif_dev; | 871 | struct hif_device_usb *hif_dev; |
850 | const char *fw_name = (const char *) id->driver_info; | ||
851 | int ret = 0; | 872 | int ret = 0; |
852 | 873 | ||
853 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); | 874 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); |
@@ -872,7 +893,27 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
872 | goto err_htc_hw_alloc; | 893 | goto err_htc_hw_alloc; |
873 | } | 894 | } |
874 | 895 | ||
875 | ret = ath9k_hif_usb_dev_init(hif_dev, fw_name); | 896 | /* Find out which firmware to load */ |
897 | |||
898 | switch(hif_dev->device_id) { | ||
899 | case 0x7010: | ||
900 | case 0x9018: | ||
901 | if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) | ||
902 | hif_dev->fw_name = FIRMWARE_AR7010_1_1; | ||
903 | else | ||
904 | hif_dev->fw_name = FIRMWARE_AR7010; | ||
905 | break; | ||
906 | default: | ||
907 | hif_dev->fw_name = FIRMWARE_AR9271; | ||
908 | break; | ||
909 | } | ||
910 | |||
911 | if (!hif_dev->fw_name) { | ||
912 | dev_err(&udev->dev, "Can't determine firmware !\n"); | ||
913 | goto err_htc_hw_alloc; | ||
914 | } | ||
915 | |||
916 | ret = ath9k_hif_usb_dev_init(hif_dev); | ||
876 | if (ret) { | 917 | if (ret) { |
877 | ret = -EINVAL; | 918 | ret = -EINVAL; |
878 | goto err_hif_init_usb; | 919 | goto err_hif_init_usb; |
@@ -907,12 +948,10 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) | |||
907 | void *buf; | 948 | void *buf; |
908 | int ret; | 949 | int ret; |
909 | 950 | ||
910 | buf = kmalloc(4, GFP_KERNEL); | 951 | buf = kmemdup(&reboot_cmd, 4, GFP_KERNEL); |
911 | if (!buf) | 952 | if (!buf) |
912 | return; | 953 | return; |
913 | 954 | ||
914 | memcpy(buf, &reboot_cmd, 4); | ||
915 | |||
916 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), | 955 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), |
917 | buf, 4, NULL, HZ); | 956 | buf, 4, NULL, HZ); |
918 | if (ret) | 957 | if (ret) |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 0aca49b6fcb6..2daf97b11c08 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #define AR9271_FIRMWARE 0x501000 | 20 | #define AR9271_FIRMWARE 0x501000 |
21 | #define AR9271_FIRMWARE_TEXT 0x903000 | 21 | #define AR9271_FIRMWARE_TEXT 0x903000 |
22 | #define AR7010_FIRMWARE_TEXT 0x906000 | ||
22 | 23 | ||
23 | #define FIRMWARE_DOWNLOAD 0x30 | 24 | #define FIRMWARE_DOWNLOAD 0x30 |
24 | #define FIRMWARE_DOWNLOAD_COMP 0x31 | 25 | #define FIRMWARE_DOWNLOAD_COMP 0x31 |
@@ -90,6 +91,7 @@ struct hif_device_usb { | |||
90 | struct usb_anchor regout_submitted; | 91 | struct usb_anchor regout_submitted; |
91 | struct usb_anchor rx_submitted; | 92 | struct usb_anchor rx_submitted; |
92 | struct sk_buff *remain_skb; | 93 | struct sk_buff *remain_skb; |
94 | const char *fw_name; | ||
93 | int rx_remain_len; | 95 | int rx_remain_len; |
94 | int rx_pkt_len; | 96 | int rx_pkt_len; |
95 | int rx_transfer_len; | 97 | int rx_transfer_len; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index c251603ab032..58f52a1dc7ea 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -223,15 +223,6 @@ struct ath9k_htc_sta { | |||
223 | enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; | 223 | enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; |
224 | }; | 224 | }; |
225 | 225 | ||
226 | struct ath9k_htc_aggr_work { | ||
227 | u16 tid; | ||
228 | u8 sta_addr[ETH_ALEN]; | ||
229 | struct ieee80211_hw *hw; | ||
230 | struct ieee80211_vif *vif; | ||
231 | enum ieee80211_ampdu_mlme_action action; | ||
232 | struct mutex mutex; | ||
233 | }; | ||
234 | |||
235 | #define ATH9K_HTC_RXBUF 256 | 226 | #define ATH9K_HTC_RXBUF 256 |
236 | #define HTC_RX_FRAME_HEADER_SIZE 40 | 227 | #define HTC_RX_FRAME_HEADER_SIZE 40 |
237 | 228 | ||
@@ -257,12 +248,15 @@ struct ath9k_htc_tx_ctl { | |||
257 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) | 248 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) |
258 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) | 249 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) |
259 | 250 | ||
251 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) | ||
252 | |||
260 | struct ath_tx_stats { | 253 | struct ath_tx_stats { |
261 | u32 buf_queued; | 254 | u32 buf_queued; |
262 | u32 buf_completed; | 255 | u32 buf_completed; |
263 | u32 skb_queued; | 256 | u32 skb_queued; |
264 | u32 skb_completed; | 257 | u32 skb_completed; |
265 | u32 skb_dropped; | 258 | u32 skb_dropped; |
259 | u32 queue_stats[WME_NUM_AC]; | ||
266 | }; | 260 | }; |
267 | 261 | ||
268 | struct ath_rx_stats { | 262 | struct ath_rx_stats { |
@@ -286,6 +280,8 @@ struct ath9k_debug { | |||
286 | #define TX_STAT_INC(c) do { } while (0) | 280 | #define TX_STAT_INC(c) do { } while (0) |
287 | #define RX_STAT_INC(c) do { } while (0) | 281 | #define RX_STAT_INC(c) do { } while (0) |
288 | 282 | ||
283 | #define TX_QSTAT_INC(c) do { } while (0) | ||
284 | |||
289 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | 285 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ |
290 | 286 | ||
291 | #define ATH_LED_PIN_DEF 1 | 287 | #define ATH_LED_PIN_DEF 1 |
@@ -326,11 +322,10 @@ struct htc_beacon_config { | |||
326 | #define OP_LED_ON BIT(4) | 322 | #define OP_LED_ON BIT(4) |
327 | #define OP_PREAMBLE_SHORT BIT(5) | 323 | #define OP_PREAMBLE_SHORT BIT(5) |
328 | #define OP_PROTECT_ENABLE BIT(6) | 324 | #define OP_PROTECT_ENABLE BIT(6) |
329 | #define OP_TXAGGR BIT(7) | 325 | #define OP_ASSOCIATED BIT(7) |
330 | #define OP_ASSOCIATED BIT(8) | 326 | #define OP_ENABLE_BEACON BIT(8) |
331 | #define OP_ENABLE_BEACON BIT(9) | 327 | #define OP_LED_DEINIT BIT(9) |
332 | #define OP_LED_DEINIT BIT(10) | 328 | #define OP_UNPLUGGED BIT(10) |
333 | #define OP_UNPLUGGED BIT(11) | ||
334 | 329 | ||
335 | struct ath9k_htc_priv { | 330 | struct ath9k_htc_priv { |
336 | struct device *dev; | 331 | struct device *dev; |
@@ -371,8 +366,6 @@ struct ath9k_htc_priv { | |||
371 | struct ath9k_htc_rx rx; | 366 | struct ath9k_htc_rx rx; |
372 | struct tasklet_struct tx_tasklet; | 367 | struct tasklet_struct tx_tasklet; |
373 | struct sk_buff_head tx_queue; | 368 | struct sk_buff_head tx_queue; |
374 | struct ath9k_htc_aggr_work aggr_work; | ||
375 | struct delayed_work ath9k_aggr_work; | ||
376 | struct delayed_work ath9k_ani_work; | 369 | struct delayed_work ath9k_ani_work; |
377 | struct work_struct ps_work; | 370 | struct work_struct ps_work; |
378 | 371 | ||
@@ -390,13 +383,14 @@ struct ath9k_htc_priv { | |||
390 | int led_off_duration; | 383 | int led_off_duration; |
391 | int led_on_cnt; | 384 | int led_on_cnt; |
392 | int led_off_cnt; | 385 | int led_off_cnt; |
393 | int hwq_map[ATH9K_WME_AC_VO+1]; | 386 | |
387 | int beaconq; | ||
388 | int cabq; | ||
389 | int hwq_map[WME_NUM_AC]; | ||
394 | 390 | ||
395 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 391 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
396 | struct ath9k_debug debug; | 392 | struct ath9k_debug debug; |
397 | #endif | 393 | #endif |
398 | struct ath9k_htc_target_rate tgt_rate; | ||
399 | |||
400 | struct mutex mutex; | 394 | struct mutex mutex; |
401 | }; | 395 | }; |
402 | 396 | ||
@@ -405,6 +399,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
405 | common->bus_ops->read_cachesize(common, csz); | 399 | common->bus_ops->read_cachesize(common, csz); |
406 | } | 400 | } |
407 | 401 | ||
402 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); | ||
408 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 403 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
409 | struct ieee80211_vif *vif); | 404 | struct ieee80211_vif *vif); |
410 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); | 405 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); |
@@ -424,8 +419,8 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv); | |||
424 | void ath9k_tx_tasklet(unsigned long data); | 419 | void ath9k_tx_tasklet(unsigned long data); |
425 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); | 420 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); |
426 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); | 421 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); |
427 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | 422 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); |
428 | enum ath9k_tx_queue_subtype qtype); | 423 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); |
429 | int get_hw_qnum(u16 queue, int *hwq_map); | 424 | int get_hw_qnum(u16 queue, int *hwq_map); |
430 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | 425 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, |
431 | struct ath9k_tx_queue_info *qinfo); | 426 | struct ath9k_tx_queue_info *qinfo); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index c10c7d002eb7..bd1506e69105 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -222,6 +222,29 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | |||
222 | spin_unlock_bh(&priv->beacon_lock); | 222 | spin_unlock_bh(&priv->beacon_lock); |
223 | } | 223 | } |
224 | 224 | ||
225 | /* Currently, only for IBSS */ | ||
226 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | ||
227 | { | ||
228 | struct ath_hw *ah = priv->ah; | ||
229 | struct ath9k_tx_queue_info qi, qi_be; | ||
230 | int qnum = priv->hwq_map[WME_AC_BE]; | ||
231 | |||
232 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | ||
233 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | ||
234 | |||
235 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | ||
236 | |||
237 | qi.tqi_aifs = qi_be.tqi_aifs; | ||
238 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | ||
239 | qi.tqi_cwmax = qi_be.tqi_cwmax; | ||
240 | |||
241 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { | ||
242 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
243 | "Unable to update beacon queue %u!\n", qnum); | ||
244 | } else { | ||
245 | ath9k_hw_resettxqueue(ah, priv->beaconq); | ||
246 | } | ||
247 | } | ||
225 | 248 | ||
226 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 249 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
227 | struct ieee80211_vif *vif) | 250 | struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index dc015077a8d9..148b43317fdb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -34,6 +34,13 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | |||
34 | .max_power = 20, \ | 34 | .max_power = 20, \ |
35 | } | 35 | } |
36 | 36 | ||
37 | #define CHAN5G(_freq, _idx) { \ | ||
38 | .band = IEEE80211_BAND_5GHZ, \ | ||
39 | .center_freq = (_freq), \ | ||
40 | .hw_value = (_idx), \ | ||
41 | .max_power = 20, \ | ||
42 | } | ||
43 | |||
37 | static struct ieee80211_channel ath9k_2ghz_channels[] = { | 44 | static struct ieee80211_channel ath9k_2ghz_channels[] = { |
38 | CHAN2G(2412, 0), /* Channel 1 */ | 45 | CHAN2G(2412, 0), /* Channel 1 */ |
39 | CHAN2G(2417, 1), /* Channel 2 */ | 46 | CHAN2G(2417, 1), /* Channel 2 */ |
@@ -51,6 +58,37 @@ static struct ieee80211_channel ath9k_2ghz_channels[] = { | |||
51 | CHAN2G(2484, 13), /* Channel 14 */ | 58 | CHAN2G(2484, 13), /* Channel 14 */ |
52 | }; | 59 | }; |
53 | 60 | ||
61 | static struct ieee80211_channel ath9k_5ghz_channels[] = { | ||
62 | /* _We_ call this UNII 1 */ | ||
63 | CHAN5G(5180, 14), /* Channel 36 */ | ||
64 | CHAN5G(5200, 15), /* Channel 40 */ | ||
65 | CHAN5G(5220, 16), /* Channel 44 */ | ||
66 | CHAN5G(5240, 17), /* Channel 48 */ | ||
67 | /* _We_ call this UNII 2 */ | ||
68 | CHAN5G(5260, 18), /* Channel 52 */ | ||
69 | CHAN5G(5280, 19), /* Channel 56 */ | ||
70 | CHAN5G(5300, 20), /* Channel 60 */ | ||
71 | CHAN5G(5320, 21), /* Channel 64 */ | ||
72 | /* _We_ call this "Middle band" */ | ||
73 | CHAN5G(5500, 22), /* Channel 100 */ | ||
74 | CHAN5G(5520, 23), /* Channel 104 */ | ||
75 | CHAN5G(5540, 24), /* Channel 108 */ | ||
76 | CHAN5G(5560, 25), /* Channel 112 */ | ||
77 | CHAN5G(5580, 26), /* Channel 116 */ | ||
78 | CHAN5G(5600, 27), /* Channel 120 */ | ||
79 | CHAN5G(5620, 28), /* Channel 124 */ | ||
80 | CHAN5G(5640, 29), /* Channel 128 */ | ||
81 | CHAN5G(5660, 30), /* Channel 132 */ | ||
82 | CHAN5G(5680, 31), /* Channel 136 */ | ||
83 | CHAN5G(5700, 32), /* Channel 140 */ | ||
84 | /* _We_ call this UNII 3 */ | ||
85 | CHAN5G(5745, 33), /* Channel 149 */ | ||
86 | CHAN5G(5765, 34), /* Channel 153 */ | ||
87 | CHAN5G(5785, 35), /* Channel 157 */ | ||
88 | CHAN5G(5805, 36), /* Channel 161 */ | ||
89 | CHAN5G(5825, 37), /* Channel 165 */ | ||
90 | }; | ||
91 | |||
54 | /* Atheros hardware rate code addition for short premble */ | 92 | /* Atheros hardware rate code addition for short premble */ |
55 | #define SHPCHECK(__hw_rate, __flags) \ | 93 | #define SHPCHECK(__hw_rate, __flags) \ |
56 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) | 94 | ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) |
@@ -141,7 +179,7 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, | |||
141 | return htc_connect_service(priv->htc, &req, ep_id); | 179 | return htc_connect_service(priv->htc, &req, ep_id); |
142 | } | 180 | } |
143 | 181 | ||
144 | static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) | 182 | static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) |
145 | { | 183 | { |
146 | int ret; | 184 | int ret; |
147 | 185 | ||
@@ -199,10 +237,28 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) | |||
199 | if (ret) | 237 | if (ret) |
200 | goto err; | 238 | goto err; |
201 | 239 | ||
240 | /* | ||
241 | * Setup required credits before initializing HTC. | ||
242 | * This is a bit hacky, but, since queuing is done in | ||
243 | * the HIF layer, shouldn't matter much. | ||
244 | */ | ||
245 | |||
246 | switch(devid) { | ||
247 | case 0x7010: | ||
248 | case 0x9018: | ||
249 | priv->htc->credits = 45; | ||
250 | break; | ||
251 | default: | ||
252 | priv->htc->credits = 33; | ||
253 | } | ||
254 | |||
202 | ret = htc_init(priv->htc); | 255 | ret = htc_init(priv->htc); |
203 | if (ret) | 256 | if (ret) |
204 | goto err; | 257 | goto err; |
205 | 258 | ||
259 | dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n", | ||
260 | priv->htc->credits); | ||
261 | |||
206 | return 0; | 262 | return 0; |
207 | 263 | ||
208 | err: | 264 | err: |
@@ -398,17 +454,43 @@ static const struct ath_bus_ops ath9k_usb_bus_ops = { | |||
398 | static void setup_ht_cap(struct ath9k_htc_priv *priv, | 454 | static void setup_ht_cap(struct ath9k_htc_priv *priv, |
399 | struct ieee80211_sta_ht_cap *ht_info) | 455 | struct ieee80211_sta_ht_cap *ht_info) |
400 | { | 456 | { |
457 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
458 | u8 tx_streams, rx_streams; | ||
459 | int i; | ||
460 | |||
401 | ht_info->ht_supported = true; | 461 | ht_info->ht_supported = true; |
402 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 462 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
403 | IEEE80211_HT_CAP_SM_PS | | 463 | IEEE80211_HT_CAP_SM_PS | |
404 | IEEE80211_HT_CAP_SGI_40 | | 464 | IEEE80211_HT_CAP_SGI_40 | |
405 | IEEE80211_HT_CAP_DSSSCCK40; | 465 | IEEE80211_HT_CAP_DSSSCCK40; |
406 | 466 | ||
467 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) | ||
468 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
469 | |||
470 | ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | ||
471 | |||
407 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | 472 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
408 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | 473 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; |
409 | 474 | ||
410 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | 475 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |
411 | ht_info->mcs.rx_mask[0] = 0xff; | 476 | |
477 | /* ath9k_htc supports only 1 or 2 stream devices */ | ||
478 | tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); | ||
479 | rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); | ||
480 | |||
481 | ath_print(common, ATH_DBG_CONFIG, | ||
482 | "TX streams %d, RX streams: %d\n", | ||
483 | tx_streams, rx_streams); | ||
484 | |||
485 | if (tx_streams != rx_streams) { | ||
486 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
487 | ht_info->mcs.tx_params |= ((tx_streams - 1) << | ||
488 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
489 | } | ||
490 | |||
491 | for (i = 0; i < rx_streams; i++) | ||
492 | ht_info->mcs.rx_mask[i] = 0xff; | ||
493 | |||
412 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | 494 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; |
413 | } | 495 | } |
414 | 496 | ||
@@ -420,23 +502,37 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) | |||
420 | for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) | 502 | for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) |
421 | priv->hwq_map[i] = -1; | 503 | priv->hwq_map[i] = -1; |
422 | 504 | ||
423 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { | 505 | priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); |
506 | if (priv->beaconq == -1) { | ||
507 | ath_print(common, ATH_DBG_FATAL, | ||
508 | "Unable to setup BEACON xmit queue\n"); | ||
509 | goto err; | ||
510 | } | ||
511 | |||
512 | priv->cabq = ath9k_htc_cabq_setup(priv); | ||
513 | if (priv->cabq == -1) { | ||
514 | ath_print(common, ATH_DBG_FATAL, | ||
515 | "Unable to setup CAB xmit queue\n"); | ||
516 | goto err; | ||
517 | } | ||
518 | |||
519 | if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { | ||
424 | ath_print(common, ATH_DBG_FATAL, | 520 | ath_print(common, ATH_DBG_FATAL, |
425 | "Unable to setup xmit queue for BE traffic\n"); | 521 | "Unable to setup xmit queue for BE traffic\n"); |
426 | goto err; | 522 | goto err; |
427 | } | 523 | } |
428 | 524 | ||
429 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { | 525 | if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { |
430 | ath_print(common, ATH_DBG_FATAL, | 526 | ath_print(common, ATH_DBG_FATAL, |
431 | "Unable to setup xmit queue for BK traffic\n"); | 527 | "Unable to setup xmit queue for BK traffic\n"); |
432 | goto err; | 528 | goto err; |
433 | } | 529 | } |
434 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { | 530 | if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { |
435 | ath_print(common, ATH_DBG_FATAL, | 531 | ath_print(common, ATH_DBG_FATAL, |
436 | "Unable to setup xmit queue for VI traffic\n"); | 532 | "Unable to setup xmit queue for VI traffic\n"); |
437 | goto err; | 533 | goto err; |
438 | } | 534 | } |
439 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { | 535 | if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { |
440 | ath_print(common, ATH_DBG_FATAL, | 536 | ath_print(common, ATH_DBG_FATAL, |
441 | "Unable to setup xmit queue for VO traffic\n"); | 537 | "Unable to setup xmit queue for VO traffic\n"); |
442 | goto err; | 538 | goto err; |
@@ -468,36 +564,6 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) | |||
468 | */ | 564 | */ |
469 | for (i = 0; i < common->keymax; i++) | 565 | for (i = 0; i < common->keymax; i++) |
470 | ath9k_hw_keyreset(priv->ah, (u16) i); | 566 | ath9k_hw_keyreset(priv->ah, (u16) i); |
471 | |||
472 | if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
473 | ATH9K_CIPHER_TKIP, NULL)) { | ||
474 | /* | ||
475 | * Whether we should enable h/w TKIP MIC. | ||
476 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
477 | * report WMM capable, so it's always safe to turn on | ||
478 | * TKIP MIC in this case. | ||
479 | */ | ||
480 | ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
481 | } | ||
482 | |||
483 | /* | ||
484 | * Check whether the separate key cache entries | ||
485 | * are required to handle both tx+rx MIC keys. | ||
486 | * With split mic keys the number of stations is limited | ||
487 | * to 27 otherwise 59. | ||
488 | */ | ||
489 | if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
490 | ATH9K_CIPHER_TKIP, NULL) | ||
491 | && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
492 | ATH9K_CIPHER_MIC, NULL) | ||
493 | && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, | ||
494 | 0, NULL)) | ||
495 | common->splitmic = 1; | ||
496 | |||
497 | /* turn on mcast key search if possible */ | ||
498 | if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
499 | (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
500 | 1, 1, NULL); | ||
501 | } | 567 | } |
502 | 568 | ||
503 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | 569 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) |
@@ -512,6 +578,17 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | |||
512 | priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = | 578 | priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = |
513 | ARRAY_SIZE(ath9k_legacy_rates); | 579 | ARRAY_SIZE(ath9k_legacy_rates); |
514 | } | 580 | } |
581 | |||
582 | if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) { | ||
583 | priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; | ||
584 | priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | ||
585 | priv->sbands[IEEE80211_BAND_5GHZ].n_channels = | ||
586 | ARRAY_SIZE(ath9k_5ghz_channels); | ||
587 | priv->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
588 | ath9k_legacy_rates + 4; | ||
589 | priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates = | ||
590 | ARRAY_SIZE(ath9k_legacy_rates) - 4; | ||
591 | } | ||
515 | } | 592 | } |
516 | 593 | ||
517 | static void ath9k_init_misc(struct ath9k_htc_priv *priv) | 594 | static void ath9k_init_misc(struct ath9k_htc_priv *priv) |
@@ -524,7 +601,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
524 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 601 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
525 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | 602 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
526 | 603 | ||
527 | priv->op_flags |= OP_TXAGGR; | ||
528 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 604 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
529 | } | 605 | } |
530 | 606 | ||
@@ -556,14 +632,12 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
556 | spin_lock_init(&priv->beacon_lock); | 632 | spin_lock_init(&priv->beacon_lock); |
557 | spin_lock_init(&priv->tx_lock); | 633 | spin_lock_init(&priv->tx_lock); |
558 | mutex_init(&priv->mutex); | 634 | mutex_init(&priv->mutex); |
559 | mutex_init(&priv->aggr_work.mutex); | ||
560 | mutex_init(&priv->htc_pm_lock); | 635 | mutex_init(&priv->htc_pm_lock); |
561 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, | 636 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, |
562 | (unsigned long)priv); | 637 | (unsigned long)priv); |
563 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, | 638 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, |
564 | (unsigned long)priv); | 639 | (unsigned long)priv); |
565 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); | 640 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); |
566 | INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); | ||
567 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); | 641 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); |
568 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | 642 | INIT_WORK(&priv->ps_work, ath9k_ps_work); |
569 | 643 | ||
@@ -643,11 +717,17 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
643 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) | 717 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) |
644 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 718 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
645 | &priv->sbands[IEEE80211_BAND_2GHZ]; | 719 | &priv->sbands[IEEE80211_BAND_2GHZ]; |
720 | if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) | ||
721 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
722 | &priv->sbands[IEEE80211_BAND_5GHZ]; | ||
646 | 723 | ||
647 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | 724 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { |
648 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) | 725 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) |
649 | setup_ht_cap(priv, | 726 | setup_ht_cap(priv, |
650 | &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); | 727 | &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); |
728 | if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) | ||
729 | setup_ht_cap(priv, | ||
730 | &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); | ||
651 | } | 731 | } |
652 | 732 | ||
653 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 733 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
@@ -747,7 +827,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | |||
747 | goto err_free; | 827 | goto err_free; |
748 | } | 828 | } |
749 | 829 | ||
750 | ret = ath9k_init_htc_services(priv); | 830 | ret = ath9k_init_htc_services(priv, devid); |
751 | if (ret) | 831 | if (ret) |
752 | goto err_init; | 832 | goto err_init; |
753 | 833 | ||
@@ -790,7 +870,8 @@ int ath9k_htc_resume(struct htc_target *htc_handle) | |||
790 | if (ret) | 870 | if (ret) |
791 | return ret; | 871 | return ret; |
792 | 872 | ||
793 | ret = ath9k_init_htc_services(htc_handle->drv_priv); | 873 | ret = ath9k_init_htc_services(htc_handle->drv_priv, |
874 | htc_handle->drv_priv->ah->hw_version.devid); | ||
794 | return ret; | 875 | return ret; |
795 | } | 876 | } |
796 | #endif | 877 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 9d371c18eb41..05445d8a9818 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -27,13 +27,11 @@ static struct dentry *ath9k_debugfs_root; | |||
27 | static void ath_update_txpow(struct ath9k_htc_priv *priv) | 27 | static void ath_update_txpow(struct ath9k_htc_priv *priv) |
28 | { | 28 | { |
29 | struct ath_hw *ah = priv->ah; | 29 | struct ath_hw *ah = priv->ah; |
30 | u32 txpow; | ||
31 | 30 | ||
32 | if (priv->curtxpow != priv->txpowlimit) { | 31 | if (priv->curtxpow != priv->txpowlimit) { |
33 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); | 32 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); |
34 | /* read back in case value is clamped */ | 33 | /* read back in case value is clamped */ |
35 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | 34 | priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
36 | priv->curtxpow = txpow; | ||
37 | } | 35 | } |
38 | } | 36 | } |
39 | 37 | ||
@@ -325,142 +323,128 @@ static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | |||
325 | tcap.flags_ext = 0x80601000; | 323 | tcap.flags_ext = 0x80601000; |
326 | tcap.ampdu_limit = 0xffff0000; | 324 | tcap.ampdu_limit = 0xffff0000; |
327 | tcap.ampdu_subframes = 20; | 325 | tcap.ampdu_subframes = 20; |
328 | tcap.tx_chainmask_legacy = 1; | 326 | tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; |
329 | tcap.protmode = 1; | 327 | tcap.protmode = 1; |
330 | tcap.tx_chainmask = 1; | 328 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; |
331 | 329 | ||
332 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); | 330 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); |
333 | 331 | ||
334 | return ret; | 332 | return ret; |
335 | } | 333 | } |
336 | 334 | ||
337 | static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv, | 335 | static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv, |
338 | struct ieee80211_vif *vif, | 336 | struct ieee80211_sta *sta, |
339 | struct ieee80211_sta *sta) | 337 | struct ath9k_htc_target_rate *trate) |
340 | { | 338 | { |
341 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
342 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; | 339 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; |
343 | struct ieee80211_supported_band *sband; | 340 | struct ieee80211_supported_band *sband; |
344 | struct ath9k_htc_target_rate trate; | ||
345 | u32 caps = 0; | 341 | u32 caps = 0; |
346 | u8 cmd_rsp; | 342 | int i, j; |
347 | int i, j, ret; | ||
348 | |||
349 | memset(&trate, 0, sizeof(trate)); | ||
350 | 343 | ||
351 | /* Only 2GHz is supported */ | 344 | sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band]; |
352 | sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
353 | 345 | ||
354 | for (i = 0, j = 0; i < sband->n_bitrates; i++) { | 346 | for (i = 0, j = 0; i < sband->n_bitrates; i++) { |
355 | if (sta->supp_rates[sband->band] & BIT(i)) { | 347 | if (sta->supp_rates[sband->band] & BIT(i)) { |
356 | priv->tgt_rate.rates.legacy_rates.rs_rates[j] | 348 | trate->rates.legacy_rates.rs_rates[j] |
357 | = (sband->bitrates[i].bitrate * 2) / 10; | 349 | = (sband->bitrates[i].bitrate * 2) / 10; |
358 | j++; | 350 | j++; |
359 | } | 351 | } |
360 | } | 352 | } |
361 | priv->tgt_rate.rates.legacy_rates.rs_nrates = j; | 353 | trate->rates.legacy_rates.rs_nrates = j; |
362 | 354 | ||
363 | if (sta->ht_cap.ht_supported) { | 355 | if (sta->ht_cap.ht_supported) { |
364 | for (i = 0, j = 0; i < 77; i++) { | 356 | for (i = 0, j = 0; i < 77; i++) { |
365 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) | 357 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) |
366 | priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i; | 358 | trate->rates.ht_rates.rs_rates[j++] = i; |
367 | if (j == ATH_HTC_RATE_MAX) | 359 | if (j == ATH_HTC_RATE_MAX) |
368 | break; | 360 | break; |
369 | } | 361 | } |
370 | priv->tgt_rate.rates.ht_rates.rs_nrates = j; | 362 | trate->rates.ht_rates.rs_nrates = j; |
371 | 363 | ||
372 | caps = WLAN_RC_HT_FLAG; | 364 | caps = WLAN_RC_HT_FLAG; |
365 | if (sta->ht_cap.mcs.rx_mask[1]) | ||
366 | caps |= WLAN_RC_DS_FLAG; | ||
373 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 367 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
374 | caps |= WLAN_RC_40_FLAG; | 368 | caps |= WLAN_RC_40_FLAG; |
375 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) | 369 | if (conf_is_ht40(&priv->hw->conf) && |
370 | (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) | ||
371 | caps |= WLAN_RC_SGI_FLAG; | ||
372 | else if (conf_is_ht20(&priv->hw->conf) && | ||
373 | (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)) | ||
376 | caps |= WLAN_RC_SGI_FLAG; | 374 | caps |= WLAN_RC_SGI_FLAG; |
377 | |||
378 | } | 375 | } |
379 | 376 | ||
380 | priv->tgt_rate.sta_index = ista->index; | 377 | trate->sta_index = ista->index; |
381 | priv->tgt_rate.isnew = 1; | 378 | trate->isnew = 1; |
382 | trate = priv->tgt_rate; | 379 | trate->capflags = cpu_to_be32(caps); |
383 | priv->tgt_rate.capflags = cpu_to_be32(caps); | 380 | } |
384 | trate.capflags = cpu_to_be32(caps); | 381 | |
382 | static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv, | ||
383 | struct ath9k_htc_target_rate *trate) | ||
384 | { | ||
385 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
386 | int ret; | ||
387 | u8 cmd_rsp; | ||
385 | 388 | ||
386 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); | 389 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); |
387 | if (ret) { | 390 | if (ret) { |
388 | ath_print(common, ATH_DBG_FATAL, | 391 | ath_print(common, ATH_DBG_FATAL, |
389 | "Unable to initialize Rate information on target\n"); | 392 | "Unable to initialize Rate information on target\n"); |
390 | return ret; | ||
391 | } | 393 | } |
392 | 394 | ||
393 | ath_print(common, ATH_DBG_CONFIG, | 395 | return ret; |
394 | "Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps); | ||
395 | return 0; | ||
396 | } | 396 | } |
397 | 397 | ||
398 | static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40) | 398 | static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv, |
399 | struct ieee80211_sta *sta) | ||
399 | { | 400 | { |
400 | struct ath9k_htc_priv *priv = hw->priv; | 401 | struct ath_common *common = ath9k_hw_common(priv->ah); |
401 | struct ieee80211_conf *conf = &hw->conf; | 402 | struct ath9k_htc_target_rate trate; |
402 | 403 | int ret; | |
403 | if (!conf_is_ht(conf)) | ||
404 | return false; | ||
405 | |||
406 | if (!(priv->op_flags & OP_ASSOCIATED) || | ||
407 | (priv->op_flags & OP_SCANNING)) | ||
408 | return false; | ||
409 | 404 | ||
410 | if (conf_is_ht40(conf)) { | 405 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); |
411 | if (priv->ah->curchan->chanmode & | 406 | ath9k_htc_setup_rate(priv, sta, &trate); |
412 | (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) { | 407 | ret = ath9k_htc_send_rate_cmd(priv, &trate); |
413 | return false; | 408 | if (!ret) |
414 | } else { | 409 | ath_print(common, ATH_DBG_CONFIG, |
415 | *cw40 = true; | 410 | "Updated target sta: %pM, rate caps: 0x%X\n", |
416 | return true; | 411 | sta->addr, be32_to_cpu(trate.capflags)); |
417 | } | ||
418 | } else { /* ht20 */ | ||
419 | if (priv->ah->curchan->chanmode & CHANNEL_HT20) | ||
420 | return false; | ||
421 | else | ||
422 | return true; | ||
423 | } | ||
424 | } | 412 | } |
425 | 413 | ||
426 | static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40) | 414 | static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, |
415 | struct ieee80211_vif *vif, | ||
416 | struct ieee80211_bss_conf *bss_conf) | ||
427 | { | 417 | { |
428 | struct ath9k_htc_target_rate trate; | ||
429 | struct ath_common *common = ath9k_hw_common(priv->ah); | 418 | struct ath_common *common = ath9k_hw_common(priv->ah); |
419 | struct ath9k_htc_target_rate trate; | ||
420 | struct ieee80211_sta *sta; | ||
430 | int ret; | 421 | int ret; |
431 | u32 caps = be32_to_cpu(priv->tgt_rate.capflags); | ||
432 | u8 cmd_rsp; | ||
433 | |||
434 | memset(&trate, 0, sizeof(trate)); | ||
435 | |||
436 | trate = priv->tgt_rate; | ||
437 | 422 | ||
438 | if (is_cw40) | 423 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); |
439 | caps |= WLAN_RC_40_FLAG; | ||
440 | else | ||
441 | caps &= ~WLAN_RC_40_FLAG; | ||
442 | |||
443 | priv->tgt_rate.capflags = cpu_to_be32(caps); | ||
444 | trate.capflags = cpu_to_be32(caps); | ||
445 | 424 | ||
446 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); | 425 | rcu_read_lock(); |
447 | if (ret) { | 426 | sta = ieee80211_find_sta(vif, bss_conf->bssid); |
448 | ath_print(common, ATH_DBG_FATAL, | 427 | if (!sta) { |
449 | "Unable to update Rate information on target\n"); | 428 | rcu_read_unlock(); |
450 | return; | 429 | return; |
451 | } | 430 | } |
431 | ath9k_htc_setup_rate(priv, sta, &trate); | ||
432 | rcu_read_unlock(); | ||
452 | 433 | ||
453 | ath_print(common, ATH_DBG_CONFIG, "Rate control updated with " | 434 | ret = ath9k_htc_send_rate_cmd(priv, &trate); |
454 | "caps:0x%x on target\n", priv->tgt_rate.capflags); | 435 | if (!ret) |
436 | ath_print(common, ATH_DBG_CONFIG, | ||
437 | "Updated target sta: %pM, rate caps: 0x%X\n", | ||
438 | bss_conf->bssid, be32_to_cpu(trate.capflags)); | ||
455 | } | 439 | } |
456 | 440 | ||
457 | static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | 441 | int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, |
458 | struct ieee80211_vif *vif, | 442 | struct ieee80211_vif *vif, |
459 | u8 *sta_addr, u8 tid, bool oper) | 443 | struct ieee80211_sta *sta, |
444 | enum ieee80211_ampdu_mlme_action action, u16 tid) | ||
460 | { | 445 | { |
461 | struct ath_common *common = ath9k_hw_common(priv->ah); | 446 | struct ath_common *common = ath9k_hw_common(priv->ah); |
462 | struct ath9k_htc_target_aggr aggr; | 447 | struct ath9k_htc_target_aggr aggr; |
463 | struct ieee80211_sta *sta = NULL; | ||
464 | struct ath9k_htc_sta *ista; | 448 | struct ath9k_htc_sta *ista; |
465 | int ret = 0; | 449 | int ret = 0; |
466 | u8 cmd_rsp; | 450 | u8 cmd_rsp; |
@@ -469,72 +453,28 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | |||
469 | return -EINVAL; | 453 | return -EINVAL; |
470 | 454 | ||
471 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); | 455 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); |
472 | |||
473 | rcu_read_lock(); | ||
474 | |||
475 | /* Check if we are able to retrieve the station */ | ||
476 | sta = ieee80211_find_sta(vif, sta_addr); | ||
477 | if (!sta) { | ||
478 | rcu_read_unlock(); | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | |||
482 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 456 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
483 | 457 | ||
484 | if (oper) | ||
485 | ista->tid_state[tid] = AGGR_START; | ||
486 | else | ||
487 | ista->tid_state[tid] = AGGR_STOP; | ||
488 | |||
489 | aggr.sta_index = ista->index; | 458 | aggr.sta_index = ista->index; |
490 | 459 | aggr.tidno = tid & 0xf; | |
491 | rcu_read_unlock(); | 460 | aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false; |
492 | |||
493 | aggr.tidno = tid; | ||
494 | aggr.aggr_enable = oper; | ||
495 | 461 | ||
496 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); | 462 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); |
497 | if (ret) | 463 | if (ret) |
498 | ath_print(common, ATH_DBG_CONFIG, | 464 | ath_print(common, ATH_DBG_CONFIG, |
499 | "Unable to %s TX aggregation for (%pM, %d)\n", | 465 | "Unable to %s TX aggregation for (%pM, %d)\n", |
500 | (oper) ? "start" : "stop", sta->addr, tid); | 466 | (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); |
501 | else | 467 | else |
502 | ath_print(common, ATH_DBG_CONFIG, | 468 | ath_print(common, ATH_DBG_CONFIG, |
503 | "%s aggregation for (%pM, %d)\n", | 469 | "%s TX aggregation for (%pM, %d)\n", |
504 | (oper) ? "Starting" : "Stopping", sta->addr, tid); | 470 | (aggr.aggr_enable) ? "Starting" : "Stopping", |
505 | 471 | sta->addr, tid); | |
506 | return ret; | ||
507 | } | ||
508 | 472 | ||
509 | void ath9k_htc_aggr_work(struct work_struct *work) | 473 | spin_lock_bh(&priv->tx_lock); |
510 | { | 474 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; |
511 | int ret = 0; | 475 | spin_unlock_bh(&priv->tx_lock); |
512 | struct ath9k_htc_priv *priv = | ||
513 | container_of(work, struct ath9k_htc_priv, | ||
514 | ath9k_aggr_work.work); | ||
515 | struct ath9k_htc_aggr_work *wk = &priv->aggr_work; | ||
516 | |||
517 | mutex_lock(&wk->mutex); | ||
518 | |||
519 | switch (wk->action) { | ||
520 | case IEEE80211_AMPDU_TX_START: | ||
521 | ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, | ||
522 | wk->tid, true); | ||
523 | if (!ret) | ||
524 | ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr, | ||
525 | wk->tid); | ||
526 | break; | ||
527 | case IEEE80211_AMPDU_TX_STOP: | ||
528 | ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, | ||
529 | wk->tid, false); | ||
530 | ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid); | ||
531 | break; | ||
532 | default: | ||
533 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | ||
534 | "Unknown AMPDU action\n"); | ||
535 | } | ||
536 | 476 | ||
537 | mutex_unlock(&wk->mutex); | 477 | return ret; |
538 | } | 478 | } |
539 | 479 | ||
540 | /*********/ | 480 | /*********/ |
@@ -617,6 +557,19 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
617 | "%20s : %10u\n", "SKBs dropped", | 557 | "%20s : %10u\n", "SKBs dropped", |
618 | priv->debug.tx_stats.skb_dropped); | 558 | priv->debug.tx_stats.skb_dropped); |
619 | 559 | ||
560 | len += snprintf(buf + len, sizeof(buf) - len, | ||
561 | "%20s : %10u\n", "BE queued", | ||
562 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
563 | len += snprintf(buf + len, sizeof(buf) - len, | ||
564 | "%20s : %10u\n", "BK queued", | ||
565 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
566 | len += snprintf(buf + len, sizeof(buf) - len, | ||
567 | "%20s : %10u\n", "VI queued", | ||
568 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
569 | len += snprintf(buf + len, sizeof(buf) - len, | ||
570 | "%20s : %10u\n", "VO queued", | ||
571 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
572 | |||
620 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 573 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
621 | } | 574 | } |
622 | 575 | ||
@@ -1054,6 +1007,95 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) | |||
1054 | wiphy_rfkill_start_polling(priv->hw->wiphy); | 1007 | wiphy_rfkill_start_polling(priv->hw->wiphy); |
1055 | } | 1008 | } |
1056 | 1009 | ||
1010 | static void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | ||
1011 | { | ||
1012 | struct ath9k_htc_priv *priv = hw->priv; | ||
1013 | struct ath_hw *ah = priv->ah; | ||
1014 | struct ath_common *common = ath9k_hw_common(ah); | ||
1015 | int ret; | ||
1016 | u8 cmd_rsp; | ||
1017 | |||
1018 | if (!ah->curchan) | ||
1019 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
1020 | |||
1021 | /* Reset the HW */ | ||
1022 | ret = ath9k_hw_reset(ah, ah->curchan, false); | ||
1023 | if (ret) { | ||
1024 | ath_print(common, ATH_DBG_FATAL, | ||
1025 | "Unable to reset hardware; reset status %d " | ||
1026 | "(freq %u MHz)\n", ret, ah->curchan->channel); | ||
1027 | } | ||
1028 | |||
1029 | ath_update_txpow(priv); | ||
1030 | |||
1031 | /* Start RX */ | ||
1032 | WMI_CMD(WMI_START_RECV_CMDID); | ||
1033 | ath9k_host_rx_init(priv); | ||
1034 | |||
1035 | /* Start TX */ | ||
1036 | htc_start(priv->htc); | ||
1037 | spin_lock_bh(&priv->tx_lock); | ||
1038 | priv->tx_queues_stop = false; | ||
1039 | spin_unlock_bh(&priv->tx_lock); | ||
1040 | ieee80211_wake_queues(hw); | ||
1041 | |||
1042 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | ||
1043 | |||
1044 | /* Enable LED */ | ||
1045 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
1046 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1047 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
1048 | } | ||
1049 | |||
1050 | static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | ||
1051 | { | ||
1052 | struct ath9k_htc_priv *priv = hw->priv; | ||
1053 | struct ath_hw *ah = priv->ah; | ||
1054 | struct ath_common *common = ath9k_hw_common(ah); | ||
1055 | int ret; | ||
1056 | u8 cmd_rsp; | ||
1057 | |||
1058 | ath9k_htc_ps_wakeup(priv); | ||
1059 | |||
1060 | /* Disable LED */ | ||
1061 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
1062 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
1063 | |||
1064 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
1065 | |||
1066 | /* Stop TX */ | ||
1067 | ieee80211_stop_queues(hw); | ||
1068 | htc_stop(priv->htc); | ||
1069 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
1070 | skb_queue_purge(&priv->tx_queue); | ||
1071 | |||
1072 | /* Stop RX */ | ||
1073 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
1074 | |||
1075 | /* | ||
1076 | * The MIB counters have to be disabled here, | ||
1077 | * since the target doesn't do it. | ||
1078 | */ | ||
1079 | ath9k_hw_disable_mib_counters(ah); | ||
1080 | |||
1081 | if (!ah->curchan) | ||
1082 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
1083 | |||
1084 | /* Reset the HW */ | ||
1085 | ret = ath9k_hw_reset(ah, ah->curchan, false); | ||
1086 | if (ret) { | ||
1087 | ath_print(common, ATH_DBG_FATAL, | ||
1088 | "Unable to reset hardware; reset status %d " | ||
1089 | "(freq %u MHz)\n", ret, ah->curchan->channel); | ||
1090 | } | ||
1091 | |||
1092 | /* Disable the PHY */ | ||
1093 | ath9k_hw_phy_disable(ah); | ||
1094 | |||
1095 | ath9k_htc_ps_restore(priv); | ||
1096 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
1097 | } | ||
1098 | |||
1057 | /**********************/ | 1099 | /**********************/ |
1058 | /* mac80211 Callbacks */ | 1100 | /* mac80211 Callbacks */ |
1059 | /**********************/ | 1101 | /**********************/ |
@@ -1099,7 +1141,7 @@ fail_tx: | |||
1099 | return 0; | 1141 | return 0; |
1100 | } | 1142 | } |
1101 | 1143 | ||
1102 | static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) | 1144 | static int ath9k_htc_start(struct ieee80211_hw *hw) |
1103 | { | 1145 | { |
1104 | struct ath9k_htc_priv *priv = hw->priv; | 1146 | struct ath9k_htc_priv *priv = hw->priv; |
1105 | struct ath_hw *ah = priv->ah; | 1147 | struct ath_hw *ah = priv->ah; |
@@ -1111,10 +1153,16 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) | |||
1111 | __be16 htc_mode; | 1153 | __be16 htc_mode; |
1112 | u8 cmd_rsp; | 1154 | u8 cmd_rsp; |
1113 | 1155 | ||
1156 | mutex_lock(&priv->mutex); | ||
1157 | |||
1114 | ath_print(common, ATH_DBG_CONFIG, | 1158 | ath_print(common, ATH_DBG_CONFIG, |
1115 | "Starting driver with initial channel: %d MHz\n", | 1159 | "Starting driver with initial channel: %d MHz\n", |
1116 | curchan->center_freq); | 1160 | curchan->center_freq); |
1117 | 1161 | ||
1162 | /* Ensure that HW is awake before flushing RX */ | ||
1163 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
1164 | WMI_CMD(WMI_FLUSH_RECV_CMDID); | ||
1165 | |||
1118 | /* setup initial channel */ | 1166 | /* setup initial channel */ |
1119 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 1167 | init_channel = ath9k_cmn_get_curchannel(hw, ah); |
1120 | 1168 | ||
@@ -1127,6 +1175,7 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) | |||
1127 | ath_print(common, ATH_DBG_FATAL, | 1175 | ath_print(common, ATH_DBG_FATAL, |
1128 | "Unable to reset hardware; reset status %d " | 1176 | "Unable to reset hardware; reset status %d " |
1129 | "(freq %u MHz)\n", ret, curchan->center_freq); | 1177 | "(freq %u MHz)\n", ret, curchan->center_freq); |
1178 | mutex_unlock(&priv->mutex); | ||
1130 | return ret; | 1179 | return ret; |
1131 | } | 1180 | } |
1132 | 1181 | ||
@@ -1147,31 +1196,14 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led) | |||
1147 | priv->tx_queues_stop = false; | 1196 | priv->tx_queues_stop = false; |
1148 | spin_unlock_bh(&priv->tx_lock); | 1197 | spin_unlock_bh(&priv->tx_lock); |
1149 | 1198 | ||
1150 | if (led) { | ||
1151 | /* Enable LED */ | ||
1152 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
1153 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1154 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
1155 | } | ||
1156 | |||
1157 | ieee80211_wake_queues(hw); | 1199 | ieee80211_wake_queues(hw); |
1158 | 1200 | ||
1159 | return ret; | ||
1160 | } | ||
1161 | |||
1162 | static int ath9k_htc_start(struct ieee80211_hw *hw) | ||
1163 | { | ||
1164 | struct ath9k_htc_priv *priv = hw->priv; | ||
1165 | int ret = 0; | ||
1166 | |||
1167 | mutex_lock(&priv->mutex); | ||
1168 | ret = ath9k_htc_radio_enable(hw, false); | ||
1169 | mutex_unlock(&priv->mutex); | 1201 | mutex_unlock(&priv->mutex); |
1170 | 1202 | ||
1171 | return ret; | 1203 | return ret; |
1172 | } | 1204 | } |
1173 | 1205 | ||
1174 | static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) | 1206 | static void ath9k_htc_stop(struct ieee80211_hw *hw) |
1175 | { | 1207 | { |
1176 | struct ath9k_htc_priv *priv = hw->priv; | 1208 | struct ath9k_htc_priv *priv = hw->priv; |
1177 | struct ath_hw *ah = priv->ah; | 1209 | struct ath_hw *ah = priv->ah; |
@@ -1179,21 +1211,17 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) | |||
1179 | int ret = 0; | 1211 | int ret = 0; |
1180 | u8 cmd_rsp; | 1212 | u8 cmd_rsp; |
1181 | 1213 | ||
1214 | mutex_lock(&priv->mutex); | ||
1215 | |||
1182 | if (priv->op_flags & OP_INVALID) { | 1216 | if (priv->op_flags & OP_INVALID) { |
1183 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); | 1217 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); |
1218 | mutex_unlock(&priv->mutex); | ||
1184 | return; | 1219 | return; |
1185 | } | 1220 | } |
1186 | 1221 | ||
1187 | if (led) { | ||
1188 | /* Disable LED */ | ||
1189 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
1190 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
1191 | } | ||
1192 | |||
1193 | /* Cancel all the running timers/work .. */ | 1222 | /* Cancel all the running timers/work .. */ |
1194 | cancel_work_sync(&priv->ps_work); | 1223 | cancel_work_sync(&priv->ps_work); |
1195 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1224 | cancel_delayed_work_sync(&priv->ath9k_ani_work); |
1196 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); | ||
1197 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1225 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); |
1198 | ath9k_led_stop_brightness(priv); | 1226 | ath9k_led_stop_brightness(priv); |
1199 | 1227 | ||
@@ -1202,12 +1230,6 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) | |||
1202 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 1230 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
1203 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 1231 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
1204 | WMI_CMD(WMI_STOP_RECV_CMDID); | 1232 | WMI_CMD(WMI_STOP_RECV_CMDID); |
1205 | ath9k_hw_phy_disable(ah); | ||
1206 | ath9k_hw_disable(ah); | ||
1207 | ath9k_hw_configpcipowersave(ah, 1, 1); | ||
1208 | ath9k_htc_ps_restore(priv); | ||
1209 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
1210 | |||
1211 | skb_queue_purge(&priv->tx_queue); | 1233 | skb_queue_purge(&priv->tx_queue); |
1212 | 1234 | ||
1213 | /* Remove monitor interface here */ | 1235 | /* Remove monitor interface here */ |
@@ -1220,21 +1242,18 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led) | |||
1220 | "Monitor interface removed\n"); | 1242 | "Monitor interface removed\n"); |
1221 | } | 1243 | } |
1222 | 1244 | ||
1245 | ath9k_hw_phy_disable(ah); | ||
1246 | ath9k_hw_disable(ah); | ||
1247 | ath9k_hw_configpcipowersave(ah, 1, 1); | ||
1248 | ath9k_htc_ps_restore(priv); | ||
1249 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
1250 | |||
1223 | priv->op_flags |= OP_INVALID; | 1251 | priv->op_flags |= OP_INVALID; |
1224 | 1252 | ||
1225 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); | 1253 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); |
1226 | } | ||
1227 | |||
1228 | static void ath9k_htc_stop(struct ieee80211_hw *hw) | ||
1229 | { | ||
1230 | struct ath9k_htc_priv *priv = hw->priv; | ||
1231 | |||
1232 | mutex_lock(&priv->mutex); | ||
1233 | ath9k_htc_radio_disable(hw, false); | ||
1234 | mutex_unlock(&priv->mutex); | 1254 | mutex_unlock(&priv->mutex); |
1235 | } | 1255 | } |
1236 | 1256 | ||
1237 | |||
1238 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | 1257 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, |
1239 | struct ieee80211_vif *vif) | 1258 | struct ieee80211_vif *vif) |
1240 | { | 1259 | { |
@@ -1302,6 +1321,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1302 | out: | 1321 | out: |
1303 | ath9k_htc_ps_restore(priv); | 1322 | ath9k_htc_ps_restore(priv); |
1304 | mutex_unlock(&priv->mutex); | 1323 | mutex_unlock(&priv->mutex); |
1324 | |||
1305 | return ret; | 1325 | return ret; |
1306 | } | 1326 | } |
1307 | 1327 | ||
@@ -1318,6 +1338,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1318 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | 1338 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
1319 | 1339 | ||
1320 | mutex_lock(&priv->mutex); | 1340 | mutex_lock(&priv->mutex); |
1341 | ath9k_htc_ps_wakeup(priv); | ||
1321 | 1342 | ||
1322 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 1343 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
1323 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | 1344 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
@@ -1328,6 +1349,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1328 | ath9k_htc_remove_station(priv, vif, NULL); | 1349 | ath9k_htc_remove_station(priv, vif, NULL); |
1329 | priv->vif = NULL; | 1350 | priv->vif = NULL; |
1330 | 1351 | ||
1352 | ath9k_htc_ps_restore(priv); | ||
1331 | mutex_unlock(&priv->mutex); | 1353 | mutex_unlock(&priv->mutex); |
1332 | } | 1354 | } |
1333 | 1355 | ||
@@ -1343,30 +1365,27 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1343 | bool enable_radio = false; | 1365 | bool enable_radio = false; |
1344 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 1366 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1345 | 1367 | ||
1368 | mutex_lock(&priv->htc_pm_lock); | ||
1346 | if (!idle && priv->ps_idle) | 1369 | if (!idle && priv->ps_idle) |
1347 | enable_radio = true; | 1370 | enable_radio = true; |
1348 | |||
1349 | priv->ps_idle = idle; | 1371 | priv->ps_idle = idle; |
1372 | mutex_unlock(&priv->htc_pm_lock); | ||
1350 | 1373 | ||
1351 | if (enable_radio) { | 1374 | if (enable_radio) { |
1352 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
1353 | ath9k_htc_radio_enable(hw, true); | ||
1354 | ath_print(common, ATH_DBG_CONFIG, | 1375 | ath_print(common, ATH_DBG_CONFIG, |
1355 | "not-idle: enabling radio\n"); | 1376 | "not-idle: enabling radio\n"); |
1377 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
1378 | ath9k_htc_radio_enable(hw); | ||
1356 | } | 1379 | } |
1357 | } | 1380 | } |
1358 | 1381 | ||
1359 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1382 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1360 | struct ieee80211_channel *curchan = hw->conf.channel; | 1383 | struct ieee80211_channel *curchan = hw->conf.channel; |
1361 | int pos = curchan->hw_value; | 1384 | int pos = curchan->hw_value; |
1362 | bool is_cw40 = false; | ||
1363 | 1385 | ||
1364 | ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 1386 | ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
1365 | curchan->center_freq); | 1387 | curchan->center_freq); |
1366 | 1388 | ||
1367 | if (check_rc_update(hw, &is_cw40)) | ||
1368 | ath9k_htc_rc_update(priv, is_cw40); | ||
1369 | |||
1370 | ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); | 1389 | ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); |
1371 | 1390 | ||
1372 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | 1391 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { |
@@ -1399,14 +1418,21 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1399 | } | 1418 | } |
1400 | } | 1419 | } |
1401 | 1420 | ||
1402 | if (priv->ps_idle) { | 1421 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1422 | mutex_lock(&priv->htc_pm_lock); | ||
1423 | if (!priv->ps_idle) { | ||
1424 | mutex_unlock(&priv->htc_pm_lock); | ||
1425 | goto out; | ||
1426 | } | ||
1427 | mutex_unlock(&priv->htc_pm_lock); | ||
1428 | |||
1403 | ath_print(common, ATH_DBG_CONFIG, | 1429 | ath_print(common, ATH_DBG_CONFIG, |
1404 | "idle: disabling radio\n"); | 1430 | "idle: disabling radio\n"); |
1405 | ath9k_htc_radio_disable(hw, true); | 1431 | ath9k_htc_radio_disable(hw); |
1406 | } | 1432 | } |
1407 | 1433 | ||
1434 | out: | ||
1408 | mutex_unlock(&priv->mutex); | 1435 | mutex_unlock(&priv->mutex); |
1409 | |||
1410 | return 0; | 1436 | return 0; |
1411 | } | 1437 | } |
1412 | 1438 | ||
@@ -1428,8 +1454,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | |||
1428 | u32 rfilt; | 1454 | u32 rfilt; |
1429 | 1455 | ||
1430 | mutex_lock(&priv->mutex); | 1456 | mutex_lock(&priv->mutex); |
1431 | |||
1432 | ath9k_htc_ps_wakeup(priv); | 1457 | ath9k_htc_ps_wakeup(priv); |
1458 | |||
1433 | changed_flags &= SUPPORTED_FILTERS; | 1459 | changed_flags &= SUPPORTED_FILTERS; |
1434 | *total_flags &= SUPPORTED_FILTERS; | 1460 | *total_flags &= SUPPORTED_FILTERS; |
1435 | 1461 | ||
@@ -1444,30 +1470,38 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | |||
1444 | mutex_unlock(&priv->mutex); | 1470 | mutex_unlock(&priv->mutex); |
1445 | } | 1471 | } |
1446 | 1472 | ||
1447 | static void ath9k_htc_sta_notify(struct ieee80211_hw *hw, | 1473 | static int ath9k_htc_sta_add(struct ieee80211_hw *hw, |
1448 | struct ieee80211_vif *vif, | 1474 | struct ieee80211_vif *vif, |
1449 | enum sta_notify_cmd cmd, | 1475 | struct ieee80211_sta *sta) |
1450 | struct ieee80211_sta *sta) | ||
1451 | { | 1476 | { |
1452 | struct ath9k_htc_priv *priv = hw->priv; | 1477 | struct ath9k_htc_priv *priv = hw->priv; |
1453 | int ret; | 1478 | int ret; |
1454 | 1479 | ||
1455 | mutex_lock(&priv->mutex); | 1480 | mutex_lock(&priv->mutex); |
1481 | ath9k_htc_ps_wakeup(priv); | ||
1482 | ret = ath9k_htc_add_station(priv, vif, sta); | ||
1483 | if (!ret) | ||
1484 | ath9k_htc_init_rate(priv, sta); | ||
1485 | ath9k_htc_ps_restore(priv); | ||
1486 | mutex_unlock(&priv->mutex); | ||
1456 | 1487 | ||
1457 | switch (cmd) { | 1488 | return ret; |
1458 | case STA_NOTIFY_ADD: | 1489 | } |
1459 | ret = ath9k_htc_add_station(priv, vif, sta); | 1490 | |
1460 | if (!ret) | 1491 | static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, |
1461 | ath9k_htc_init_rate(priv, vif, sta); | 1492 | struct ieee80211_vif *vif, |
1462 | break; | 1493 | struct ieee80211_sta *sta) |
1463 | case STA_NOTIFY_REMOVE: | 1494 | { |
1464 | ath9k_htc_remove_station(priv, vif, sta); | 1495 | struct ath9k_htc_priv *priv = hw->priv; |
1465 | break; | 1496 | int ret; |
1466 | default: | ||
1467 | break; | ||
1468 | } | ||
1469 | 1497 | ||
1498 | mutex_lock(&priv->mutex); | ||
1499 | ath9k_htc_ps_wakeup(priv); | ||
1500 | ret = ath9k_htc_remove_station(priv, vif, sta); | ||
1501 | ath9k_htc_ps_restore(priv); | ||
1470 | mutex_unlock(&priv->mutex); | 1502 | mutex_unlock(&priv->mutex); |
1503 | |||
1504 | return ret; | ||
1471 | } | 1505 | } |
1472 | 1506 | ||
1473 | static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1507 | static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -1482,6 +1516,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1482 | return 0; | 1516 | return 0; |
1483 | 1517 | ||
1484 | mutex_lock(&priv->mutex); | 1518 | mutex_lock(&priv->mutex); |
1519 | ath9k_htc_ps_wakeup(priv); | ||
1485 | 1520 | ||
1486 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | 1521 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
1487 | 1522 | ||
@@ -1499,9 +1534,16 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1499 | params->cw_max, params->txop); | 1534 | params->cw_max, params->txop); |
1500 | 1535 | ||
1501 | ret = ath_htc_txq_update(priv, qnum, &qi); | 1536 | ret = ath_htc_txq_update(priv, qnum, &qi); |
1502 | if (ret) | 1537 | if (ret) { |
1503 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); | 1538 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); |
1539 | goto out; | ||
1540 | } | ||
1504 | 1541 | ||
1542 | if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) && | ||
1543 | (qnum == priv->hwq_map[WME_AC_BE])) | ||
1544 | ath9k_htc_beaconq_config(priv); | ||
1545 | out: | ||
1546 | ath9k_htc_ps_restore(priv); | ||
1505 | mutex_unlock(&priv->mutex); | 1547 | mutex_unlock(&priv->mutex); |
1506 | 1548 | ||
1507 | return ret; | 1549 | return ret; |
@@ -1574,7 +1616,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1574 | ath_start_ani(priv); | 1616 | ath_start_ani(priv); |
1575 | } else { | 1617 | } else { |
1576 | priv->op_flags &= ~OP_ASSOCIATED; | 1618 | priv->op_flags &= ~OP_ASSOCIATED; |
1577 | cancel_work_sync(&priv->ps_work); | ||
1578 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1619 | cancel_delayed_work_sync(&priv->ath9k_ani_work); |
1579 | } | 1620 | } |
1580 | } | 1621 | } |
@@ -1631,6 +1672,9 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1631 | ath9k_hw_init_global_settings(ah); | 1672 | ath9k_hw_init_global_settings(ah); |
1632 | } | 1673 | } |
1633 | 1674 | ||
1675 | if (changed & BSS_CHANGED_HT) | ||
1676 | ath9k_htc_update_rate(priv, vif, bss_conf); | ||
1677 | |||
1634 | ath9k_htc_ps_restore(priv); | 1678 | ath9k_htc_ps_restore(priv); |
1635 | mutex_unlock(&priv->mutex); | 1679 | mutex_unlock(&priv->mutex); |
1636 | } | 1680 | } |
@@ -1641,7 +1685,9 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) | |||
1641 | u64 tsf; | 1685 | u64 tsf; |
1642 | 1686 | ||
1643 | mutex_lock(&priv->mutex); | 1687 | mutex_lock(&priv->mutex); |
1688 | ath9k_htc_ps_wakeup(priv); | ||
1644 | tsf = ath9k_hw_gettsf64(priv->ah); | 1689 | tsf = ath9k_hw_gettsf64(priv->ah); |
1690 | ath9k_htc_ps_restore(priv); | ||
1645 | mutex_unlock(&priv->mutex); | 1691 | mutex_unlock(&priv->mutex); |
1646 | 1692 | ||
1647 | return tsf; | 1693 | return tsf; |
@@ -1652,7 +1698,9 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) | |||
1652 | struct ath9k_htc_priv *priv = hw->priv; | 1698 | struct ath9k_htc_priv *priv = hw->priv; |
1653 | 1699 | ||
1654 | mutex_lock(&priv->mutex); | 1700 | mutex_lock(&priv->mutex); |
1701 | ath9k_htc_ps_wakeup(priv); | ||
1655 | ath9k_hw_settsf64(priv->ah, tsf); | 1702 | ath9k_hw_settsf64(priv->ah, tsf); |
1703 | ath9k_htc_ps_restore(priv); | ||
1656 | mutex_unlock(&priv->mutex); | 1704 | mutex_unlock(&priv->mutex); |
1657 | } | 1705 | } |
1658 | 1706 | ||
@@ -1660,11 +1708,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) | |||
1660 | { | 1708 | { |
1661 | struct ath9k_htc_priv *priv = hw->priv; | 1709 | struct ath9k_htc_priv *priv = hw->priv; |
1662 | 1710 | ||
1663 | ath9k_htc_ps_wakeup(priv); | ||
1664 | mutex_lock(&priv->mutex); | 1711 | mutex_lock(&priv->mutex); |
1712 | ath9k_htc_ps_wakeup(priv); | ||
1665 | ath9k_hw_reset_tsf(priv->ah); | 1713 | ath9k_hw_reset_tsf(priv->ah); |
1666 | mutex_unlock(&priv->mutex); | ||
1667 | ath9k_htc_ps_restore(priv); | 1714 | ath9k_htc_ps_restore(priv); |
1715 | mutex_unlock(&priv->mutex); | ||
1668 | } | 1716 | } |
1669 | 1717 | ||
1670 | static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | 1718 | static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, |
@@ -1674,8 +1722,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1674 | u16 tid, u16 *ssn) | 1722 | u16 tid, u16 *ssn) |
1675 | { | 1723 | { |
1676 | struct ath9k_htc_priv *priv = hw->priv; | 1724 | struct ath9k_htc_priv *priv = hw->priv; |
1677 | struct ath9k_htc_aggr_work *work = &priv->aggr_work; | ||
1678 | struct ath9k_htc_sta *ista; | 1725 | struct ath9k_htc_sta *ista; |
1726 | int ret = 0; | ||
1679 | 1727 | ||
1680 | switch (action) { | 1728 | switch (action) { |
1681 | case IEEE80211_AMPDU_RX_START: | 1729 | case IEEE80211_AMPDU_RX_START: |
@@ -1683,26 +1731,26 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1683 | case IEEE80211_AMPDU_RX_STOP: | 1731 | case IEEE80211_AMPDU_RX_STOP: |
1684 | break; | 1732 | break; |
1685 | case IEEE80211_AMPDU_TX_START: | 1733 | case IEEE80211_AMPDU_TX_START: |
1734 | ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); | ||
1735 | if (!ret) | ||
1736 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1737 | break; | ||
1686 | case IEEE80211_AMPDU_TX_STOP: | 1738 | case IEEE80211_AMPDU_TX_STOP: |
1687 | if (!(priv->op_flags & OP_TXAGGR)) | 1739 | ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); |
1688 | return -ENOTSUPP; | 1740 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1689 | memcpy(work->sta_addr, sta->addr, ETH_ALEN); | ||
1690 | work->hw = hw; | ||
1691 | work->vif = vif; | ||
1692 | work->action = action; | ||
1693 | work->tid = tid; | ||
1694 | ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0); | ||
1695 | break; | 1741 | break; |
1696 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1742 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
1697 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 1743 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1744 | spin_lock_bh(&priv->tx_lock); | ||
1698 | ista->tid_state[tid] = AGGR_OPERATIONAL; | 1745 | ista->tid_state[tid] = AGGR_OPERATIONAL; |
1746 | spin_unlock_bh(&priv->tx_lock); | ||
1699 | break; | 1747 | break; |
1700 | default: | 1748 | default: |
1701 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | 1749 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, |
1702 | "Unknown AMPDU action\n"); | 1750 | "Unknown AMPDU action\n"); |
1703 | } | 1751 | } |
1704 | 1752 | ||
1705 | return 0; | 1753 | return ret; |
1706 | } | 1754 | } |
1707 | 1755 | ||
1708 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | 1756 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) |
@@ -1722,8 +1770,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | |||
1722 | { | 1770 | { |
1723 | struct ath9k_htc_priv *priv = hw->priv; | 1771 | struct ath9k_htc_priv *priv = hw->priv; |
1724 | 1772 | ||
1725 | ath9k_htc_ps_wakeup(priv); | ||
1726 | mutex_lock(&priv->mutex); | 1773 | mutex_lock(&priv->mutex); |
1774 | ath9k_htc_ps_wakeup(priv); | ||
1727 | spin_lock_bh(&priv->beacon_lock); | 1775 | spin_lock_bh(&priv->beacon_lock); |
1728 | priv->op_flags &= ~OP_SCANNING; | 1776 | priv->op_flags &= ~OP_SCANNING; |
1729 | spin_unlock_bh(&priv->beacon_lock); | 1777 | spin_unlock_bh(&priv->beacon_lock); |
@@ -1731,8 +1779,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | |||
1731 | if (priv->op_flags & OP_ASSOCIATED) | 1779 | if (priv->op_flags & OP_ASSOCIATED) |
1732 | ath9k_htc_beacon_config(priv, priv->vif); | 1780 | ath9k_htc_beacon_config(priv, priv->vif); |
1733 | ath_start_ani(priv); | 1781 | ath_start_ani(priv); |
1734 | mutex_unlock(&priv->mutex); | ||
1735 | ath9k_htc_ps_restore(priv); | 1782 | ath9k_htc_ps_restore(priv); |
1783 | mutex_unlock(&priv->mutex); | ||
1736 | } | 1784 | } |
1737 | 1785 | ||
1738 | static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1786 | static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
@@ -1746,8 +1794,10 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, | |||
1746 | struct ath9k_htc_priv *priv = hw->priv; | 1794 | struct ath9k_htc_priv *priv = hw->priv; |
1747 | 1795 | ||
1748 | mutex_lock(&priv->mutex); | 1796 | mutex_lock(&priv->mutex); |
1797 | ath9k_htc_ps_wakeup(priv); | ||
1749 | priv->ah->coverage_class = coverage_class; | 1798 | priv->ah->coverage_class = coverage_class; |
1750 | ath9k_hw_init_global_settings(priv->ah); | 1799 | ath9k_hw_init_global_settings(priv->ah); |
1800 | ath9k_htc_ps_restore(priv); | ||
1751 | mutex_unlock(&priv->mutex); | 1801 | mutex_unlock(&priv->mutex); |
1752 | } | 1802 | } |
1753 | 1803 | ||
@@ -1759,7 +1809,8 @@ struct ieee80211_ops ath9k_htc_ops = { | |||
1759 | .remove_interface = ath9k_htc_remove_interface, | 1809 | .remove_interface = ath9k_htc_remove_interface, |
1760 | .config = ath9k_htc_config, | 1810 | .config = ath9k_htc_config, |
1761 | .configure_filter = ath9k_htc_configure_filter, | 1811 | .configure_filter = ath9k_htc_configure_filter, |
1762 | .sta_notify = ath9k_htc_sta_notify, | 1812 | .sta_add = ath9k_htc_sta_add, |
1813 | .sta_remove = ath9k_htc_sta_remove, | ||
1763 | .conf_tx = ath9k_htc_conf_tx, | 1814 | .conf_tx = ath9k_htc_conf_tx, |
1764 | .bss_info_changed = ath9k_htc_bss_info_changed, | 1815 | .bss_info_changed = ath9k_htc_bss_info_changed, |
1765 | .set_key = ath9k_htc_set_key, | 1816 | .set_key = ath9k_htc_set_key, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2571b443ac82..bd0b4acc3ece 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -20,19 +20,29 @@ | |||
20 | /* TX */ | 20 | /* TX */ |
21 | /******/ | 21 | /******/ |
22 | 22 | ||
23 | #define ATH9K_HTC_INIT_TXQ(subtype) do { \ | ||
24 | qi.tqi_subtype = subtype; \ | ||
25 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ | ||
26 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ | ||
27 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ | ||
28 | qi.tqi_physCompBuf = 0; \ | ||
29 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | \ | ||
30 | TXQ_FLAG_TXDESCINT_ENABLE; \ | ||
31 | } while (0) | ||
32 | |||
23 | int get_hw_qnum(u16 queue, int *hwq_map) | 33 | int get_hw_qnum(u16 queue, int *hwq_map) |
24 | { | 34 | { |
25 | switch (queue) { | 35 | switch (queue) { |
26 | case 0: | 36 | case 0: |
27 | return hwq_map[ATH9K_WME_AC_VO]; | 37 | return hwq_map[WME_AC_VO]; |
28 | case 1: | 38 | case 1: |
29 | return hwq_map[ATH9K_WME_AC_VI]; | 39 | return hwq_map[WME_AC_VI]; |
30 | case 2: | 40 | case 2: |
31 | return hwq_map[ATH9K_WME_AC_BE]; | 41 | return hwq_map[WME_AC_BE]; |
32 | case 3: | 42 | case 3: |
33 | return hwq_map[ATH9K_WME_AC_BK]; | 43 | return hwq_map[WME_AC_BK]; |
34 | default: | 44 | default: |
35 | return hwq_map[ATH9K_WME_AC_BE]; | 45 | return hwq_map[WME_AC_BE]; |
36 | } | 46 | } |
37 | } | 47 | } |
38 | 48 | ||
@@ -71,7 +81,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
71 | struct ath9k_htc_vif *avp; | 81 | struct ath9k_htc_vif *avp; |
72 | struct ath9k_htc_tx_ctl tx_ctl; | 82 | struct ath9k_htc_tx_ctl tx_ctl; |
73 | enum htc_endpoint_id epid; | 83 | enum htc_endpoint_id epid; |
74 | u16 qnum, hw_qnum; | 84 | u16 qnum; |
75 | __le16 fc; | 85 | __le16 fc; |
76 | u8 *tx_fhdr; | 86 | u8 *tx_fhdr; |
77 | u8 sta_idx; | 87 | u8 sta_idx; |
@@ -131,20 +141,23 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
131 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | 141 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); |
132 | 142 | ||
133 | qnum = skb_get_queue_mapping(skb); | 143 | qnum = skb_get_queue_mapping(skb); |
134 | hw_qnum = get_hw_qnum(qnum, priv->hwq_map); | ||
135 | 144 | ||
136 | switch (hw_qnum) { | 145 | switch (qnum) { |
137 | case 0: | 146 | case 0: |
138 | epid = priv->data_be_ep; | 147 | TX_QSTAT_INC(WME_AC_VO); |
148 | epid = priv->data_vo_ep; | ||
139 | break; | 149 | break; |
140 | case 2: | 150 | case 1: |
151 | TX_QSTAT_INC(WME_AC_VI); | ||
141 | epid = priv->data_vi_ep; | 152 | epid = priv->data_vi_ep; |
142 | break; | 153 | break; |
143 | case 3: | 154 | case 2: |
144 | epid = priv->data_vo_ep; | 155 | TX_QSTAT_INC(WME_AC_BE); |
156 | epid = priv->data_be_ep; | ||
145 | break; | 157 | break; |
146 | case 1: | 158 | case 3: |
147 | default: | 159 | default: |
160 | TX_QSTAT_INC(WME_AC_BK); | ||
148 | epid = priv->data_bk_ep; | 161 | epid = priv->data_bk_ep; |
149 | break; | 162 | break; |
150 | } | 163 | } |
@@ -174,6 +187,19 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
174 | return htc_send(priv->htc, skb, epid, &tx_ctl); | 187 | return htc_send(priv->htc, skb, epid, &tx_ctl); |
175 | } | 188 | } |
176 | 189 | ||
190 | static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | ||
191 | struct ath9k_htc_sta *ista, u8 tid) | ||
192 | { | ||
193 | bool ret = false; | ||
194 | |||
195 | spin_lock_bh(&priv->tx_lock); | ||
196 | if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) | ||
197 | ret = true; | ||
198 | spin_unlock_bh(&priv->tx_lock); | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
177 | void ath9k_tx_tasklet(unsigned long data) | 203 | void ath9k_tx_tasklet(unsigned long data) |
178 | { | 204 | { |
179 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 205 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
@@ -203,8 +229,7 @@ void ath9k_tx_tasklet(unsigned long data) | |||
203 | /* Check if we need to start aggregation */ | 229 | /* Check if we need to start aggregation */ |
204 | 230 | ||
205 | if (sta && conf_is_ht(&priv->hw->conf) && | 231 | if (sta && conf_is_ht(&priv->hw->conf) && |
206 | (priv->op_flags & OP_TXAGGR) | 232 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
207 | && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
208 | if (ieee80211_is_data_qos(fc)) { | 233 | if (ieee80211_is_data_qos(fc)) { |
209 | u8 *qc, tid; | 234 | u8 *qc, tid; |
210 | struct ath9k_htc_sta *ista; | 235 | struct ath9k_htc_sta *ista; |
@@ -213,10 +238,11 @@ void ath9k_tx_tasklet(unsigned long data) | |||
213 | tid = qc[0] & 0xf; | 238 | tid = qc[0] & 0xf; |
214 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | 239 | ista = (struct ath9k_htc_sta *)sta->drv_priv; |
215 | 240 | ||
216 | if ((tid < ATH9K_HTC_MAX_TID) && | 241 | if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { |
217 | ista->tid_state[tid] == AGGR_STOP) { | ||
218 | ieee80211_start_tx_ba_session(sta, tid); | 242 | ieee80211_start_tx_ba_session(sta, tid); |
243 | spin_lock_bh(&priv->tx_lock); | ||
219 | ista->tid_state[tid] = AGGR_PROGRESS; | 244 | ista->tid_state[tid] = AGGR_PROGRESS; |
245 | spin_unlock_bh(&priv->tx_lock); | ||
220 | } | 246 | } |
221 | } | 247 | } |
222 | } | 248 | } |
@@ -284,8 +310,7 @@ void ath9k_tx_cleanup(struct ath9k_htc_priv *priv) | |||
284 | 310 | ||
285 | } | 311 | } |
286 | 312 | ||
287 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | 313 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype) |
288 | enum ath9k_tx_queue_subtype subtype) | ||
289 | { | 314 | { |
290 | struct ath_hw *ah = priv->ah; | 315 | struct ath_hw *ah = priv->ah; |
291 | struct ath_common *common = ath9k_hw_common(ah); | 316 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -293,13 +318,7 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | |||
293 | int qnum; | 318 | int qnum; |
294 | 319 | ||
295 | memset(&qi, 0, sizeof(qi)); | 320 | memset(&qi, 0, sizeof(qi)); |
296 | 321 | ATH9K_HTC_INIT_TXQ(subtype); | |
297 | qi.tqi_subtype = subtype; | ||
298 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; | ||
299 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | ||
300 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; | ||
301 | qi.tqi_physCompBuf = 0; | ||
302 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE; | ||
303 | 322 | ||
304 | qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi); | 323 | qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi); |
305 | if (qnum == -1) | 324 | if (qnum == -1) |
@@ -317,6 +336,16 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | |||
317 | return true; | 336 | return true; |
318 | } | 337 | } |
319 | 338 | ||
339 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv) | ||
340 | { | ||
341 | struct ath9k_tx_queue_info qi; | ||
342 | |||
343 | memset(&qi, 0, sizeof(qi)); | ||
344 | ATH9K_HTC_INIT_TXQ(0); | ||
345 | |||
346 | return ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_CAB, &qi); | ||
347 | } | ||
348 | |||
320 | /******/ | 349 | /******/ |
321 | /* RX */ | 350 | /* RX */ |
322 | /******/ | 351 | /******/ |
@@ -387,9 +416,6 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | |||
387 | /* configure operational mode */ | 416 | /* configure operational mode */ |
388 | ath9k_hw_setopmode(ah); | 417 | ath9k_hw_setopmode(ah); |
389 | 418 | ||
390 | /* Handle any link-level address change. */ | ||
391 | ath9k_hw_setmac(ah, common->macaddr); | ||
392 | |||
393 | /* calculate and install multicast filter */ | 419 | /* calculate and install multicast filter */ |
394 | mfilt[0] = mfilt[1] = ~0; | 420 | mfilt[0] = mfilt[1] = ~0; |
395 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | 421 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); |
@@ -399,7 +425,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv) | |||
399 | { | 425 | { |
400 | ath9k_hw_rxena(priv->ah); | 426 | ath9k_hw_rxena(priv->ah); |
401 | ath9k_htc_opmode_init(priv); | 427 | ath9k_htc_opmode_init(priv); |
402 | ath9k_hw_startpcureceive(priv->ah); | 428 | ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING)); |
403 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; | 429 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; |
404 | } | 430 | } |
405 | 431 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 064397fd738e..705c0f342e1c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -89,7 +89,6 @@ static void htc_process_target_rdy(struct htc_target *target, | |||
89 | struct htc_endpoint *endpoint; | 89 | struct htc_endpoint *endpoint; |
90 | struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf; | 90 | struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf; |
91 | 91 | ||
92 | target->credits = be16_to_cpu(htc_ready_msg->credits); | ||
93 | target->credit_size = be16_to_cpu(htc_ready_msg->credit_size); | 92 | target->credit_size = be16_to_cpu(htc_ready_msg->credit_size); |
94 | 93 | ||
95 | endpoint = &target->endpoint[ENDPOINT0]; | 94 | endpoint = &target->endpoint[ENDPOINT0]; |
@@ -159,7 +158,7 @@ static int htc_config_pipe_credits(struct htc_target *target) | |||
159 | 158 | ||
160 | cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID); | 159 | cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID); |
161 | cp_msg->pipe_id = USB_WLAN_TX_PIPE; | 160 | cp_msg->pipe_id = USB_WLAN_TX_PIPE; |
162 | cp_msg->credits = 28; | 161 | cp_msg->credits = target->credits; |
163 | 162 | ||
164 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; | 163 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; |
165 | 164 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 624422a8169e..381da6c93b14 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -128,6 +128,17 @@ static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | |||
128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); | 128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline void ath9k_hw_procmibevent(struct ath_hw *ah) | ||
132 | { | ||
133 | ath9k_hw_ops(ah)->ani_proc_mib_event(ah); | ||
134 | } | ||
135 | |||
136 | static inline void ath9k_hw_ani_monitor(struct ath_hw *ah, | ||
137 | struct ath9k_channel *chan) | ||
138 | { | ||
139 | ath9k_hw_ops(ah)->ani_monitor(ah, chan); | ||
140 | } | ||
141 | |||
131 | /* Private hardware call ops */ | 142 | /* Private hardware call ops */ |
132 | 143 | ||
133 | /* PHY ops */ | 144 | /* PHY ops */ |
@@ -277,4 +288,9 @@ static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, | |||
277 | return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); | 288 | return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); |
278 | } | 289 | } |
279 | 290 | ||
291 | static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | ||
292 | { | ||
293 | ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning); | ||
294 | } | ||
295 | |||
280 | #endif /* ATH9K_HW_OPS_H */ | 296 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c33f17dbe6f1..1ed144038c36 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -23,11 +23,6 @@ | |||
23 | #include "rc.h" | 23 | #include "rc.h" |
24 | #include "ar9003_mac.h" | 24 | #include "ar9003_mac.h" |
25 | 25 | ||
26 | #define ATH9K_CLOCK_RATE_CCK 22 | ||
27 | #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 | ||
28 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 | ||
29 | #define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 | ||
30 | |||
31 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); | 26 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); |
32 | 27 | ||
33 | MODULE_AUTHOR("Atheros Communications"); | 28 | MODULE_AUTHOR("Atheros Communications"); |
@@ -80,6 +75,15 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
80 | ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); | 75 | ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); |
81 | } | 76 | } |
82 | 77 | ||
78 | static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
79 | { | ||
80 | /* You will not have this callback if using the old ANI */ | ||
81 | if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs) | ||
82 | return; | ||
83 | |||
84 | ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah); | ||
85 | } | ||
86 | |||
83 | /********************/ | 87 | /********************/ |
84 | /* Helper Functions */ | 88 | /* Helper Functions */ |
85 | /********************/ | 89 | /********************/ |
@@ -371,13 +375,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
371 | ah->config.ofdm_trig_high = 500; | 375 | ah->config.ofdm_trig_high = 500; |
372 | ah->config.cck_trig_high = 200; | 376 | ah->config.cck_trig_high = 200; |
373 | ah->config.cck_trig_low = 100; | 377 | ah->config.cck_trig_low = 100; |
374 | 378 | ah->config.enable_ani = true; | |
375 | /* | ||
376 | * For now ANI is disabled for AR9003, it is still | ||
377 | * being tested. | ||
378 | */ | ||
379 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
380 | ah->config.enable_ani = 1; | ||
381 | 379 | ||
382 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 380 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
383 | ah->config.spurchans[i][0] = AR_NO_SPUR; | 381 | ah->config.spurchans[i][0] = AR_NO_SPUR; |
@@ -390,12 +388,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
390 | ah->config.ht_enable = 0; | 388 | ah->config.ht_enable = 0; |
391 | 389 | ||
392 | ah->config.rx_intr_mitigation = true; | 390 | ah->config.rx_intr_mitigation = true; |
393 | 391 | ah->config.pcieSerDesWrite = true; | |
394 | /* | ||
395 | * Tx IQ Calibration (ah->config.tx_iq_calibration) is only | ||
396 | * used by AR9003, but it is showing reliability issues. | ||
397 | * It will take a while to fix so this is currently disabled. | ||
398 | */ | ||
399 | 392 | ||
400 | /* | 393 | /* |
401 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) | 394 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) |
@@ -433,7 +426,9 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
433 | ah->ah_flags = AH_USE_EEPROM; | 426 | ah->ah_flags = AH_USE_EEPROM; |
434 | 427 | ||
435 | ah->atim_window = 0; | 428 | ah->atim_window = 0; |
436 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; | 429 | ah->sta_id1_defaults = |
430 | AR_STA_ID1_CRPT_MIC_ENABLE | | ||
431 | AR_STA_ID1_MCAST_KSRCH; | ||
437 | ah->beacon_interval = 100; | 432 | ah->beacon_interval = 100; |
438 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | 433 | ah->enable_32kHz_clock = DONT_USE_32KHZ; |
439 | ah->slottime = (u32) -1; | 434 | ah->slottime = (u32) -1; |
@@ -571,28 +566,19 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
571 | ah->ani_function = ATH9K_ANI_ALL; | 566 | ah->ani_function = ATH9K_ANI_ALL; |
572 | if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) | 567 | if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) |
573 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | 568 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; |
569 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
570 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | ||
574 | 571 | ||
575 | ath9k_hw_init_mode_regs(ah); | 572 | ath9k_hw_init_mode_regs(ah); |
576 | 573 | ||
577 | /* | 574 | /* |
578 | * Configire PCIE after Ini init. SERDES values now come from ini file | 575 | * Read back AR_WA into a permanent copy and set bits 14 and 17. |
579 | * This enables PCIe low power mode. | 576 | * We need to do this to avoid RMW of this register. We cannot |
577 | * read the reg when chip is asleep. | ||
580 | */ | 578 | */ |
581 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 579 | ah->WARegVal = REG_READ(ah, AR_WA); |
582 | u32 regval; | 580 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | |
583 | unsigned int i; | 581 | AR_WA_ASPM_TIMER_BASED_DISABLE); |
584 | |||
585 | /* Set Bits 16 and 17 in the AR_WA register. */ | ||
586 | regval = REG_READ(ah, AR_WA); | ||
587 | regval |= 0x00030000; | ||
588 | REG_WRITE(ah, AR_WA, regval); | ||
589 | |||
590 | for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) { | ||
591 | REG_WRITE(ah, | ||
592 | INI_RA(&ah->iniPcieSerdesLowPower, i, 0), | ||
593 | INI_RA(&ah->iniPcieSerdesLowPower, i, 1)); | ||
594 | } | ||
595 | } | ||
596 | 582 | ||
597 | if (ah->is_pciexpress) | 583 | if (ah->is_pciexpress) |
598 | ath9k_hw_configpcipowersave(ah, 0, 0); | 584 | ath9k_hw_configpcipowersave(ah, 0, 0); |
@@ -627,6 +613,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
627 | ar9003_hw_set_nf_limits(ah); | 613 | ar9003_hw_set_nf_limits(ah); |
628 | 614 | ||
629 | ath9k_init_nfcal_hist_buffer(ah); | 615 | ath9k_init_nfcal_hist_buffer(ah); |
616 | ah->bb_watchdog_timeout_ms = 25; | ||
630 | 617 | ||
631 | common->state = ATH_HW_INITIALIZED; | 618 | common->state = ATH_HW_INITIALIZED; |
632 | 619 | ||
@@ -1012,6 +999,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1012 | 999 | ||
1013 | ENABLE_REGWRITE_BUFFER(ah); | 1000 | ENABLE_REGWRITE_BUFFER(ah); |
1014 | 1001 | ||
1002 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1003 | REG_WRITE(ah, AR_WA, ah->WARegVal); | ||
1004 | udelay(10); | ||
1005 | } | ||
1006 | |||
1015 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | | 1007 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | |
1016 | AR_RTC_FORCE_WAKE_ON_INT); | 1008 | AR_RTC_FORCE_WAKE_ON_INT); |
1017 | 1009 | ||
@@ -1066,6 +1058,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1066 | { | 1058 | { |
1067 | ENABLE_REGWRITE_BUFFER(ah); | 1059 | ENABLE_REGWRITE_BUFFER(ah); |
1068 | 1060 | ||
1061 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1062 | REG_WRITE(ah, AR_WA, ah->WARegVal); | ||
1063 | udelay(10); | ||
1064 | } | ||
1065 | |||
1069 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | | 1066 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | |
1070 | AR_RTC_FORCE_WAKE_ON_INT); | 1067 | AR_RTC_FORCE_WAKE_ON_INT); |
1071 | 1068 | ||
@@ -1073,6 +1070,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1073 | REG_WRITE(ah, AR_RC, AR_RC_AHB); | 1070 | REG_WRITE(ah, AR_RC, AR_RC_AHB); |
1074 | 1071 | ||
1075 | REG_WRITE(ah, AR_RTC_RESET, 0); | 1072 | REG_WRITE(ah, AR_RTC_RESET, 0); |
1073 | udelay(2); | ||
1076 | 1074 | ||
1077 | REGWRITE_BUFFER_FLUSH(ah); | 1075 | REGWRITE_BUFFER_FLUSH(ah); |
1078 | DISABLE_REGWRITE_BUFFER(ah); | 1076 | DISABLE_REGWRITE_BUFFER(ah); |
@@ -1102,6 +1100,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1102 | 1100 | ||
1103 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) | 1101 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) |
1104 | { | 1102 | { |
1103 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1104 | REG_WRITE(ah, AR_WA, ah->WARegVal); | ||
1105 | udelay(10); | ||
1106 | } | ||
1107 | |||
1105 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, | 1108 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, |
1106 | AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); | 1109 | AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); |
1107 | 1110 | ||
@@ -1303,6 +1306,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1303 | if (AR_SREV_9280_10_OR_LATER(ah)) | 1306 | if (AR_SREV_9280_10_OR_LATER(ah)) |
1304 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 1307 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
1305 | 1308 | ||
1309 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
1310 | ar9002_hw_enable_async_fifo(ah); | ||
1311 | |||
1306 | r = ath9k_hw_process_ini(ah, chan); | 1312 | r = ath9k_hw_process_ini(ah, chan); |
1307 | if (r) | 1313 | if (r) |
1308 | return r; | 1314 | return r; |
@@ -1367,6 +1373,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1367 | ath9k_hw_resettxqueue(ah, i); | 1373 | ath9k_hw_resettxqueue(ah, i); |
1368 | 1374 | ||
1369 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); | 1375 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); |
1376 | ath9k_hw_ani_cache_ini_regs(ah); | ||
1370 | ath9k_hw_init_qos(ah); | 1377 | ath9k_hw_init_qos(ah); |
1371 | 1378 | ||
1372 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 1379 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
@@ -1375,7 +1382,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1375 | ath9k_hw_init_global_settings(ah); | 1382 | ath9k_hw_init_global_settings(ah); |
1376 | 1383 | ||
1377 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | 1384 | if (!AR_SREV_9300_20_OR_LATER(ah)) { |
1378 | ar9002_hw_enable_async_fifo(ah); | 1385 | ar9002_hw_update_async_fifo(ah); |
1379 | ar9002_hw_enable_wep_aggregation(ah); | 1386 | ar9002_hw_enable_wep_aggregation(ah); |
1380 | } | 1387 | } |
1381 | 1388 | ||
@@ -1426,9 +1433,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1426 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); | 1433 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); |
1427 | } | 1434 | } |
1428 | } else { | 1435 | } else { |
1429 | /* Configure AR9271 target WLAN */ | 1436 | if (common->bus_ops->ath_bus_type == ATH_USB) { |
1430 | if (AR_SREV_9271(ah)) | 1437 | /* Configure AR9271 target WLAN */ |
1431 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | 1438 | if (AR_SREV_9271(ah)) |
1439 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1440 | else | ||
1441 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1442 | } | ||
1432 | #ifdef __BIG_ENDIAN | 1443 | #ifdef __BIG_ENDIAN |
1433 | else | 1444 | else |
1434 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | 1445 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); |
@@ -1441,6 +1452,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1441 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1452 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
1442 | ath9k_hw_loadnf(ah, curchan); | 1453 | ath9k_hw_loadnf(ah, curchan); |
1443 | ath9k_hw_start_nfcal(ah); | 1454 | ath9k_hw_start_nfcal(ah); |
1455 | ar9003_hw_bb_watchdog_config(ah); | ||
1444 | } | 1456 | } |
1445 | 1457 | ||
1446 | return 0; | 1458 | return 0; |
@@ -1489,6 +1501,7 @@ EXPORT_SYMBOL(ath9k_hw_keyreset); | |||
1489 | bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | 1501 | bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) |
1490 | { | 1502 | { |
1491 | u32 macHi, macLo; | 1503 | u32 macHi, macLo; |
1504 | u32 unicast_flag = AR_KEYTABLE_VALID; | ||
1492 | 1505 | ||
1493 | if (entry >= ah->caps.keycache_size) { | 1506 | if (entry >= ah->caps.keycache_size) { |
1494 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 1507 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
@@ -1497,6 +1510,16 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | |||
1497 | } | 1510 | } |
1498 | 1511 | ||
1499 | if (mac != NULL) { | 1512 | if (mac != NULL) { |
1513 | /* | ||
1514 | * AR_KEYTABLE_VALID indicates that the address is a unicast | ||
1515 | * address, which must match the transmitter address for | ||
1516 | * decrypting frames. | ||
1517 | * Not setting this bit allows the hardware to use the key | ||
1518 | * for multicast frame decryption. | ||
1519 | */ | ||
1520 | if (mac[0] & 0x01) | ||
1521 | unicast_flag = 0; | ||
1522 | |||
1500 | macHi = (mac[5] << 8) | mac[4]; | 1523 | macHi = (mac[5] << 8) | mac[4]; |
1501 | macLo = (mac[3] << 24) | | 1524 | macLo = (mac[3] << 24) | |
1502 | (mac[2] << 16) | | 1525 | (mac[2] << 16) | |
@@ -1509,7 +1532,7 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | |||
1509 | macLo = macHi = 0; | 1532 | macLo = macHi = 0; |
1510 | } | 1533 | } |
1511 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | 1534 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); |
1512 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); | 1535 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); |
1513 | 1536 | ||
1514 | return true; | 1537 | return true; |
1515 | } | 1538 | } |
@@ -1751,6 +1774,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) | |||
1751 | REG_CLR_BIT(ah, (AR_RTC_RESET), | 1774 | REG_CLR_BIT(ah, (AR_RTC_RESET), |
1752 | AR_RTC_RESET_EN); | 1775 | AR_RTC_RESET_EN); |
1753 | } | 1776 | } |
1777 | |||
1778 | /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ | ||
1779 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
1780 | REG_WRITE(ah, AR_WA, | ||
1781 | ah->WARegVal & ~AR_WA_D3_L1_DISABLE); | ||
1754 | } | 1782 | } |
1755 | 1783 | ||
1756 | /* | 1784 | /* |
@@ -1777,6 +1805,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) | |||
1777 | AR_RTC_FORCE_WAKE_EN); | 1805 | AR_RTC_FORCE_WAKE_EN); |
1778 | } | 1806 | } |
1779 | } | 1807 | } |
1808 | |||
1809 | /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */ | ||
1810 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
1811 | REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); | ||
1780 | } | 1812 | } |
1781 | 1813 | ||
1782 | static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | 1814 | static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) |
@@ -1784,6 +1816,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
1784 | u32 val; | 1816 | u32 val; |
1785 | int i; | 1817 | int i; |
1786 | 1818 | ||
1819 | /* Set Bits 14 and 17 of AR_WA before powering on the chip. */ | ||
1820 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1821 | REG_WRITE(ah, AR_WA, ah->WARegVal); | ||
1822 | udelay(10); | ||
1823 | } | ||
1824 | |||
1787 | if (setChip) { | 1825 | if (setChip) { |
1788 | if ((REG_READ(ah, AR_RTC_STATUS) & | 1826 | if ((REG_READ(ah, AR_RTC_STATUS) & |
1789 | AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { | 1827 | AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { |
@@ -2165,7 +2203,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2165 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; | 2203 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; |
2166 | } | 2204 | } |
2167 | #endif | 2205 | #endif |
2168 | if (AR_SREV_9271(ah)) | 2206 | if (AR_SREV_9271(ah) || AR_SREV_9300_20_OR_LATER(ah)) |
2169 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; | 2207 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; |
2170 | else | 2208 | else |
2171 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | 2209 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; |
@@ -2220,6 +2258,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2220 | pCap->rx_status_len = sizeof(struct ar9003_rxs); | 2258 | pCap->rx_status_len = sizeof(struct ar9003_rxs); |
2221 | pCap->tx_desc_len = sizeof(struct ar9003_txc); | 2259 | pCap->tx_desc_len = sizeof(struct ar9003_txc); |
2222 | pCap->txs_len = sizeof(struct ar9003_txs); | 2260 | pCap->txs_len = sizeof(struct ar9003_txs); |
2261 | if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | ||
2262 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | ||
2223 | } else { | 2263 | } else { |
2224 | pCap->tx_desc_len = sizeof(struct ath_desc); | 2264 | pCap->tx_desc_len = sizeof(struct ath_desc); |
2225 | if (AR_SREV_9280_20(ah) && | 2265 | if (AR_SREV_9280_20(ah) && |
@@ -2232,100 +2272,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2232 | if (AR_SREV_9300_20_OR_LATER(ah)) | 2272 | if (AR_SREV_9300_20_OR_LATER(ah)) |
2233 | pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; | 2273 | pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; |
2234 | 2274 | ||
2235 | return 0; | 2275 | if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) |
2236 | } | 2276 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; |
2237 | 2277 | ||
2238 | bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | 2278 | return 0; |
2239 | u32 capability, u32 *result) | ||
2240 | { | ||
2241 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
2242 | switch (type) { | ||
2243 | case ATH9K_CAP_CIPHER: | ||
2244 | switch (capability) { | ||
2245 | case ATH9K_CIPHER_AES_CCM: | ||
2246 | case ATH9K_CIPHER_AES_OCB: | ||
2247 | case ATH9K_CIPHER_TKIP: | ||
2248 | case ATH9K_CIPHER_WEP: | ||
2249 | case ATH9K_CIPHER_MIC: | ||
2250 | case ATH9K_CIPHER_CLR: | ||
2251 | return true; | ||
2252 | default: | ||
2253 | return false; | ||
2254 | } | ||
2255 | case ATH9K_CAP_TKIP_MIC: | ||
2256 | switch (capability) { | ||
2257 | case 0: | ||
2258 | return true; | ||
2259 | case 1: | ||
2260 | return (ah->sta_id1_defaults & | ||
2261 | AR_STA_ID1_CRPT_MIC_ENABLE) ? true : | ||
2262 | false; | ||
2263 | } | ||
2264 | case ATH9K_CAP_TKIP_SPLIT: | ||
2265 | return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? | ||
2266 | false : true; | ||
2267 | case ATH9K_CAP_MCAST_KEYSRCH: | ||
2268 | switch (capability) { | ||
2269 | case 0: | ||
2270 | return true; | ||
2271 | case 1: | ||
2272 | if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { | ||
2273 | return false; | ||
2274 | } else { | ||
2275 | return (ah->sta_id1_defaults & | ||
2276 | AR_STA_ID1_MCAST_KSRCH) ? true : | ||
2277 | false; | ||
2278 | } | ||
2279 | } | ||
2280 | return false; | ||
2281 | case ATH9K_CAP_TXPOW: | ||
2282 | switch (capability) { | ||
2283 | case 0: | ||
2284 | return 0; | ||
2285 | case 1: | ||
2286 | *result = regulatory->power_limit; | ||
2287 | return 0; | ||
2288 | case 2: | ||
2289 | *result = regulatory->max_power_level; | ||
2290 | return 0; | ||
2291 | case 3: | ||
2292 | *result = regulatory->tp_scale; | ||
2293 | return 0; | ||
2294 | } | ||
2295 | return false; | ||
2296 | case ATH9K_CAP_DS: | ||
2297 | return (AR_SREV_9280_20_OR_LATER(ah) && | ||
2298 | (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) | ||
2299 | ? false : true; | ||
2300 | default: | ||
2301 | return false; | ||
2302 | } | ||
2303 | } | ||
2304 | EXPORT_SYMBOL(ath9k_hw_getcapability); | ||
2305 | |||
2306 | bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
2307 | u32 capability, u32 setting, int *status) | ||
2308 | { | ||
2309 | switch (type) { | ||
2310 | case ATH9K_CAP_TKIP_MIC: | ||
2311 | if (setting) | ||
2312 | ah->sta_id1_defaults |= | ||
2313 | AR_STA_ID1_CRPT_MIC_ENABLE; | ||
2314 | else | ||
2315 | ah->sta_id1_defaults &= | ||
2316 | ~AR_STA_ID1_CRPT_MIC_ENABLE; | ||
2317 | return true; | ||
2318 | case ATH9K_CAP_MCAST_KEYSRCH: | ||
2319 | if (setting) | ||
2320 | ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; | ||
2321 | else | ||
2322 | ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; | ||
2323 | return true; | ||
2324 | default: | ||
2325 | return false; | ||
2326 | } | ||
2327 | } | 2279 | } |
2328 | EXPORT_SYMBOL(ath9k_hw_setcapability); | ||
2329 | 2280 | ||
2330 | /****************************/ | 2281 | /****************************/ |
2331 | /* GPIO / RFKILL / Antennae */ | 2282 | /* GPIO / RFKILL / Antennae */ |
@@ -2520,12 +2471,6 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | |||
2520 | } | 2471 | } |
2521 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); | 2472 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); |
2522 | 2473 | ||
2523 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) | ||
2524 | { | ||
2525 | memcpy(ath9k_hw_common(ah)->macaddr, mac, ETH_ALEN); | ||
2526 | } | ||
2527 | EXPORT_SYMBOL(ath9k_hw_setmac); | ||
2528 | |||
2529 | void ath9k_hw_setopmode(struct ath_hw *ah) | 2474 | void ath9k_hw_setopmode(struct ath_hw *ah) |
2530 | { | 2475 | { |
2531 | ath9k_hw_set_operating_mode(ah, ah->opmode); | 2476 | ath9k_hw_set_operating_mode(ah, ah->opmode); |
@@ -2598,21 +2543,6 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) | |||
2598 | } | 2543 | } |
2599 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); | 2544 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); |
2600 | 2545 | ||
2601 | /* | ||
2602 | * Extend 15-bit time stamp from rx descriptor to | ||
2603 | * a full 64-bit TSF using the current h/w TSF. | ||
2604 | */ | ||
2605 | u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) | ||
2606 | { | ||
2607 | u64 tsf; | ||
2608 | |||
2609 | tsf = ath9k_hw_gettsf64(ah); | ||
2610 | if ((tsf & 0x7fff) < rstamp) | ||
2611 | tsf -= 0x8000; | ||
2612 | return (tsf & ~0x7fff) | rstamp; | ||
2613 | } | ||
2614 | EXPORT_SYMBOL(ath9k_hw_extend_tsf); | ||
2615 | |||
2616 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) | 2546 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) |
2617 | { | 2547 | { |
2618 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 2548 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 77245dff5993..e9578a4c912f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -158,6 +158,9 @@ | |||
158 | #define ATH9K_HW_RX_HP_QDEPTH 16 | 158 | #define ATH9K_HW_RX_HP_QDEPTH 16 |
159 | #define ATH9K_HW_RX_LP_QDEPTH 128 | 159 | #define ATH9K_HW_RX_LP_QDEPTH 128 |
160 | 160 | ||
161 | #define PAPRD_GAIN_TABLE_ENTRIES 32 | ||
162 | #define PAPRD_TABLE_SZ 24 | ||
163 | |||
161 | enum ath_ini_subsys { | 164 | enum ath_ini_subsys { |
162 | ATH_INI_PRE = 0, | 165 | ATH_INI_PRE = 0, |
163 | ATH_INI_CORE, | 166 | ATH_INI_CORE, |
@@ -199,15 +202,8 @@ enum ath9k_hw_caps { | |||
199 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), | 202 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), |
200 | ATH9K_HW_CAP_LDPC = BIT(19), | 203 | ATH9K_HW_CAP_LDPC = BIT(19), |
201 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), | 204 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), |
202 | }; | 205 | ATH9K_HW_CAP_SGI_20 = BIT(21), |
203 | 206 | ATH9K_HW_CAP_PAPRD = BIT(22), | |
204 | enum ath9k_capability_type { | ||
205 | ATH9K_CAP_CIPHER = 0, | ||
206 | ATH9K_CAP_TKIP_MIC, | ||
207 | ATH9K_CAP_TKIP_SPLIT, | ||
208 | ATH9K_CAP_TXPOW, | ||
209 | ATH9K_CAP_MCAST_KEYSRCH, | ||
210 | ATH9K_CAP_DS | ||
211 | }; | 207 | }; |
212 | 208 | ||
213 | struct ath9k_hw_capabilities { | 209 | struct ath9k_hw_capabilities { |
@@ -237,8 +233,9 @@ struct ath9k_ops_config { | |||
237 | int sw_beacon_response_time; | 233 | int sw_beacon_response_time; |
238 | int additional_swba_backoff; | 234 | int additional_swba_backoff; |
239 | int ack_6mb; | 235 | int ack_6mb; |
240 | int cwm_ignore_extcca; | 236 | u32 cwm_ignore_extcca; |
241 | u8 pcie_powersave_enable; | 237 | u8 pcie_powersave_enable; |
238 | bool pcieSerDesWrite; | ||
242 | u8 pcie_clock_req; | 239 | u8 pcie_clock_req; |
243 | u32 pcie_waen; | 240 | u32 pcie_waen; |
244 | u8 analog_shiftreg; | 241 | u8 analog_shiftreg; |
@@ -262,10 +259,10 @@ struct ath9k_ops_config { | |||
262 | #define AR_BASE_FREQ_5GHZ 4900 | 259 | #define AR_BASE_FREQ_5GHZ 4900 |
263 | #define AR_SPUR_FEEQ_BOUND_HT40 19 | 260 | #define AR_SPUR_FEEQ_BOUND_HT40 19 |
264 | #define AR_SPUR_FEEQ_BOUND_HT20 10 | 261 | #define AR_SPUR_FEEQ_BOUND_HT20 10 |
265 | bool tx_iq_calibration; /* Only available for >= AR9003 */ | ||
266 | int spurmode; | 262 | int spurmode; |
267 | u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; | 263 | u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; |
268 | u8 max_txtrig_level; | 264 | u8 max_txtrig_level; |
265 | u16 ani_poll_interval; /* ANI poll interval in ms */ | ||
269 | }; | 266 | }; |
270 | 267 | ||
271 | enum ath9k_int { | 268 | enum ath9k_int { |
@@ -279,6 +276,7 @@ enum ath9k_int { | |||
279 | ATH9K_INT_TX = 0x00000040, | 276 | ATH9K_INT_TX = 0x00000040, |
280 | ATH9K_INT_TXDESC = 0x00000080, | 277 | ATH9K_INT_TXDESC = 0x00000080, |
281 | ATH9K_INT_TIM_TIMER = 0x00000100, | 278 | ATH9K_INT_TIM_TIMER = 0x00000100, |
279 | ATH9K_INT_BB_WATCHDOG = 0x00000400, | ||
282 | ATH9K_INT_TXURN = 0x00000800, | 280 | ATH9K_INT_TXURN = 0x00000800, |
283 | ATH9K_INT_MIB = 0x00001000, | 281 | ATH9K_INT_MIB = 0x00001000, |
284 | ATH9K_INT_RXPHY = 0x00004000, | 282 | ATH9K_INT_RXPHY = 0x00004000, |
@@ -358,6 +356,9 @@ struct ath9k_channel { | |||
358 | int8_t iCoff; | 356 | int8_t iCoff; |
359 | int8_t qCoff; | 357 | int8_t qCoff; |
360 | int16_t rawNoiseFloor; | 358 | int16_t rawNoiseFloor; |
359 | bool paprd_done; | ||
360 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | ||
361 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | ||
361 | }; | 362 | }; |
362 | 363 | ||
363 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 364 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -459,7 +460,7 @@ struct ath9k_hw_version { | |||
459 | #define AR_GENTMR_BIT(_index) (1 << (_index)) | 460 | #define AR_GENTMR_BIT(_index) (1 << (_index)) |
460 | 461 | ||
461 | /* | 462 | /* |
462 | * Using de Bruijin sequence to to look up 1's index in a 32 bit number | 463 | * Using de Bruijin sequence to look up 1's index in a 32 bit number |
463 | * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 | 464 | * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 |
464 | */ | 465 | */ |
465 | #define debruijn32 0x077CB531U | 466 | #define debruijn32 0x077CB531U |
@@ -510,6 +511,17 @@ struct ath_gen_timer_table { | |||
510 | * @setup_calibration: set up calibration | 511 | * @setup_calibration: set up calibration |
511 | * @iscal_supported: used to query if a type of calibration is supported | 512 | * @iscal_supported: used to query if a type of calibration is supported |
512 | * @loadnf: load noise floor read from each chain on the CCA registers | 513 | * @loadnf: load noise floor read from each chain on the CCA registers |
514 | * | ||
515 | * @ani_reset: reset ANI parameters to default values | ||
516 | * @ani_lower_immunity: lower the noise immunity level. The level controls | ||
517 | * the power-based packet detection on hardware. If a power jump is | ||
518 | * detected the adapter takes it as an indication that a packet has | ||
519 | * arrived. The level ranges from 0-5. Each level corresponds to a | ||
520 | * few dB more of noise immunity. If you have a strong time-varying | ||
521 | * interference that is causing false detections (OFDM timing errors or | ||
522 | * CCK timing errors) the level can be increased. | ||
523 | * @ani_cache_ini_regs: cache the values for ANI from the initial | ||
524 | * register settings through the register initialization. | ||
513 | */ | 525 | */ |
514 | struct ath_hw_private_ops { | 526 | struct ath_hw_private_ops { |
515 | /* Calibration ops */ | 527 | /* Calibration ops */ |
@@ -553,6 +565,11 @@ struct ath_hw_private_ops { | |||
553 | int param); | 565 | int param); |
554 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); | 566 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); |
555 | void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); | 567 | void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); |
568 | |||
569 | /* ANI */ | ||
570 | void (*ani_reset)(struct ath_hw *ah, bool is_scanning); | ||
571 | void (*ani_lower_immunity)(struct ath_hw *ah); | ||
572 | void (*ani_cache_ini_regs)(struct ath_hw *ah); | ||
556 | }; | 573 | }; |
557 | 574 | ||
558 | /** | 575 | /** |
@@ -563,6 +580,11 @@ struct ath_hw_private_ops { | |||
563 | * | 580 | * |
564 | * @config_pci_powersave: | 581 | * @config_pci_powersave: |
565 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC | 582 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC |
583 | * | ||
584 | * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI | ||
585 | * thresholds being reached or having overflowed. | ||
586 | * @ani_monitor: called periodically by the core driver to collect | ||
587 | * MIB stats and adjust ANI if specific thresholds have been reached. | ||
566 | */ | 588 | */ |
567 | struct ath_hw_ops { | 589 | struct ath_hw_ops { |
568 | void (*config_pci_powersave)(struct ath_hw *ah, | 590 | void (*config_pci_powersave)(struct ath_hw *ah, |
@@ -603,6 +625,9 @@ struct ath_hw_ops { | |||
603 | u32 burstDuration); | 625 | u32 burstDuration); |
604 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, | 626 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, |
605 | u32 vmf); | 627 | u32 vmf); |
628 | |||
629 | void (*ani_proc_mib_event)(struct ath_hw *ah); | ||
630 | void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan); | ||
606 | }; | 631 | }; |
607 | 632 | ||
608 | struct ath_hw { | 633 | struct ath_hw { |
@@ -789,6 +814,18 @@ struct ath_hw { | |||
789 | u32 ts_paddr_end; | 814 | u32 ts_paddr_end; |
790 | u16 ts_tail; | 815 | u16 ts_tail; |
791 | u8 ts_size; | 816 | u8 ts_size; |
817 | |||
818 | u32 bb_watchdog_last_status; | ||
819 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ | ||
820 | |||
821 | u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; | ||
822 | u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; | ||
823 | /* | ||
824 | * Store the permanent value of Reg 0x4004in WARegVal | ||
825 | * so we dont have to R/M/W. We should not be reading | ||
826 | * this register when in sleep states. | ||
827 | */ | ||
828 | u32 WARegVal; | ||
792 | }; | 829 | }; |
793 | 830 | ||
794 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | 831 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) |
@@ -818,10 +855,6 @@ int ath9k_hw_init(struct ath_hw *ah); | |||
818 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 855 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
819 | bool bChannelChange); | 856 | bool bChannelChange); |
820 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 857 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
821 | bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
822 | u32 capability, u32 *result); | ||
823 | bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
824 | u32 capability, u32 setting, int *status); | ||
825 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 858 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
826 | 859 | ||
827 | /* Key Cache Management */ | 860 | /* Key Cache Management */ |
@@ -856,7 +889,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); | |||
856 | bool ath9k_hw_phy_disable(struct ath_hw *ah); | 889 | bool ath9k_hw_phy_disable(struct ath_hw *ah); |
857 | bool ath9k_hw_disable(struct ath_hw *ah); | 890 | bool ath9k_hw_disable(struct ath_hw *ah); |
858 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); | 891 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); |
859 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); | ||
860 | void ath9k_hw_setopmode(struct ath_hw *ah); | 892 | void ath9k_hw_setopmode(struct ath_hw *ah); |
861 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); | 893 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
862 | void ath9k_hw_setbssidmask(struct ath_hw *ah); | 894 | void ath9k_hw_setbssidmask(struct ath_hw *ah); |
@@ -865,7 +897,6 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah); | |||
865 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | 897 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); |
866 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 898 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
867 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 899 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
868 | u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); | ||
869 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 900 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
870 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 901 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); |
871 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 902 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
@@ -907,13 +938,26 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, | |||
907 | void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); | 938 | void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); |
908 | int ar9002_hw_rf_claim(struct ath_hw *ah); | 939 | int ar9002_hw_rf_claim(struct ath_hw *ah); |
909 | void ar9002_hw_enable_async_fifo(struct ath_hw *ah); | 940 | void ar9002_hw_enable_async_fifo(struct ath_hw *ah); |
941 | void ar9002_hw_update_async_fifo(struct ath_hw *ah); | ||
910 | void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); | 942 | void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); |
911 | 943 | ||
912 | /* | 944 | /* |
913 | * Code specifric to AR9003, we stuff these here to avoid callbacks | 945 | * Code specific to AR9003, we stuff these here to avoid callbacks |
914 | * for older families | 946 | * for older families |
915 | */ | 947 | */ |
916 | void ar9003_hw_set_nf_limits(struct ath_hw *ah); | 948 | void ar9003_hw_set_nf_limits(struct ath_hw *ah); |
949 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); | ||
950 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | ||
951 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | ||
952 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); | ||
953 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | ||
954 | struct ath9k_channel *chan, int chain); | ||
955 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | ||
956 | int chain); | ||
957 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | ||
958 | int ar9003_paprd_init_table(struct ath_hw *ah); | ||
959 | bool ar9003_paprd_is_done(struct ath_hw *ah); | ||
960 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); | ||
917 | 961 | ||
918 | /* Hardware family op attach helpers */ | 962 | /* Hardware family op attach helpers */ |
919 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 963 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); |
@@ -926,8 +970,24 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah); | |||
926 | void ar9002_hw_attach_ops(struct ath_hw *ah); | 970 | void ar9002_hw_attach_ops(struct ath_hw *ah); |
927 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 971 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
928 | 972 | ||
973 | /* | ||
974 | * ANI work can be shared between all families but a next | ||
975 | * generation implementation of ANI will be used only for AR9003 only | ||
976 | * for now as the other families still need to be tested with the same | ||
977 | * next generation ANI. Feel free to start testing it though for the | ||
978 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. | ||
979 | */ | ||
980 | extern int modparam_force_new_ani; | ||
981 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); | ||
982 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah); | ||
983 | |||
929 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 | 984 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 |
930 | #define ATH_PCIE_CAP_LINK_L0S 1 | 985 | #define ATH_PCIE_CAP_LINK_L0S 1 |
931 | #define ATH_PCIE_CAP_LINK_L1 2 | 986 | #define ATH_PCIE_CAP_LINK_L1 2 |
932 | 987 | ||
988 | #define ATH9K_CLOCK_RATE_CCK 22 | ||
989 | #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 | ||
990 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 | ||
991 | #define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 | ||
992 | |||
933 | #endif | 993 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d457cb3bd772..8700e3dc53cf 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -33,6 +33,10 @@ int modparam_nohwcrypt; | |||
33 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | 33 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); |
34 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | 34 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); |
35 | 35 | ||
36 | int led_blink = 1; | ||
37 | module_param_named(blink, led_blink, int, 0444); | ||
38 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | ||
39 | |||
36 | /* We use the hw_value as an index into our private channel structure */ | 40 | /* We use the hw_value as an index into our private channel structure */ |
37 | 41 | ||
38 | #define CHAN2G(_freq, _idx) { \ | 42 | #define CHAN2G(_freq, _idx) { \ |
@@ -175,18 +179,6 @@ static const struct ath_ops ath9k_common_ops = { | |||
175 | .write = ath9k_iowrite32, | 179 | .write = ath9k_iowrite32, |
176 | }; | 180 | }; |
177 | 181 | ||
178 | static int count_streams(unsigned int chainmask, int max) | ||
179 | { | ||
180 | int streams = 0; | ||
181 | |||
182 | do { | ||
183 | if (++streams == max) | ||
184 | break; | ||
185 | } while ((chainmask = chainmask & (chainmask - 1))); | ||
186 | |||
187 | return streams; | ||
188 | } | ||
189 | |||
190 | /**************************/ | 182 | /**************************/ |
191 | /* Initialization */ | 183 | /* Initialization */ |
192 | /**************************/ | 184 | /**************************/ |
@@ -208,6 +200,9 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
208 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) | 200 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) |
209 | ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; | 201 | ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; |
210 | 202 | ||
203 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) | ||
204 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
205 | |||
211 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | 206 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
212 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | 207 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; |
213 | 208 | ||
@@ -224,8 +219,8 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
224 | 219 | ||
225 | /* set up supported mcs set */ | 220 | /* set up supported mcs set */ |
226 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | 221 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |
227 | tx_streams = count_streams(common->tx_chainmask, max_streams); | 222 | tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); |
228 | rx_streams = count_streams(common->rx_chainmask, max_streams); | 223 | rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); |
229 | 224 | ||
230 | ath_print(common, ATH_DBG_CONFIG, | 225 | ath_print(common, ATH_DBG_CONFIG, |
231 | "TX streams %d, RX streams: %d\n", | 226 | "TX streams %d, RX streams: %d\n", |
@@ -388,36 +383,14 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
388 | for (i = 0; i < common->keymax; i++) | 383 | for (i = 0; i < common->keymax; i++) |
389 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); | 384 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); |
390 | 385 | ||
391 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
392 | ATH9K_CIPHER_TKIP, NULL)) { | ||
393 | /* | ||
394 | * Whether we should enable h/w TKIP MIC. | ||
395 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
396 | * report WMM capable, so it's always safe to turn on | ||
397 | * TKIP MIC in this case. | ||
398 | */ | ||
399 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
400 | } | ||
401 | |||
402 | /* | 386 | /* |
403 | * Check whether the separate key cache entries | 387 | * Check whether the separate key cache entries |
404 | * are required to handle both tx+rx MIC keys. | 388 | * are required to handle both tx+rx MIC keys. |
405 | * With split mic keys the number of stations is limited | 389 | * With split mic keys the number of stations is limited |
406 | * to 27 otherwise 59. | 390 | * to 27 otherwise 59. |
407 | */ | 391 | */ |
408 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | 392 | if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)) |
409 | ATH9K_CIPHER_TKIP, NULL) | ||
410 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
411 | ATH9K_CIPHER_MIC, NULL) | ||
412 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT, | ||
413 | 0, NULL)) | ||
414 | common->splitmic = 1; | 393 | common->splitmic = 1; |
415 | |||
416 | /* turn on mcast key search if possible */ | ||
417 | if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
418 | (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
419 | 1, 1, NULL); | ||
420 | |||
421 | } | 394 | } |
422 | 395 | ||
423 | static int ath9k_init_btcoex(struct ath_softc *sc) | 396 | static int ath9k_init_btcoex(struct ath_softc *sc) |
@@ -435,7 +408,7 @@ static int ath9k_init_btcoex(struct ath_softc *sc) | |||
435 | r = ath_init_btcoex_timer(sc); | 408 | r = ath_init_btcoex_timer(sc); |
436 | if (r) | 409 | if (r) |
437 | return -1; | 410 | return -1; |
438 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | 411 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
439 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); | 412 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); |
440 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | 413 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; |
441 | break; | 414 | break; |
@@ -472,23 +445,23 @@ static int ath9k_init_queues(struct ath_softc *sc) | |||
472 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | 445 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; |
473 | ath_cabq_update(sc); | 446 | ath_cabq_update(sc); |
474 | 447 | ||
475 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | 448 | if (!ath_tx_setup(sc, WME_AC_BK)) { |
476 | ath_print(common, ATH_DBG_FATAL, | 449 | ath_print(common, ATH_DBG_FATAL, |
477 | "Unable to setup xmit queue for BK traffic\n"); | 450 | "Unable to setup xmit queue for BK traffic\n"); |
478 | goto err; | 451 | goto err; |
479 | } | 452 | } |
480 | 453 | ||
481 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | 454 | if (!ath_tx_setup(sc, WME_AC_BE)) { |
482 | ath_print(common, ATH_DBG_FATAL, | 455 | ath_print(common, ATH_DBG_FATAL, |
483 | "Unable to setup xmit queue for BE traffic\n"); | 456 | "Unable to setup xmit queue for BE traffic\n"); |
484 | goto err; | 457 | goto err; |
485 | } | 458 | } |
486 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | 459 | if (!ath_tx_setup(sc, WME_AC_VI)) { |
487 | ath_print(common, ATH_DBG_FATAL, | 460 | ath_print(common, ATH_DBG_FATAL, |
488 | "Unable to setup xmit queue for VI traffic\n"); | 461 | "Unable to setup xmit queue for VI traffic\n"); |
489 | goto err; | 462 | goto err; |
490 | } | 463 | } |
491 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | 464 | if (!ath_tx_setup(sc, WME_AC_VO)) { |
492 | ath_print(common, ATH_DBG_FATAL, | 465 | ath_print(common, ATH_DBG_FATAL, |
493 | "Unable to setup xmit queue for VO traffic\n"); | 466 | "Unable to setup xmit queue for VO traffic\n"); |
494 | goto err; | 467 | goto err; |
@@ -745,6 +718,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
745 | goto error_world; | 718 | goto error_world; |
746 | } | 719 | } |
747 | 720 | ||
721 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | ||
748 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | 722 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); |
749 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | 723 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); |
750 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | 724 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0e425cb4bbb1..e955bb9d98cb 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | ||
18 | 19 | ||
19 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 20 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
20 | struct ath9k_tx_queue_info *qi) | 21 | struct ath9k_tx_queue_info *qi) |
@@ -554,8 +555,13 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
554 | REGWRITE_BUFFER_FLUSH(ah); | 555 | REGWRITE_BUFFER_FLUSH(ah); |
555 | DISABLE_REGWRITE_BUFFER(ah); | 556 | DISABLE_REGWRITE_BUFFER(ah); |
556 | 557 | ||
557 | /* cwmin and cwmax should be 0 for beacon queue */ | 558 | /* |
558 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 559 | * cwmin and cwmax should be 0 for beacon queue |
560 | * but not for IBSS as we would create an imbalance | ||
561 | * on beaconing fairness for participating nodes. | ||
562 | */ | ||
563 | if (AR_SREV_9300_20_OR_LATER(ah) && | ||
564 | ah->opmode != NL80211_IFTYPE_ADHOC) { | ||
559 | REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) | 565 | REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) |
560 | | SM(0, AR_D_LCL_IFS_CWMAX) | 566 | | SM(0, AR_D_LCL_IFS_CWMAX) |
561 | | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); | 567 | | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); |
@@ -756,11 +762,11 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) | |||
756 | } | 762 | } |
757 | EXPORT_SYMBOL(ath9k_hw_putrxbuf); | 763 | EXPORT_SYMBOL(ath9k_hw_putrxbuf); |
758 | 764 | ||
759 | void ath9k_hw_startpcureceive(struct ath_hw *ah) | 765 | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning) |
760 | { | 766 | { |
761 | ath9k_enable_mib_counters(ah); | 767 | ath9k_enable_mib_counters(ah); |
762 | 768 | ||
763 | ath9k_ani_reset(ah); | 769 | ath9k_ani_reset(ah, is_scanning); |
764 | 770 | ||
765 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 771 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
766 | } | 772 | } |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 00f3e0c7528a..7559fb2b28a5 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -577,13 +577,8 @@ enum ath9k_tx_queue { | |||
577 | 577 | ||
578 | #define ATH9K_NUM_TX_QUEUES 10 | 578 | #define ATH9K_NUM_TX_QUEUES 10 |
579 | 579 | ||
580 | enum ath9k_tx_queue_subtype { | 580 | /* Used as a queue subtype instead of a WMM AC */ |
581 | ATH9K_WME_AC_BK = 0, | 581 | #define ATH9K_WME_UPSD 4 |
582 | ATH9K_WME_AC_BE, | ||
583 | ATH9K_WME_AC_VI, | ||
584 | ATH9K_WME_AC_VO, | ||
585 | ATH9K_WME_UPSD | ||
586 | }; | ||
587 | 582 | ||
588 | enum ath9k_tx_queue_flags { | 583 | enum ath9k_tx_queue_flags { |
589 | TXQ_FLAG_TXOKINT_ENABLE = 0x0001, | 584 | TXQ_FLAG_TXOKINT_ENABLE = 0x0001, |
@@ -617,7 +612,7 @@ enum ath9k_pkt_type { | |||
617 | struct ath9k_tx_queue_info { | 612 | struct ath9k_tx_queue_info { |
618 | u32 tqi_ver; | 613 | u32 tqi_ver; |
619 | enum ath9k_tx_queue tqi_type; | 614 | enum ath9k_tx_queue tqi_type; |
620 | enum ath9k_tx_queue_subtype tqi_subtype; | 615 | int tqi_subtype; |
621 | enum ath9k_tx_queue_flags tqi_qflags; | 616 | enum ath9k_tx_queue_flags tqi_qflags; |
622 | u32 tqi_priority; | 617 | u32 tqi_priority; |
623 | u32 tqi_aifs; | 618 | u32 tqi_aifs; |
@@ -715,7 +710,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
715 | u32 size, u32 flags); | 710 | u32 size, u32 flags); |
716 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); | 711 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); |
717 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); | 712 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); |
718 | void ath9k_hw_startpcureceive(struct ath_hw *ah); | 713 | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); |
719 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); | 714 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); |
720 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); | 715 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); |
721 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); | 716 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1e2a68ea9355..efbf53534ade 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -51,13 +51,11 @@ static void ath_cache_conf_rate(struct ath_softc *sc, | |||
51 | static void ath_update_txpow(struct ath_softc *sc) | 51 | static void ath_update_txpow(struct ath_softc *sc) |
52 | { | 52 | { |
53 | struct ath_hw *ah = sc->sc_ah; | 53 | struct ath_hw *ah = sc->sc_ah; |
54 | u32 txpow; | ||
55 | 54 | ||
56 | if (sc->curtxpow != sc->config.txpowlimit) { | 55 | if (sc->curtxpow != sc->config.txpowlimit) { |
57 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); | 56 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); |
58 | /* read back in case value is clamped */ | 57 | /* read back in case value is clamped */ |
59 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | 58 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
60 | sc->curtxpow = txpow; | ||
61 | } | 59 | } |
62 | } | 60 | } |
63 | 61 | ||
@@ -232,6 +230,114 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
232 | return r; | 230 | return r; |
233 | } | 231 | } |
234 | 232 | ||
233 | static void ath_paprd_activate(struct ath_softc *sc) | ||
234 | { | ||
235 | struct ath_hw *ah = sc->sc_ah; | ||
236 | int chain; | ||
237 | |||
238 | if (!ah->curchan->paprd_done) | ||
239 | return; | ||
240 | |||
241 | ath9k_ps_wakeup(sc); | ||
242 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
243 | if (!(ah->caps.tx_chainmask & BIT(chain))) | ||
244 | continue; | ||
245 | |||
246 | ar9003_paprd_populate_single_table(ah, ah->curchan, chain); | ||
247 | } | ||
248 | |||
249 | ar9003_paprd_enable(ah, true); | ||
250 | ath9k_ps_restore(sc); | ||
251 | } | ||
252 | |||
253 | void ath_paprd_calibrate(struct work_struct *work) | ||
254 | { | ||
255 | struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); | ||
256 | struct ieee80211_hw *hw = sc->hw; | ||
257 | struct ath_hw *ah = sc->sc_ah; | ||
258 | struct ieee80211_hdr *hdr; | ||
259 | struct sk_buff *skb = NULL; | ||
260 | struct ieee80211_tx_info *tx_info; | ||
261 | int band = hw->conf.channel->band; | ||
262 | struct ieee80211_supported_band *sband = &sc->sbands[band]; | ||
263 | struct ath_tx_control txctl; | ||
264 | int qnum, ftype; | ||
265 | int chain_ok = 0; | ||
266 | int chain; | ||
267 | int len = 1800; | ||
268 | int time_left; | ||
269 | int i; | ||
270 | |||
271 | skb = alloc_skb(len, GFP_KERNEL); | ||
272 | if (!skb) | ||
273 | return; | ||
274 | |||
275 | tx_info = IEEE80211_SKB_CB(skb); | ||
276 | |||
277 | skb_put(skb, len); | ||
278 | memset(skb->data, 0, len); | ||
279 | hdr = (struct ieee80211_hdr *)skb->data; | ||
280 | ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; | ||
281 | hdr->frame_control = cpu_to_le16(ftype); | ||
282 | hdr->duration_id = 10; | ||
283 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
284 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
285 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
286 | |||
287 | memset(&txctl, 0, sizeof(txctl)); | ||
288 | qnum = sc->tx.hwq_map[WME_AC_BE]; | ||
289 | txctl.txq = &sc->tx.txq[qnum]; | ||
290 | |||
291 | ath9k_ps_wakeup(sc); | ||
292 | ar9003_paprd_init_table(ah); | ||
293 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
294 | if (!(ah->caps.tx_chainmask & BIT(chain))) | ||
295 | continue; | ||
296 | |||
297 | chain_ok = 0; | ||
298 | memset(tx_info, 0, sizeof(*tx_info)); | ||
299 | tx_info->band = band; | ||
300 | |||
301 | for (i = 0; i < 4; i++) { | ||
302 | tx_info->control.rates[i].idx = sband->n_bitrates - 1; | ||
303 | tx_info->control.rates[i].count = 6; | ||
304 | } | ||
305 | |||
306 | init_completion(&sc->paprd_complete); | ||
307 | ar9003_paprd_setup_gain_table(ah, chain); | ||
308 | txctl.paprd = BIT(chain); | ||
309 | if (ath_tx_start(hw, skb, &txctl) != 0) | ||
310 | break; | ||
311 | |||
312 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | ||
313 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); | ||
314 | if (!time_left) { | ||
315 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
316 | "Timeout waiting for paprd training on " | ||
317 | "TX chain %d\n", | ||
318 | chain); | ||
319 | goto fail_paprd; | ||
320 | } | ||
321 | |||
322 | if (!ar9003_paprd_is_done(ah)) | ||
323 | break; | ||
324 | |||
325 | if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) | ||
326 | break; | ||
327 | |||
328 | chain_ok = 1; | ||
329 | } | ||
330 | kfree_skb(skb); | ||
331 | |||
332 | if (chain_ok) { | ||
333 | ah->curchan->paprd_done = true; | ||
334 | ath_paprd_activate(sc); | ||
335 | } | ||
336 | |||
337 | fail_paprd: | ||
338 | ath9k_ps_restore(sc); | ||
339 | } | ||
340 | |||
235 | /* | 341 | /* |
236 | * This routine performs the periodic noise floor calibration function | 342 | * This routine performs the periodic noise floor calibration function |
237 | * that is used to adjust and optimize the chip performance. This | 343 | * that is used to adjust and optimize the chip performance. This |
@@ -285,7 +391,8 @@ void ath_ani_calibrate(unsigned long data) | |||
285 | } | 391 | } |
286 | 392 | ||
287 | /* Verify whether we must check ANI */ | 393 | /* Verify whether we must check ANI */ |
288 | if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { | 394 | if ((timestamp - common->ani.checkani_timer) >= |
395 | ah->config.ani_poll_interval) { | ||
289 | aniflag = true; | 396 | aniflag = true; |
290 | common->ani.checkani_timer = timestamp; | 397 | common->ani.checkani_timer = timestamp; |
291 | } | 398 | } |
@@ -326,15 +433,24 @@ set_timer: | |||
326 | */ | 433 | */ |
327 | cal_interval = ATH_LONG_CALINTERVAL; | 434 | cal_interval = ATH_LONG_CALINTERVAL; |
328 | if (sc->sc_ah->config.enable_ani) | 435 | if (sc->sc_ah->config.enable_ani) |
329 | cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); | 436 | cal_interval = min(cal_interval, |
437 | (u32)ah->config.ani_poll_interval); | ||
330 | if (!common->ani.caldone) | 438 | if (!common->ani.caldone) |
331 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 439 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
332 | 440 | ||
333 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | 441 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); |
442 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && | ||
443 | !(sc->sc_flags & SC_OP_SCANNING)) { | ||
444 | if (!sc->sc_ah->curchan->paprd_done) | ||
445 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | ||
446 | else | ||
447 | ath_paprd_activate(sc); | ||
448 | } | ||
334 | } | 449 | } |
335 | 450 | ||
336 | static void ath_start_ani(struct ath_common *common) | 451 | static void ath_start_ani(struct ath_common *common) |
337 | { | 452 | { |
453 | struct ath_hw *ah = common->ah; | ||
338 | unsigned long timestamp = jiffies_to_msecs(jiffies); | 454 | unsigned long timestamp = jiffies_to_msecs(jiffies); |
339 | struct ath_softc *sc = (struct ath_softc *) common->priv; | 455 | struct ath_softc *sc = (struct ath_softc *) common->priv; |
340 | 456 | ||
@@ -346,7 +462,8 @@ static void ath_start_ani(struct ath_common *common) | |||
346 | common->ani.checkani_timer = timestamp; | 462 | common->ani.checkani_timer = timestamp; |
347 | 463 | ||
348 | mod_timer(&common->ani.timer, | 464 | mod_timer(&common->ani.timer, |
349 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 465 | jiffies + |
466 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
350 | } | 467 | } |
351 | 468 | ||
352 | /* | 469 | /* |
@@ -524,6 +641,12 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
524 | !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) | 641 | !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) |
525 | goto chip_reset; | 642 | goto chip_reset; |
526 | 643 | ||
644 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && | ||
645 | (status & ATH9K_INT_BB_WATCHDOG)) { | ||
646 | ar9003_hw_bb_watchdog_dbg_info(ah); | ||
647 | goto chip_reset; | ||
648 | } | ||
649 | |||
527 | if (status & ATH9K_INT_SWBA) | 650 | if (status & ATH9K_INT_SWBA) |
528 | tasklet_schedule(&sc->bcon_tasklet); | 651 | tasklet_schedule(&sc->bcon_tasklet); |
529 | 652 | ||
@@ -619,234 +742,6 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, | |||
619 | return chanmode; | 742 | return chanmode; |
620 | } | 743 | } |
621 | 744 | ||
622 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
623 | struct ath9k_keyval *hk, const u8 *addr, | ||
624 | bool authenticator) | ||
625 | { | ||
626 | struct ath_hw *ah = common->ah; | ||
627 | const u8 *key_rxmic; | ||
628 | const u8 *key_txmic; | ||
629 | |||
630 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
631 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
632 | |||
633 | if (addr == NULL) { | ||
634 | /* | ||
635 | * Group key installation - only two key cache entries are used | ||
636 | * regardless of splitmic capability since group key is only | ||
637 | * used either for TX or RX. | ||
638 | */ | ||
639 | if (authenticator) { | ||
640 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
641 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
642 | } else { | ||
643 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
644 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
645 | } | ||
646 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
647 | } | ||
648 | if (!common->splitmic) { | ||
649 | /* TX and RX keys share the same key cache entry. */ | ||
650 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
651 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
652 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
653 | } | ||
654 | |||
655 | /* Separate key cache entries for TX and RX */ | ||
656 | |||
657 | /* TX key goes at first index, RX key at +32. */ | ||
658 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
659 | if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { | ||
660 | /* TX MIC entry failed. No need to proceed further */ | ||
661 | ath_print(common, ATH_DBG_FATAL, | ||
662 | "Setting TX MIC Key Failed\n"); | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
667 | /* XXX delete tx key on failure? */ | ||
668 | return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); | ||
669 | } | ||
670 | |||
671 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
672 | { | ||
673 | int i; | ||
674 | |||
675 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
676 | if (test_bit(i, common->keymap) || | ||
677 | test_bit(i + 64, common->keymap)) | ||
678 | continue; /* At least one part of TKIP key allocated */ | ||
679 | if (common->splitmic && | ||
680 | (test_bit(i + 32, common->keymap) || | ||
681 | test_bit(i + 64 + 32, common->keymap))) | ||
682 | continue; /* At least one part of TKIP key allocated */ | ||
683 | |||
684 | /* Found a free slot for a TKIP key */ | ||
685 | return i; | ||
686 | } | ||
687 | return -1; | ||
688 | } | ||
689 | |||
690 | static int ath_reserve_key_cache_slot(struct ath_common *common) | ||
691 | { | ||
692 | int i; | ||
693 | |||
694 | /* First, try to find slots that would not be available for TKIP. */ | ||
695 | if (common->splitmic) { | ||
696 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
697 | if (!test_bit(i, common->keymap) && | ||
698 | (test_bit(i + 32, common->keymap) || | ||
699 | test_bit(i + 64, common->keymap) || | ||
700 | test_bit(i + 64 + 32, common->keymap))) | ||
701 | return i; | ||
702 | if (!test_bit(i + 32, common->keymap) && | ||
703 | (test_bit(i, common->keymap) || | ||
704 | test_bit(i + 64, common->keymap) || | ||
705 | test_bit(i + 64 + 32, common->keymap))) | ||
706 | return i + 32; | ||
707 | if (!test_bit(i + 64, common->keymap) && | ||
708 | (test_bit(i , common->keymap) || | ||
709 | test_bit(i + 32, common->keymap) || | ||
710 | test_bit(i + 64 + 32, common->keymap))) | ||
711 | return i + 64; | ||
712 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
713 | (test_bit(i, common->keymap) || | ||
714 | test_bit(i + 32, common->keymap) || | ||
715 | test_bit(i + 64, common->keymap))) | ||
716 | return i + 64 + 32; | ||
717 | } | ||
718 | } else { | ||
719 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
720 | if (!test_bit(i, common->keymap) && | ||
721 | test_bit(i + 64, common->keymap)) | ||
722 | return i; | ||
723 | if (test_bit(i, common->keymap) && | ||
724 | !test_bit(i + 64, common->keymap)) | ||
725 | return i + 64; | ||
726 | } | ||
727 | } | ||
728 | |||
729 | /* No partially used TKIP slots, pick any available slot */ | ||
730 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
731 | /* Do not allow slots that could be needed for TKIP group keys | ||
732 | * to be used. This limitation could be removed if we know that | ||
733 | * TKIP will not be used. */ | ||
734 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
735 | continue; | ||
736 | if (common->splitmic) { | ||
737 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
738 | continue; | ||
739 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
740 | continue; | ||
741 | } | ||
742 | |||
743 | if (!test_bit(i, common->keymap)) | ||
744 | return i; /* Found a free slot for a key */ | ||
745 | } | ||
746 | |||
747 | /* No free slot found */ | ||
748 | return -1; | ||
749 | } | ||
750 | |||
751 | static int ath_key_config(struct ath_common *common, | ||
752 | struct ieee80211_vif *vif, | ||
753 | struct ieee80211_sta *sta, | ||
754 | struct ieee80211_key_conf *key) | ||
755 | { | ||
756 | struct ath_hw *ah = common->ah; | ||
757 | struct ath9k_keyval hk; | ||
758 | const u8 *mac = NULL; | ||
759 | int ret = 0; | ||
760 | int idx; | ||
761 | |||
762 | memset(&hk, 0, sizeof(hk)); | ||
763 | |||
764 | switch (key->alg) { | ||
765 | case ALG_WEP: | ||
766 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
767 | break; | ||
768 | case ALG_TKIP: | ||
769 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
770 | break; | ||
771 | case ALG_CCMP: | ||
772 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
773 | break; | ||
774 | default: | ||
775 | return -EOPNOTSUPP; | ||
776 | } | ||
777 | |||
778 | hk.kv_len = key->keylen; | ||
779 | memcpy(hk.kv_val, key->key, key->keylen); | ||
780 | |||
781 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
782 | /* For now, use the default keys for broadcast keys. This may | ||
783 | * need to change with virtual interfaces. */ | ||
784 | idx = key->keyidx; | ||
785 | } else if (key->keyidx) { | ||
786 | if (WARN_ON(!sta)) | ||
787 | return -EOPNOTSUPP; | ||
788 | mac = sta->addr; | ||
789 | |||
790 | if (vif->type != NL80211_IFTYPE_AP) { | ||
791 | /* Only keyidx 0 should be used with unicast key, but | ||
792 | * allow this for client mode for now. */ | ||
793 | idx = key->keyidx; | ||
794 | } else | ||
795 | return -EIO; | ||
796 | } else { | ||
797 | if (WARN_ON(!sta)) | ||
798 | return -EOPNOTSUPP; | ||
799 | mac = sta->addr; | ||
800 | |||
801 | if (key->alg == ALG_TKIP) | ||
802 | idx = ath_reserve_key_cache_slot_tkip(common); | ||
803 | else | ||
804 | idx = ath_reserve_key_cache_slot(common); | ||
805 | if (idx < 0) | ||
806 | return -ENOSPC; /* no free key cache entries */ | ||
807 | } | ||
808 | |||
809 | if (key->alg == ALG_TKIP) | ||
810 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
811 | vif->type == NL80211_IFTYPE_AP); | ||
812 | else | ||
813 | ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); | ||
814 | |||
815 | if (!ret) | ||
816 | return -EIO; | ||
817 | |||
818 | set_bit(idx, common->keymap); | ||
819 | if (key->alg == ALG_TKIP) { | ||
820 | set_bit(idx + 64, common->keymap); | ||
821 | if (common->splitmic) { | ||
822 | set_bit(idx + 32, common->keymap); | ||
823 | set_bit(idx + 64 + 32, common->keymap); | ||
824 | } | ||
825 | } | ||
826 | |||
827 | return idx; | ||
828 | } | ||
829 | |||
830 | static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key) | ||
831 | { | ||
832 | struct ath_hw *ah = common->ah; | ||
833 | |||
834 | ath9k_hw_keyreset(ah, key->hw_key_idx); | ||
835 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
836 | return; | ||
837 | |||
838 | clear_bit(key->hw_key_idx, common->keymap); | ||
839 | if (key->alg != ALG_TKIP) | ||
840 | return; | ||
841 | |||
842 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
843 | if (common->splitmic) { | ||
844 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
845 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
846 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 745 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
851 | struct ieee80211_vif *vif, | 746 | struct ieee80211_vif *vif, |
852 | struct ieee80211_bss_conf *bss_conf) | 747 | struct ieee80211_bss_conf *bss_conf) |
@@ -1032,25 +927,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
1032 | return r; | 927 | return r; |
1033 | } | 928 | } |
1034 | 929 | ||
1035 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | 930 | static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) |
1036 | { | 931 | { |
1037 | int qnum; | 932 | int qnum; |
1038 | 933 | ||
1039 | switch (queue) { | 934 | switch (queue) { |
1040 | case 0: | 935 | case 0: |
1041 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO]; | 936 | qnum = sc->tx.hwq_map[WME_AC_VO]; |
1042 | break; | 937 | break; |
1043 | case 1: | 938 | case 1: |
1044 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI]; | 939 | qnum = sc->tx.hwq_map[WME_AC_VI]; |
1045 | break; | 940 | break; |
1046 | case 2: | 941 | case 2: |
1047 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; | 942 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
1048 | break; | 943 | break; |
1049 | case 3: | 944 | case 3: |
1050 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK]; | 945 | qnum = sc->tx.hwq_map[WME_AC_BK]; |
1051 | break; | 946 | break; |
1052 | default: | 947 | default: |
1053 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; | 948 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
1054 | break; | 949 | break; |
1055 | } | 950 | } |
1056 | 951 | ||
@@ -1062,16 +957,16 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | |||
1062 | int qnum; | 957 | int qnum; |
1063 | 958 | ||
1064 | switch (queue) { | 959 | switch (queue) { |
1065 | case ATH9K_WME_AC_VO: | 960 | case WME_AC_VO: |
1066 | qnum = 0; | 961 | qnum = 0; |
1067 | break; | 962 | break; |
1068 | case ATH9K_WME_AC_VI: | 963 | case WME_AC_VI: |
1069 | qnum = 1; | 964 | qnum = 1; |
1070 | break; | 965 | break; |
1071 | case ATH9K_WME_AC_BE: | 966 | case WME_AC_BE: |
1072 | qnum = 2; | 967 | qnum = 2; |
1073 | break; | 968 | break; |
1074 | case ATH9K_WME_AC_BK: | 969 | case WME_AC_BK: |
1075 | qnum = 3; | 970 | qnum = 3; |
1076 | break; | 971 | break; |
1077 | default: | 972 | default: |
@@ -1201,7 +1096,9 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1201 | ATH9K_INT_GLOBAL; | 1096 | ATH9K_INT_GLOBAL; |
1202 | 1097 | ||
1203 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 1098 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
1204 | ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP; | 1099 | ah->imask |= ATH9K_INT_RXHP | |
1100 | ATH9K_INT_RXLP | | ||
1101 | ATH9K_INT_BB_WATCHDOG; | ||
1205 | else | 1102 | else |
1206 | ah->imask |= ATH9K_INT_RX; | 1103 | ah->imask |= ATH9K_INT_RX; |
1207 | 1104 | ||
@@ -1251,6 +1148,7 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1251 | struct ath_tx_control txctl; | 1148 | struct ath_tx_control txctl; |
1252 | int padpos, padsize; | 1149 | int padpos, padsize; |
1253 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1150 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1151 | int qnum; | ||
1254 | 1152 | ||
1255 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { | 1153 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { |
1256 | ath_print(common, ATH_DBG_XMIT, | 1154 | ath_print(common, ATH_DBG_XMIT, |
@@ -1280,7 +1178,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1280 | * completed and if needed, also for RX of buffered frames. | 1178 | * completed and if needed, also for RX of buffered frames. |
1281 | */ | 1179 | */ |
1282 | ath9k_ps_wakeup(sc); | 1180 | ath9k_ps_wakeup(sc); |
1283 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 1181 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
1182 | ath9k_hw_setrxabort(sc->sc_ah, 0); | ||
1284 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 1183 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
1285 | ath_print(common, ATH_DBG_PS, | 1184 | ath_print(common, ATH_DBG_PS, |
1286 | "Sending PS-Poll to pick a buffered frame\n"); | 1185 | "Sending PS-Poll to pick a buffered frame\n"); |
@@ -1322,11 +1221,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1322 | memmove(skb->data, skb->data + padsize, padpos); | 1221 | memmove(skb->data, skb->data + padsize, padpos); |
1323 | } | 1222 | } |
1324 | 1223 | ||
1325 | /* Check if a tx queue is available */ | 1224 | qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); |
1326 | 1225 | txctl.txq = &sc->tx.txq[qnum]; | |
1327 | txctl.txq = ath_test_get_txq(sc, skb); | ||
1328 | if (!txctl.txq) | ||
1329 | goto exit; | ||
1330 | 1226 | ||
1331 | ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); | 1227 | ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); |
1332 | 1228 | ||
@@ -1352,8 +1248,11 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1352 | 1248 | ||
1353 | aphy->state = ATH_WIPHY_INACTIVE; | 1249 | aphy->state = ATH_WIPHY_INACTIVE; |
1354 | 1250 | ||
1355 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | 1251 | if (led_blink) |
1252 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
1253 | |||
1356 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1254 | cancel_delayed_work_sync(&sc->tx_complete_work); |
1255 | cancel_work_sync(&sc->paprd_work); | ||
1357 | 1256 | ||
1358 | if (!sc->num_sec_wiphy) { | 1257 | if (!sc->num_sec_wiphy) { |
1359 | cancel_delayed_work_sync(&sc->wiphy_work); | 1258 | cancel_delayed_work_sync(&sc->wiphy_work); |
@@ -1547,8 +1446,8 @@ void ath9k_enable_ps(struct ath_softc *sc) | |||
1547 | ah->imask |= ATH9K_INT_TIM_TIMER; | 1446 | ah->imask |= ATH9K_INT_TIM_TIMER; |
1548 | ath9k_hw_set_interrupts(ah, ah->imask); | 1447 | ath9k_hw_set_interrupts(ah, ah->imask); |
1549 | } | 1448 | } |
1449 | ath9k_hw_setrxabort(ah, 1); | ||
1550 | } | 1450 | } |
1551 | ath9k_hw_setrxabort(ah, 1); | ||
1552 | } | 1451 | } |
1553 | 1452 | ||
1554 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1453 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
@@ -1785,7 +1684,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1785 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); | 1684 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); |
1786 | 1685 | ||
1787 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) | 1686 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) |
1788 | if ((qnum == sc->tx.hwq_map[ATH9K_WME_AC_BE]) && !ret) | 1687 | if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) |
1789 | ath_beaconq_config(sc); | 1688 | ath_beaconq_config(sc); |
1790 | 1689 | ||
1791 | mutex_unlock(&sc->mutex); | 1690 | mutex_unlock(&sc->mutex); |
@@ -1813,7 +1712,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1813 | 1712 | ||
1814 | switch (cmd) { | 1713 | switch (cmd) { |
1815 | case SET_KEY: | 1714 | case SET_KEY: |
1816 | ret = ath_key_config(common, vif, sta, key); | 1715 | ret = ath9k_cmn_key_config(common, vif, sta, key); |
1817 | if (ret >= 0) { | 1716 | if (ret >= 0) { |
1818 | key->hw_key_idx = ret; | 1717 | key->hw_key_idx = ret; |
1819 | /* push IV and Michael MIC generation to stack */ | 1718 | /* push IV and Michael MIC generation to stack */ |
@@ -1826,7 +1725,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1826 | } | 1725 | } |
1827 | break; | 1726 | break; |
1828 | case DISABLE_KEY: | 1727 | case DISABLE_KEY: |
1829 | ath_key_delete(common, key); | 1728 | ath9k_cmn_key_delete(common, key); |
1830 | break; | 1729 | break; |
1831 | default: | 1730 | default: |
1832 | ret = -EINVAL; | 1731 | ret = -EINVAL; |
@@ -1999,6 +1898,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1999 | struct ath_softc *sc = aphy->sc; | 1898 | struct ath_softc *sc = aphy->sc; |
2000 | int ret = 0; | 1899 | int ret = 0; |
2001 | 1900 | ||
1901 | local_bh_disable(); | ||
1902 | |||
2002 | switch (action) { | 1903 | switch (action) { |
2003 | case IEEE80211_AMPDU_RX_START: | 1904 | case IEEE80211_AMPDU_RX_START: |
2004 | if (!(sc->sc_flags & SC_OP_RXAGGR)) | 1905 | if (!(sc->sc_flags & SC_OP_RXAGGR)) |
@@ -2028,6 +1929,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
2028 | "Unknown AMPDU action\n"); | 1929 | "Unknown AMPDU action\n"); |
2029 | } | 1930 | } |
2030 | 1931 | ||
1932 | local_bh_enable(); | ||
1933 | |||
2031 | return ret; | 1934 | return ret; |
2032 | } | 1935 | } |
2033 | 1936 | ||
@@ -2072,6 +1975,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
2072 | ath9k_wiphy_pause_all_forced(sc, aphy); | 1975 | ath9k_wiphy_pause_all_forced(sc, aphy); |
2073 | sc->sc_flags |= SC_OP_SCANNING; | 1976 | sc->sc_flags |= SC_OP_SCANNING; |
2074 | del_timer_sync(&common->ani.timer); | 1977 | del_timer_sync(&common->ani.timer); |
1978 | cancel_work_sync(&sc->paprd_work); | ||
2075 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1979 | cancel_delayed_work_sync(&sc->tx_complete_work); |
2076 | mutex_unlock(&sc->mutex); | 1980 | mutex_unlock(&sc->mutex); |
2077 | } | 1981 | } |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 1ec836cf1c0d..257b10ba6f57 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -28,6 +28,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | 28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ |
29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | 30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ |
31 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ | ||
31 | { 0 } | 32 | { 0 } |
32 | }; | 33 | }; |
33 | 34 | ||
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 8519452c95f1..600ee0ba2880 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "ath9k.h" | 20 | #include "ath9k.h" |
21 | 21 | ||
22 | static const struct ath_rate_table ar5416_11na_ratetable = { | 22 | static const struct ath_rate_table ar5416_11na_ratetable = { |
23 | 42, | 23 | 43, |
24 | 8, /* MCS start */ | 24 | 8, /* MCS start */ |
25 | { | 25 | { |
26 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | 26 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
@@ -40,73 +40,75 @@ static const struct ath_rate_table ar5416_11na_ratetable = { | |||
40 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 40 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
41 | 29300, 7, 108, 4, 7, 7, 7, 7 }, | 41 | 29300, 7, 108, 4, 7, 7, 7, 7 }, |
42 | { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 42 | { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
43 | 6400, 0, 0, 0, 8, 24, 8, 24 }, | 43 | 6400, 0, 0, 0, 8, 25, 8, 25 }, |
44 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ | 44 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
45 | 12700, 1, 1, 2, 9, 25, 9, 25 }, | 45 | 12700, 1, 1, 2, 9, 26, 9, 26 }, |
46 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 46 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
47 | 18800, 2, 2, 2, 10, 26, 10, 26 }, | 47 | 18800, 2, 2, 2, 10, 27, 10, 27 }, |
48 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ | 48 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ |
49 | 25000, 3, 3, 4, 11, 27, 11, 27 }, | 49 | 25000, 3, 3, 4, 11, 28, 11, 28 }, |
50 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ | 50 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ |
51 | 36700, 4, 4, 4, 12, 28, 12, 28 }, | 51 | 36700, 4, 4, 4, 12, 29, 12, 29 }, |
52 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ | 52 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ |
53 | 48100, 5, 5, 4, 13, 29, 13, 29 }, | 53 | 48100, 5, 5, 4, 13, 30, 13, 30 }, |
54 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 54 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
55 | 53500, 6, 6, 4, 14, 30, 14, 30 }, | 55 | 53500, 6, 6, 4, 14, 31, 14, 31 }, |
56 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ | 56 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ |
57 | 59000, 7, 7, 4, 15, 31, 15, 32 }, | 57 | 59000, 7, 7, 4, 15, 32, 15, 33 }, |
58 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ | 58 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ |
59 | 12700, 8, 8, 3, 16, 33, 16, 33 }, | 59 | 12700, 8, 8, 3, 16, 34, 16, 34 }, |
60 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ | 60 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ |
61 | 24800, 9, 9, 2, 17, 34, 17, 34 }, | 61 | 24800, 9, 9, 2, 17, 35, 17, 35 }, |
62 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ | 62 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ |
63 | 36600, 10, 10, 2, 18, 35, 18, 35 }, | 63 | 36600, 10, 10, 2, 18, 36, 18, 36 }, |
64 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ | 64 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ |
65 | 48100, 11, 11, 4, 19, 36, 19, 36 }, | 65 | 48100, 11, 11, 4, 19, 37, 19, 37 }, |
66 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ | 66 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ |
67 | 69500, 12, 12, 4, 20, 37, 20, 37 }, | 67 | 69500, 12, 12, 4, 20, 38, 20, 38 }, |
68 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ | 68 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ |
69 | 89500, 13, 13, 4, 21, 38, 21, 38 }, | 69 | 89500, 13, 13, 4, 21, 39, 21, 39 }, |
70 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ | 70 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ |
71 | 98900, 14, 14, 4, 22, 39, 22, 39 }, | 71 | 98900, 14, 14, 4, 22, 40, 22, 40 }, |
72 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ | 72 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ |
73 | 108300, 15, 15, 4, 23, 40, 23, 41 }, | 73 | 108300, 15, 15, 4, 23, 41, 24, 42 }, |
74 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 144.4 Mb */ | ||
75 | 12000, 15, 15, 4, 23, 41, 24, 42 }, | ||
74 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 76 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
75 | 13200, 0, 0, 0, 8, 24, 24, 24 }, | 77 | 13200, 0, 0, 0, 8, 25, 25, 25 }, |
76 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 78 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
77 | 25900, 1, 1, 2, 9, 25, 25, 25 }, | 79 | 25900, 1, 1, 2, 9, 26, 26, 26 }, |
78 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 80 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
79 | 38600, 2, 2, 2, 10, 26, 26, 26 }, | 81 | 38600, 2, 2, 2, 10, 27, 27, 27 }, |
80 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ | 82 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ |
81 | 49800, 3, 3, 4, 11, 27, 27, 27 }, | 83 | 49800, 3, 3, 4, 11, 28, 28, 28 }, |
82 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ | 84 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ |
83 | 72200, 4, 4, 4, 12, 28, 28, 28 }, | 85 | 72200, 4, 4, 4, 12, 29, 29, 29 }, |
84 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ | 86 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ |
85 | 92900, 5, 5, 4, 13, 29, 29, 29 }, | 87 | 92900, 5, 5, 4, 13, 30, 30, 30 }, |
86 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 88 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
87 | 102700, 6, 6, 4, 14, 30, 30, 30 }, | 89 | 102700, 6, 6, 4, 14, 31, 31, 31 }, |
88 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ | 90 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ |
89 | 112000, 7, 7, 4, 15, 31, 32, 32 }, | 91 | 112000, 7, 7, 4, 15, 32, 33, 33 }, |
90 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 92 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
91 | 122000, 7, 7, 4, 15, 31, 32, 32 }, | 93 | 122000, 7, 7, 4, 15, 32, 33, 33 }, |
92 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ | 94 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ |
93 | 25800, 8, 8, 0, 16, 33, 33, 33 }, | 95 | 25800, 8, 8, 0, 16, 34, 34, 34 }, |
94 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ | 96 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ |
95 | 49800, 9, 9, 2, 17, 34, 34, 34 }, | 97 | 49800, 9, 9, 2, 17, 35, 35, 35 }, |
96 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ | 98 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ |
97 | 71900, 10, 10, 2, 18, 35, 35, 35 }, | 99 | 71900, 10, 10, 2, 18, 36, 36, 36 }, |
98 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ | 100 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ |
99 | 92500, 11, 11, 4, 19, 36, 36, 36 }, | 101 | 92500, 11, 11, 4, 19, 37, 37, 37 }, |
100 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ | 102 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ |
101 | 130300, 12, 12, 4, 20, 37, 37, 37 }, | 103 | 130300, 12, 12, 4, 20, 38, 38, 38 }, |
102 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ | 104 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ |
103 | 162800, 13, 13, 4, 21, 38, 38, 38 }, | 105 | 162800, 13, 13, 4, 21, 39, 39, 39 }, |
104 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ | 106 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ |
105 | 178200, 14, 14, 4, 22, 39, 39, 39 }, | 107 | 178200, 14, 14, 4, 22, 40, 40, 40 }, |
106 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ | 108 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ |
107 | 192100, 15, 15, 4, 23, 40, 41, 41 }, | 109 | 192100, 15, 15, 4, 23, 41, 42, 42 }, |
108 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 110 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
109 | 207000, 15, 15, 4, 23, 40, 41, 41 }, | 111 | 207000, 15, 15, 4, 23, 41, 42, 42 }, |
110 | }, | 112 | }, |
111 | 50, /* probe interval */ | 113 | 50, /* probe interval */ |
112 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 114 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
@@ -116,7 +118,7 @@ static const struct ath_rate_table ar5416_11na_ratetable = { | |||
116 | * for HT are the 64K max aggregate limit */ | 118 | * for HT are the 64K max aggregate limit */ |
117 | 119 | ||
118 | static const struct ath_rate_table ar5416_11ng_ratetable = { | 120 | static const struct ath_rate_table ar5416_11ng_ratetable = { |
119 | 46, | 121 | 47, |
120 | 12, /* MCS start */ | 122 | 12, /* MCS start */ |
121 | { | 123 | { |
122 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ | 124 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ |
@@ -144,73 +146,75 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { | |||
144 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 146 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
145 | 30900, 11, 108, 8, 11, 11, 11, 11 }, | 147 | 30900, 11, 108, 8, 11, 11, 11, 11 }, |
146 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 148 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
147 | 6400, 0, 0, 4, 12, 28, 12, 28 }, | 149 | 6400, 0, 0, 4, 12, 29, 12, 29 }, |
148 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ | 150 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
149 | 12700, 1, 1, 6, 13, 29, 13, 29 }, | 151 | 12700, 1, 1, 6, 13, 30, 13, 30 }, |
150 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 152 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
151 | 18800, 2, 2, 6, 14, 30, 14, 30 }, | 153 | 18800, 2, 2, 6, 14, 31, 14, 31 }, |
152 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ | 154 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ |
153 | 25000, 3, 3, 8, 15, 31, 15, 31 }, | 155 | 25000, 3, 3, 8, 15, 32, 15, 32 }, |
154 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ | 156 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ |
155 | 36700, 4, 4, 8, 16, 32, 16, 32 }, | 157 | 36700, 4, 4, 8, 16, 33, 16, 33 }, |
156 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ | 158 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ |
157 | 48100, 5, 5, 8, 17, 33, 17, 33 }, | 159 | 48100, 5, 5, 8, 17, 34, 17, 34 }, |
158 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 160 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
159 | 53500, 6, 6, 8, 18, 34, 18, 34 }, | 161 | 53500, 6, 6, 8, 18, 35, 18, 35 }, |
160 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ | 162 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ |
161 | 59000, 7, 7, 8, 19, 35, 19, 36 }, | 163 | 59000, 7, 7, 8, 19, 36, 19, 37 }, |
162 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ | 164 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ |
163 | 12700, 8, 8, 4, 20, 37, 20, 37 }, | 165 | 12700, 8, 8, 4, 20, 38, 20, 38 }, |
164 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ | 166 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ |
165 | 24800, 9, 9, 6, 21, 38, 21, 38 }, | 167 | 24800, 9, 9, 6, 21, 39, 21, 39 }, |
166 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ | 168 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ |
167 | 36600, 10, 10, 6, 22, 39, 22, 39 }, | 169 | 36600, 10, 10, 6, 22, 40, 22, 40 }, |
168 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ | 170 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ |
169 | 48100, 11, 11, 8, 23, 40, 23, 40 }, | 171 | 48100, 11, 11, 8, 23, 41, 23, 41 }, |
170 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ | 172 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ |
171 | 69500, 12, 12, 8, 24, 41, 24, 41 }, | 173 | 69500, 12, 12, 8, 24, 42, 24, 42 }, |
172 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ | 174 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ |
173 | 89500, 13, 13, 8, 25, 42, 25, 42 }, | 175 | 89500, 13, 13, 8, 25, 43, 25, 43 }, |
174 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ | 176 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ |
175 | 98900, 14, 14, 8, 26, 43, 26, 44 }, | 177 | 98900, 14, 14, 8, 26, 44, 26, 44 }, |
176 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ | 178 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ |
177 | 108300, 15, 15, 8, 27, 44, 27, 45 }, | 179 | 108300, 15, 15, 8, 27, 45, 28, 46 }, |
180 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 130 Mb */ | ||
181 | 120000, 15, 15, 8, 27, 45, 28, 46 }, | ||
178 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 182 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
179 | 13200, 0, 0, 8, 12, 28, 28, 28 }, | 183 | 13200, 0, 0, 8, 12, 29, 29, 29 }, |
180 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 184 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
181 | 25900, 1, 1, 8, 13, 29, 29, 29 }, | 185 | 25900, 1, 1, 8, 13, 30, 30, 30 }, |
182 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 186 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
183 | 38600, 2, 2, 8, 14, 30, 30, 30 }, | 187 | 38600, 2, 2, 8, 14, 31, 31, 31 }, |
184 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ | 188 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ |
185 | 49800, 3, 3, 8, 15, 31, 31, 31 }, | 189 | 49800, 3, 3, 8, 15, 32, 32, 32 }, |
186 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ | 190 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ |
187 | 72200, 4, 4, 8, 16, 32, 32, 32 }, | 191 | 72200, 4, 4, 8, 16, 33, 33, 33 }, |
188 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ | 192 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ |
189 | 92900, 5, 5, 8, 17, 33, 33, 33 }, | 193 | 92900, 5, 5, 8, 17, 34, 34, 34 }, |
190 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 194 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
191 | 102700, 6, 6, 8, 18, 34, 34, 34 }, | 195 | 102700, 6, 6, 8, 18, 35, 35, 35 }, |
192 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ | 196 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ |
193 | 112000, 7, 7, 8, 19, 35, 36, 36 }, | 197 | 112000, 7, 7, 8, 19, 36, 37, 37 }, |
194 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 198 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
195 | 122000, 7, 7, 8, 19, 35, 36, 36 }, | 199 | 122000, 7, 7, 8, 19, 36, 37, 37 }, |
196 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ | 200 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ |
197 | 25800, 8, 8, 8, 20, 37, 37, 37 }, | 201 | 25800, 8, 8, 8, 20, 38, 38, 38 }, |
198 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ | 202 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ |
199 | 49800, 9, 9, 8, 21, 38, 38, 38 }, | 203 | 49800, 9, 9, 8, 21, 39, 39, 39 }, |
200 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ | 204 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ |
201 | 71900, 10, 10, 8, 22, 39, 39, 39 }, | 205 | 71900, 10, 10, 8, 22, 40, 40, 40 }, |
202 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ | 206 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ |
203 | 92500, 11, 11, 8, 23, 40, 40, 40 }, | 207 | 92500, 11, 11, 8, 23, 41, 41, 41 }, |
204 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ | 208 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ |
205 | 130300, 12, 12, 8, 24, 41, 41, 41 }, | 209 | 130300, 12, 12, 8, 24, 42, 42, 42 }, |
206 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ | 210 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ |
207 | 162800, 13, 13, 8, 25, 42, 42, 42 }, | 211 | 162800, 13, 13, 8, 25, 43, 43, 43 }, |
208 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ | 212 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ |
209 | 178200, 14, 14, 8, 26, 43, 43, 43 }, | 213 | 178200, 14, 14, 8, 26, 44, 44, 44 }, |
210 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ | 214 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ |
211 | 192100, 15, 15, 8, 27, 44, 45, 45 }, | 215 | 192100, 15, 15, 8, 27, 45, 46, 46 }, |
212 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 216 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
213 | 207000, 15, 15, 8, 27, 44, 45, 45 }, | 217 | 207000, 15, 15, 8, 27, 45, 46, 46 }, |
214 | }, | 218 | }, |
215 | 50, /* probe interval */ | 219 | 50, /* probe interval */ |
216 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 220 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
@@ -1193,21 +1197,19 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1193 | } | 1197 | } |
1194 | 1198 | ||
1195 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | 1199 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, |
1196 | bool is_cw40, bool is_sgi40) | 1200 | bool is_cw40, bool is_sgi) |
1197 | { | 1201 | { |
1198 | u8 caps = 0; | 1202 | u8 caps = 0; |
1199 | 1203 | ||
1200 | if (sta->ht_cap.ht_supported) { | 1204 | if (sta->ht_cap.ht_supported) { |
1201 | caps = WLAN_RC_HT_FLAG; | 1205 | caps = WLAN_RC_HT_FLAG; |
1202 | if (sc->sc_ah->caps.tx_chainmask != 1 && | 1206 | if (sta->ht_cap.mcs.rx_mask[1]) |
1203 | ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { | 1207 | caps |= WLAN_RC_DS_FLAG; |
1204 | if (sta->ht_cap.mcs.rx_mask[1]) | ||
1205 | caps |= WLAN_RC_DS_FLAG; | ||
1206 | } | ||
1207 | if (is_cw40) | 1208 | if (is_cw40) |
1208 | caps |= WLAN_RC_40_FLAG; | 1209 | caps |= WLAN_RC_40_FLAG; |
1209 | if (is_sgi40) | 1210 | if (is_sgi) |
1210 | caps |= WLAN_RC_SGI_FLAG; | 1211 | caps |= WLAN_RC_SGI_FLAG; |
1212 | |||
1211 | } | 1213 | } |
1212 | 1214 | ||
1213 | return caps; | 1215 | return caps; |
@@ -1300,7 +1302,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1300 | struct ath_softc *sc = priv; | 1302 | struct ath_softc *sc = priv; |
1301 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1303 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1302 | const struct ath_rate_table *rate_table; | 1304 | const struct ath_rate_table *rate_table; |
1303 | bool is_cw40, is_sgi40; | 1305 | bool is_cw40, is_sgi = false; |
1304 | int i, j = 0; | 1306 | int i, j = 0; |
1305 | 1307 | ||
1306 | for (i = 0; i < sband->n_bitrates; i++) { | 1308 | for (i = 0; i < sband->n_bitrates; i++) { |
@@ -1323,7 +1325,11 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1323 | } | 1325 | } |
1324 | 1326 | ||
1325 | is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 1327 | is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
1326 | is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; | 1328 | |
1329 | if (is_cw40) | ||
1330 | is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; | ||
1331 | else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) | ||
1332 | is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; | ||
1327 | 1333 | ||
1328 | /* Choose rate table first */ | 1334 | /* Choose rate table first */ |
1329 | 1335 | ||
@@ -1336,7 +1342,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1336 | rate_table = hw_rate_table[sc->cur_rate_mode]; | 1342 | rate_table = hw_rate_table[sc->cur_rate_mode]; |
1337 | } | 1343 | } |
1338 | 1344 | ||
1339 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); | 1345 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); |
1340 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1346 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
1341 | } | 1347 | } |
1342 | 1348 | ||
@@ -1347,10 +1353,10 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1347 | struct ath_softc *sc = priv; | 1353 | struct ath_softc *sc = priv; |
1348 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1354 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1349 | const struct ath_rate_table *rate_table = NULL; | 1355 | const struct ath_rate_table *rate_table = NULL; |
1350 | bool oper_cw40 = false, oper_sgi40; | 1356 | bool oper_cw40 = false, oper_sgi; |
1351 | bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? | 1357 | bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? |
1352 | true : false; | 1358 | true : false; |
1353 | bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? | 1359 | bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? |
1354 | true : false; | 1360 | true : false; |
1355 | 1361 | ||
1356 | /* FIXME: Handle AP mode later when we support CWM */ | 1362 | /* FIXME: Handle AP mode later when we support CWM */ |
@@ -1363,15 +1369,21 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1363 | oper_chan_type == NL80211_CHAN_HT40PLUS) | 1369 | oper_chan_type == NL80211_CHAN_HT40PLUS) |
1364 | oper_cw40 = true; | 1370 | oper_cw40 = true; |
1365 | 1371 | ||
1366 | oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? | 1372 | if (oper_cw40) |
1367 | true : false; | 1373 | oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? |
1374 | true : false; | ||
1375 | else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) | ||
1376 | oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? | ||
1377 | true : false; | ||
1378 | else | ||
1379 | oper_sgi = false; | ||
1368 | 1380 | ||
1369 | if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { | 1381 | if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) { |
1370 | rate_table = ath_choose_rate_table(sc, sband->band, | 1382 | rate_table = ath_choose_rate_table(sc, sband->band, |
1371 | sta->ht_cap.ht_supported, | 1383 | sta->ht_cap.ht_supported, |
1372 | oper_cw40); | 1384 | oper_cw40); |
1373 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, | 1385 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, |
1374 | oper_cw40, oper_sgi40); | 1386 | oper_cw40, oper_sgi); |
1375 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1387 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
1376 | 1388 | ||
1377 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, | 1389 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ca6065b71b46..da0cfe90c38a 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -116,9 +116,6 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
116 | /* configure operational mode */ | 116 | /* configure operational mode */ |
117 | ath9k_hw_setopmode(ah); | 117 | ath9k_hw_setopmode(ah); |
118 | 118 | ||
119 | /* Handle any link-level address change. */ | ||
120 | ath9k_hw_setmac(ah, common->macaddr); | ||
121 | |||
122 | /* calculate and install multicast filter */ | 119 | /* calculate and install multicast filter */ |
123 | mfilt[0] = mfilt[1] = ~0; | 120 | mfilt[0] = mfilt[1] = ~0; |
124 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | 121 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); |
@@ -295,7 +292,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
295 | 292 | ||
296 | ath_opmode_init(sc); | 293 | ath_opmode_init(sc); |
297 | 294 | ||
298 | ath9k_hw_startpcureceive(sc->sc_ah); | 295 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); |
299 | } | 296 | } |
300 | 297 | ||
301 | static void ath_edma_stop_recv(struct ath_softc *sc) | 298 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -501,7 +498,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
501 | start_recv: | 498 | start_recv: |
502 | spin_unlock_bh(&sc->rx.rxbuflock); | 499 | spin_unlock_bh(&sc->rx.rxbuflock); |
503 | ath_opmode_init(sc); | 500 | ath_opmode_init(sc); |
504 | ath9k_hw_startpcureceive(ah); | 501 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); |
505 | 502 | ||
506 | return 0; | 503 | return 0; |
507 | } | 504 | } |
@@ -700,12 +697,16 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, | |||
700 | bf = SKB_CB_ATHBUF(skb); | 697 | bf = SKB_CB_ATHBUF(skb); |
701 | BUG_ON(!bf); | 698 | BUG_ON(!bf); |
702 | 699 | ||
703 | dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, | 700 | dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, |
704 | common->rx_bufsize, DMA_FROM_DEVICE); | 701 | common->rx_bufsize, DMA_FROM_DEVICE); |
705 | 702 | ||
706 | ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data); | 703 | ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data); |
707 | if (ret == -EINPROGRESS) | 704 | if (ret == -EINPROGRESS) { |
705 | /*let device gain the buffer again*/ | ||
706 | dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, | ||
707 | common->rx_bufsize, DMA_FROM_DEVICE); | ||
708 | return false; | 708 | return false; |
709 | } | ||
709 | 710 | ||
710 | __skb_unlink(skb, &rx_edma->rx_fifo); | 711 | __skb_unlink(skb, &rx_edma->rx_fifo); |
711 | if (ret == -EINVAL) { | 712 | if (ret == -EINVAL) { |
@@ -814,13 +815,263 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
814 | * 1. accessing the frame | 815 | * 1. accessing the frame |
815 | * 2. requeueing the same buffer to h/w | 816 | * 2. requeueing the same buffer to h/w |
816 | */ | 817 | */ |
817 | dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, | 818 | dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, |
818 | common->rx_bufsize, | 819 | common->rx_bufsize, |
819 | DMA_FROM_DEVICE); | 820 | DMA_FROM_DEVICE); |
820 | 821 | ||
821 | return bf; | 822 | return bf; |
822 | } | 823 | } |
823 | 824 | ||
825 | /* Assumes you've already done the endian to CPU conversion */ | ||
826 | static bool ath9k_rx_accept(struct ath_common *common, | ||
827 | struct ieee80211_hdr *hdr, | ||
828 | struct ieee80211_rx_status *rxs, | ||
829 | struct ath_rx_status *rx_stats, | ||
830 | bool *decrypt_error) | ||
831 | { | ||
832 | struct ath_hw *ah = common->ah; | ||
833 | __le16 fc; | ||
834 | u8 rx_status_len = ah->caps.rx_status_len; | ||
835 | |||
836 | fc = hdr->frame_control; | ||
837 | |||
838 | if (!rx_stats->rs_datalen) | ||
839 | return false; | ||
840 | /* | ||
841 | * rs_status follows rs_datalen so if rs_datalen is too large | ||
842 | * we can take a hint that hardware corrupted it, so ignore | ||
843 | * those frames. | ||
844 | */ | ||
845 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) | ||
846 | return false; | ||
847 | |||
848 | /* | ||
849 | * rs_more indicates chained descriptors which can be used | ||
850 | * to link buffers together for a sort of scatter-gather | ||
851 | * operation. | ||
852 | * reject the frame, we don't support scatter-gather yet and | ||
853 | * the frame is probably corrupt anyway | ||
854 | */ | ||
855 | if (rx_stats->rs_more) | ||
856 | return false; | ||
857 | |||
858 | /* | ||
859 | * The rx_stats->rs_status will not be set until the end of the | ||
860 | * chained descriptors so it can be ignored if rs_more is set. The | ||
861 | * rs_more will be false at the last element of the chained | ||
862 | * descriptors. | ||
863 | */ | ||
864 | if (rx_stats->rs_status != 0) { | ||
865 | if (rx_stats->rs_status & ATH9K_RXERR_CRC) | ||
866 | rxs->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
867 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) | ||
868 | return false; | ||
869 | |||
870 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { | ||
871 | *decrypt_error = true; | ||
872 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { | ||
873 | if (ieee80211_is_ctl(fc)) | ||
874 | /* | ||
875 | * Sometimes, we get invalid | ||
876 | * MIC failures on valid control frames. | ||
877 | * Remove these mic errors. | ||
878 | */ | ||
879 | rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | ||
880 | else | ||
881 | rxs->flag |= RX_FLAG_MMIC_ERROR; | ||
882 | } | ||
883 | /* | ||
884 | * Reject error frames with the exception of | ||
885 | * decryption and MIC failures. For monitor mode, | ||
886 | * we also ignore the CRC error. | ||
887 | */ | ||
888 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | ||
889 | if (rx_stats->rs_status & | ||
890 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | ||
891 | ATH9K_RXERR_CRC)) | ||
892 | return false; | ||
893 | } else { | ||
894 | if (rx_stats->rs_status & | ||
895 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { | ||
896 | return false; | ||
897 | } | ||
898 | } | ||
899 | } | ||
900 | return true; | ||
901 | } | ||
902 | |||
903 | static int ath9k_process_rate(struct ath_common *common, | ||
904 | struct ieee80211_hw *hw, | ||
905 | struct ath_rx_status *rx_stats, | ||
906 | struct ieee80211_rx_status *rxs) | ||
907 | { | ||
908 | struct ieee80211_supported_band *sband; | ||
909 | enum ieee80211_band band; | ||
910 | unsigned int i = 0; | ||
911 | |||
912 | band = hw->conf.channel->band; | ||
913 | sband = hw->wiphy->bands[band]; | ||
914 | |||
915 | if (rx_stats->rs_rate & 0x80) { | ||
916 | /* HT rate */ | ||
917 | rxs->flag |= RX_FLAG_HT; | ||
918 | if (rx_stats->rs_flags & ATH9K_RX_2040) | ||
919 | rxs->flag |= RX_FLAG_40MHZ; | ||
920 | if (rx_stats->rs_flags & ATH9K_RX_GI) | ||
921 | rxs->flag |= RX_FLAG_SHORT_GI; | ||
922 | rxs->rate_idx = rx_stats->rs_rate & 0x7f; | ||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | for (i = 0; i < sband->n_bitrates; i++) { | ||
927 | if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { | ||
928 | rxs->rate_idx = i; | ||
929 | return 0; | ||
930 | } | ||
931 | if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { | ||
932 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
933 | rxs->rate_idx = i; | ||
934 | return 0; | ||
935 | } | ||
936 | } | ||
937 | |||
938 | /* | ||
939 | * No valid hardware bitrate found -- we should not get here | ||
940 | * because hardware has already validated this frame as OK. | ||
941 | */ | ||
942 | ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " | ||
943 | "0x%02x using 1 Mbit\n", rx_stats->rs_rate); | ||
944 | |||
945 | return -EINVAL; | ||
946 | } | ||
947 | |||
948 | static void ath9k_process_rssi(struct ath_common *common, | ||
949 | struct ieee80211_hw *hw, | ||
950 | struct ieee80211_hdr *hdr, | ||
951 | struct ath_rx_status *rx_stats) | ||
952 | { | ||
953 | struct ath_hw *ah = common->ah; | ||
954 | struct ieee80211_sta *sta; | ||
955 | struct ath_node *an; | ||
956 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
957 | __le16 fc; | ||
958 | |||
959 | fc = hdr->frame_control; | ||
960 | |||
961 | rcu_read_lock(); | ||
962 | /* | ||
963 | * XXX: use ieee80211_find_sta! This requires quite a bit of work | ||
964 | * under the current ath9k virtual wiphy implementation as we have | ||
965 | * no way of tying a vif to wiphy. Typically vifs are attached to | ||
966 | * at least one sdata of a wiphy on mac80211 but with ath9k virtual | ||
967 | * wiphy you'd have to iterate over every wiphy and each sdata. | ||
968 | */ | ||
969 | sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); | ||
970 | if (sta) { | ||
971 | an = (struct ath_node *) sta->drv_priv; | ||
972 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && | ||
973 | !rx_stats->rs_moreaggr) | ||
974 | ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); | ||
975 | last_rssi = an->last_rssi; | ||
976 | } | ||
977 | rcu_read_unlock(); | ||
978 | |||
979 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
980 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, | ||
981 | ATH_RSSI_EP_MULTIPLIER); | ||
982 | if (rx_stats->rs_rssi < 0) | ||
983 | rx_stats->rs_rssi = 0; | ||
984 | |||
985 | /* Update Beacon RSSI, this is used by ANI. */ | ||
986 | if (ieee80211_is_beacon(fc)) | ||
987 | ah->stats.avgbrssi = rx_stats->rs_rssi; | ||
988 | } | ||
989 | |||
990 | /* | ||
991 | * For Decrypt or Demic errors, we only mark packet status here and always push | ||
992 | * up the frame up to let mac80211 handle the actual error case, be it no | ||
993 | * decryption key or real decryption error. This let us keep statistics there. | ||
994 | */ | ||
995 | static int ath9k_rx_skb_preprocess(struct ath_common *common, | ||
996 | struct ieee80211_hw *hw, | ||
997 | struct ieee80211_hdr *hdr, | ||
998 | struct ath_rx_status *rx_stats, | ||
999 | struct ieee80211_rx_status *rx_status, | ||
1000 | bool *decrypt_error) | ||
1001 | { | ||
1002 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | ||
1003 | |||
1004 | /* | ||
1005 | * everything but the rate is checked here, the rate check is done | ||
1006 | * separately to avoid doing two lookups for a rate for each frame. | ||
1007 | */ | ||
1008 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) | ||
1009 | return -EINVAL; | ||
1010 | |||
1011 | ath9k_process_rssi(common, hw, hdr, rx_stats); | ||
1012 | |||
1013 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | rx_status->band = hw->conf.channel->band; | ||
1017 | rx_status->freq = hw->conf.channel->center_freq; | ||
1018 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; | ||
1019 | rx_status->antenna = rx_stats->rs_antenna; | ||
1020 | rx_status->flag |= RX_FLAG_TSFT; | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | static void ath9k_rx_skb_postprocess(struct ath_common *common, | ||
1026 | struct sk_buff *skb, | ||
1027 | struct ath_rx_status *rx_stats, | ||
1028 | struct ieee80211_rx_status *rxs, | ||
1029 | bool decrypt_error) | ||
1030 | { | ||
1031 | struct ath_hw *ah = common->ah; | ||
1032 | struct ieee80211_hdr *hdr; | ||
1033 | int hdrlen, padpos, padsize; | ||
1034 | u8 keyix; | ||
1035 | __le16 fc; | ||
1036 | |||
1037 | /* see if any padding is done by the hw and remove it */ | ||
1038 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1039 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1040 | fc = hdr->frame_control; | ||
1041 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
1042 | |||
1043 | /* The MAC header is padded to have 32-bit boundary if the | ||
1044 | * packet payload is non-zero. The general calculation for | ||
1045 | * padsize would take into account odd header lengths: | ||
1046 | * padsize = (4 - padpos % 4) % 4; However, since only | ||
1047 | * even-length headers are used, padding can only be 0 or 2 | ||
1048 | * bytes and we can optimize this a bit. In addition, we must | ||
1049 | * not try to remove padding from short control frames that do | ||
1050 | * not have payload. */ | ||
1051 | padsize = padpos & 3; | ||
1052 | if (padsize && skb->len>=padpos+padsize+FCS_LEN) { | ||
1053 | memmove(skb->data + padsize, skb->data, padpos); | ||
1054 | skb_pull(skb, padsize); | ||
1055 | } | ||
1056 | |||
1057 | keyix = rx_stats->rs_keyix; | ||
1058 | |||
1059 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && | ||
1060 | ieee80211_has_protected(fc)) { | ||
1061 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
1062 | } else if (ieee80211_has_protected(fc) | ||
1063 | && !decrypt_error && skb->len >= hdrlen + 4) { | ||
1064 | keyix = skb->data[hdrlen + 3] >> 6; | ||
1065 | |||
1066 | if (test_bit(keyix, common->keymap)) | ||
1067 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
1068 | } | ||
1069 | if (ah->sw_mgmt_crypto && | ||
1070 | (rxs->flag & RX_FLAG_DECRYPTED) && | ||
1071 | ieee80211_is_mgmt(fc)) | ||
1072 | /* Use software decrypt for management frames. */ | ||
1073 | rxs->flag &= ~RX_FLAG_DECRYPTED; | ||
1074 | } | ||
824 | 1075 | ||
825 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1076 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
826 | { | 1077 | { |
@@ -842,15 +1093,21 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
842 | enum ath9k_rx_qtype qtype; | 1093 | enum ath9k_rx_qtype qtype; |
843 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); | 1094 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); |
844 | int dma_type; | 1095 | int dma_type; |
1096 | u8 rx_status_len = ah->caps.rx_status_len; | ||
1097 | u64 tsf = 0; | ||
1098 | u32 tsf_lower = 0; | ||
845 | 1099 | ||
846 | if (edma) | 1100 | if (edma) |
847 | dma_type = DMA_FROM_DEVICE; | ||
848 | else | ||
849 | dma_type = DMA_BIDIRECTIONAL; | 1101 | dma_type = DMA_BIDIRECTIONAL; |
1102 | else | ||
1103 | dma_type = DMA_FROM_DEVICE; | ||
850 | 1104 | ||
851 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; | 1105 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; |
852 | spin_lock_bh(&sc->rx.rxbuflock); | 1106 | spin_lock_bh(&sc->rx.rxbuflock); |
853 | 1107 | ||
1108 | tsf = ath9k_hw_gettsf64(ah); | ||
1109 | tsf_lower = tsf & 0xffffffff; | ||
1110 | |||
854 | do { | 1111 | do { |
855 | /* If handling rx interrupt and flush is in progress => exit */ | 1112 | /* If handling rx interrupt and flush is in progress => exit */ |
856 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) | 1113 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) |
@@ -869,7 +1126,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
869 | if (!skb) | 1126 | if (!skb) |
870 | continue; | 1127 | continue; |
871 | 1128 | ||
872 | hdr = (struct ieee80211_hdr *) skb->data; | 1129 | hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); |
873 | rxs = IEEE80211_SKB_RXCB(skb); | 1130 | rxs = IEEE80211_SKB_RXCB(skb); |
874 | 1131 | ||
875 | hw = ath_get_virt_hw(sc, hdr); | 1132 | hw = ath_get_virt_hw(sc, hdr); |
@@ -883,8 +1140,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
883 | if (flush) | 1140 | if (flush) |
884 | goto requeue; | 1141 | goto requeue; |
885 | 1142 | ||
886 | retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs, | 1143 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
887 | rxs, &decrypt_error); | 1144 | if (rs.rs_tstamp > tsf_lower && |
1145 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) | ||
1146 | rxs->mactime -= 0x100000000ULL; | ||
1147 | |||
1148 | if (rs.rs_tstamp < tsf_lower && | ||
1149 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | ||
1150 | rxs->mactime += 0x100000000ULL; | ||
1151 | |||
1152 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1153 | rxs, &decrypt_error); | ||
888 | if (retval) | 1154 | if (retval) |
889 | goto requeue; | 1155 | goto requeue; |
890 | 1156 | ||
@@ -908,8 +1174,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
908 | if (ah->caps.rx_status_len) | 1174 | if (ah->caps.rx_status_len) |
909 | skb_pull(skb, ah->caps.rx_status_len); | 1175 | skb_pull(skb, ah->caps.rx_status_len); |
910 | 1176 | ||
911 | ath9k_cmn_rx_skb_postprocess(common, skb, &rs, | 1177 | ath9k_rx_skb_postprocess(common, skb, &rs, |
912 | rxs, decrypt_error); | 1178 | rxs, decrypt_error); |
913 | 1179 | ||
914 | /* We will now give hardware our shiny new allocated skb */ | 1180 | /* We will now give hardware our shiny new allocated skb */ |
915 | bf->bf_mpdu = requeue_skb; | 1181 | bf->bf_mpdu = requeue_skb; |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d4371a43bdaa..47be667fe4ff 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -222,6 +222,7 @@ | |||
222 | 222 | ||
223 | #define AR_ISR_S2 0x008c | 223 | #define AR_ISR_S2 0x008c |
224 | #define AR_ISR_S2_QCU_TXURN 0x000003FF | 224 | #define AR_ISR_S2_QCU_TXURN 0x000003FF |
225 | #define AR_ISR_S2_BB_WATCHDOG 0x00010000 | ||
225 | #define AR_ISR_S2_CST 0x00400000 | 226 | #define AR_ISR_S2_CST 0x00400000 |
226 | #define AR_ISR_S2_GTT 0x00800000 | 227 | #define AR_ISR_S2_GTT 0x00800000 |
227 | #define AR_ISR_S2_TIM 0x01000000 | 228 | #define AR_ISR_S2_TIM 0x01000000 |
@@ -699,7 +700,15 @@ | |||
699 | #define AR_RC_HOSTIF 0x00000100 | 700 | #define AR_RC_HOSTIF 0x00000100 |
700 | 701 | ||
701 | #define AR_WA 0x4004 | 702 | #define AR_WA 0x4004 |
703 | #define AR_WA_BIT6 (1 << 6) | ||
704 | #define AR_WA_BIT7 (1 << 7) | ||
705 | #define AR_WA_BIT23 (1 << 23) | ||
702 | #define AR_WA_D3_L1_DISABLE (1 << 14) | 706 | #define AR_WA_D3_L1_DISABLE (1 << 14) |
707 | #define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16) | ||
708 | #define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17) | ||
709 | #define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */ | ||
710 | #define AR_WA_ANALOG_SHIFT (1 << 20) | ||
711 | #define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */ | ||
703 | #define AR9285_WA_DEFAULT 0x004a050b | 712 | #define AR9285_WA_DEFAULT 0x004a050b |
704 | #define AR9280_WA_DEFAULT 0x0040073b | 713 | #define AR9280_WA_DEFAULT 0x0040073b |
705 | #define AR_WA_DEFAULT 0x0000073f | 714 | #define AR_WA_DEFAULT 0x0000073f |
@@ -756,32 +765,33 @@ | |||
756 | #define AR_SREV_REVISION2 0x00000F00 | 765 | #define AR_SREV_REVISION2 0x00000F00 |
757 | #define AR_SREV_REVISION2_S 8 | 766 | #define AR_SREV_REVISION2_S 8 |
758 | 767 | ||
759 | #define AR_SREV_VERSION_5416_PCI 0xD | 768 | #define AR_SREV_VERSION_5416_PCI 0xD |
760 | #define AR_SREV_VERSION_5416_PCIE 0xC | 769 | #define AR_SREV_VERSION_5416_PCIE 0xC |
761 | #define AR_SREV_REVISION_5416_10 0 | 770 | #define AR_SREV_REVISION_5416_10 0 |
762 | #define AR_SREV_REVISION_5416_20 1 | 771 | #define AR_SREV_REVISION_5416_20 1 |
763 | #define AR_SREV_REVISION_5416_22 2 | 772 | #define AR_SREV_REVISION_5416_22 2 |
764 | #define AR_SREV_VERSION_9100 0x14 | 773 | #define AR_SREV_VERSION_9100 0x14 |
765 | #define AR_SREV_VERSION_9160 0x40 | 774 | #define AR_SREV_VERSION_9160 0x40 |
766 | #define AR_SREV_REVISION_9160_10 0 | 775 | #define AR_SREV_REVISION_9160_10 0 |
767 | #define AR_SREV_REVISION_9160_11 1 | 776 | #define AR_SREV_REVISION_9160_11 1 |
768 | #define AR_SREV_VERSION_9280 0x80 | 777 | #define AR_SREV_VERSION_9280 0x80 |
769 | #define AR_SREV_REVISION_9280_10 0 | 778 | #define AR_SREV_REVISION_9280_10 0 |
770 | #define AR_SREV_REVISION_9280_20 1 | 779 | #define AR_SREV_REVISION_9280_20 1 |
771 | #define AR_SREV_REVISION_9280_21 2 | 780 | #define AR_SREV_REVISION_9280_21 2 |
772 | #define AR_SREV_VERSION_9285 0xC0 | 781 | #define AR_SREV_VERSION_9285 0xC0 |
773 | #define AR_SREV_REVISION_9285_10 0 | 782 | #define AR_SREV_REVISION_9285_10 0 |
774 | #define AR_SREV_REVISION_9285_11 1 | 783 | #define AR_SREV_REVISION_9285_11 1 |
775 | #define AR_SREV_REVISION_9285_12 2 | 784 | #define AR_SREV_REVISION_9285_12 2 |
776 | #define AR_SREV_VERSION_9287 0x180 | 785 | #define AR_SREV_VERSION_9287 0x180 |
777 | #define AR_SREV_REVISION_9287_10 0 | 786 | #define AR_SREV_REVISION_9287_10 0 |
778 | #define AR_SREV_REVISION_9287_11 1 | 787 | #define AR_SREV_REVISION_9287_11 1 |
779 | #define AR_SREV_REVISION_9287_12 2 | 788 | #define AR_SREV_REVISION_9287_12 2 |
780 | #define AR_SREV_VERSION_9271 0x140 | 789 | #define AR_SREV_REVISION_9287_13 3 |
781 | #define AR_SREV_REVISION_9271_10 0 | 790 | #define AR_SREV_VERSION_9271 0x140 |
782 | #define AR_SREV_REVISION_9271_11 1 | 791 | #define AR_SREV_REVISION_9271_10 0 |
783 | #define AR_SREV_VERSION_9300 0x1c0 | 792 | #define AR_SREV_REVISION_9271_11 1 |
784 | #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ | 793 | #define AR_SREV_VERSION_9300 0x1c0 |
794 | #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ | ||
785 | 795 | ||
786 | #define AR_SREV_5416(_ah) \ | 796 | #define AR_SREV_5416(_ah) \ |
787 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 797 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
@@ -859,6 +869,11 @@ | |||
859 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ | 869 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ |
860 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | 870 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ |
861 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12))) | 871 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12))) |
872 | #define AR_SREV_9287_13_OR_LATER(_ah) \ | ||
873 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ | ||
874 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
875 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_13))) | ||
876 | |||
862 | #define AR_SREV_9271(_ah) \ | 877 | #define AR_SREV_9271(_ah) \ |
863 | (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) | 878 | (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) |
864 | #define AR_SREV_9271_10(_ah) \ | 879 | #define AR_SREV_9271_10(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 105ad40968f6..89423ca23d2c 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -219,7 +219,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | |||
219 | info->control.rates[1].idx = -1; | 219 | info->control.rates[1].idx = -1; |
220 | 220 | ||
221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | 221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); |
222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; | 222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; |
223 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; | 223 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; |
224 | 224 | ||
225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | 225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index e23172c9caaf..6260faa658a2 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -279,9 +279,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
279 | if (wmi->drv_priv->op_flags & OP_UNPLUGGED) | 279 | if (wmi->drv_priv->op_flags & OP_UNPLUGGED) |
280 | return 0; | 280 | return 0; |
281 | 281 | ||
282 | if (!wmi) | ||
283 | return -EINVAL; | ||
284 | |||
285 | skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); | 282 | skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); |
286 | if (!skb) | 283 | if (!skb) |
287 | return -ENOMEM; | 284 | return -ENOMEM; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 859aa4ab0769..c41185b28c0a 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -941,6 +941,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
941 | if (!ATH_TXQ_SETUP(sc, qnum)) { | 941 | if (!ATH_TXQ_SETUP(sc, qnum)) { |
942 | struct ath_txq *txq = &sc->tx.txq[qnum]; | 942 | struct ath_txq *txq = &sc->tx.txq[qnum]; |
943 | 943 | ||
944 | txq->axq_class = subtype; | ||
944 | txq->axq_qnum = qnum; | 945 | txq->axq_qnum = qnum; |
945 | txq->axq_link = NULL; | 946 | txq->axq_link = NULL; |
946 | INIT_LIST_HEAD(&txq->axq_q); | 947 | INIT_LIST_HEAD(&txq->axq_q); |
@@ -958,58 +959,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
958 | return &sc->tx.txq[qnum]; | 959 | return &sc->tx.txq[qnum]; |
959 | } | 960 | } |
960 | 961 | ||
961 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) | ||
962 | { | ||
963 | int qnum; | ||
964 | |||
965 | switch (qtype) { | ||
966 | case ATH9K_TX_QUEUE_DATA: | ||
967 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { | ||
968 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | ||
969 | "HAL AC %u out of range, max %zu!\n", | ||
970 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); | ||
971 | return -1; | ||
972 | } | ||
973 | qnum = sc->tx.hwq_map[haltype]; | ||
974 | break; | ||
975 | case ATH9K_TX_QUEUE_BEACON: | ||
976 | qnum = sc->beacon.beaconq; | ||
977 | break; | ||
978 | case ATH9K_TX_QUEUE_CAB: | ||
979 | qnum = sc->beacon.cabq->axq_qnum; | ||
980 | break; | ||
981 | default: | ||
982 | qnum = -1; | ||
983 | } | ||
984 | return qnum; | ||
985 | } | ||
986 | |||
987 | struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) | ||
988 | { | ||
989 | struct ath_txq *txq = NULL; | ||
990 | u16 skb_queue = skb_get_queue_mapping(skb); | ||
991 | int qnum; | ||
992 | |||
993 | qnum = ath_get_hal_qnum(skb_queue, sc); | ||
994 | txq = &sc->tx.txq[qnum]; | ||
995 | |||
996 | spin_lock_bh(&txq->axq_lock); | ||
997 | |||
998 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { | ||
999 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT, | ||
1000 | "TX queue: %d is full, depth: %d\n", | ||
1001 | qnum, txq->axq_depth); | ||
1002 | ath_mac80211_stop_queue(sc, skb_queue); | ||
1003 | txq->stopped = 1; | ||
1004 | spin_unlock_bh(&txq->axq_lock); | ||
1005 | return NULL; | ||
1006 | } | ||
1007 | |||
1008 | spin_unlock_bh(&txq->axq_lock); | ||
1009 | |||
1010 | return txq; | ||
1011 | } | ||
1012 | |||
1013 | int ath_txq_update(struct ath_softc *sc, int qnum, | 962 | int ath_txq_update(struct ath_softc *sc, int qnum, |
1014 | struct ath9k_tx_queue_info *qinfo) | 963 | struct ath9k_tx_queue_info *qinfo) |
1015 | { | 964 | { |
@@ -1688,12 +1637,15 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1688 | bf->bf_frmlen -= padsize; | 1637 | bf->bf_frmlen -= padsize; |
1689 | } | 1638 | } |
1690 | 1639 | ||
1691 | if (conf_is_ht(&hw->conf)) { | 1640 | if (!txctl->paprd && conf_is_ht(&hw->conf)) { |
1692 | bf->bf_state.bf_type |= BUF_HT; | 1641 | bf->bf_state.bf_type |= BUF_HT; |
1693 | if (tx_info->flags & IEEE80211_TX_CTL_LDPC) | 1642 | if (tx_info->flags & IEEE80211_TX_CTL_LDPC) |
1694 | use_ldpc = true; | 1643 | use_ldpc = true; |
1695 | } | 1644 | } |
1696 | 1645 | ||
1646 | bf->bf_state.bfs_paprd = txctl->paprd; | ||
1647 | if (txctl->paprd) | ||
1648 | bf->bf_state.bfs_paprd_timestamp = jiffies; | ||
1697 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); | 1649 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); |
1698 | 1650 | ||
1699 | bf->bf_keytype = get_hw_crypto_keytype(skb); | 1651 | bf->bf_keytype = get_hw_crypto_keytype(skb); |
@@ -1768,6 +1720,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1768 | bf->bf_buf_addr, | 1720 | bf->bf_buf_addr, |
1769 | txctl->txq->axq_qnum); | 1721 | txctl->txq->axq_qnum); |
1770 | 1722 | ||
1723 | if (bf->bf_state.bfs_paprd) | ||
1724 | ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd); | ||
1725 | |||
1771 | spin_lock_bh(&txctl->txq->axq_lock); | 1726 | spin_lock_bh(&txctl->txq->axq_lock); |
1772 | 1727 | ||
1773 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && | 1728 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && |
@@ -1809,8 +1764,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1809 | struct ath_wiphy *aphy = hw->priv; | 1764 | struct ath_wiphy *aphy = hw->priv; |
1810 | struct ath_softc *sc = aphy->sc; | 1765 | struct ath_softc *sc = aphy->sc; |
1811 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1766 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1767 | struct ath_txq *txq = txctl->txq; | ||
1812 | struct ath_buf *bf; | 1768 | struct ath_buf *bf; |
1813 | int r; | 1769 | int q, r; |
1814 | 1770 | ||
1815 | bf = ath_tx_get_buffer(sc); | 1771 | bf = ath_tx_get_buffer(sc); |
1816 | if (!bf) { | 1772 | if (!bf) { |
@@ -1820,8 +1776,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1820 | 1776 | ||
1821 | r = ath_tx_setup_buffer(hw, bf, skb, txctl); | 1777 | r = ath_tx_setup_buffer(hw, bf, skb, txctl); |
1822 | if (unlikely(r)) { | 1778 | if (unlikely(r)) { |
1823 | struct ath_txq *txq = txctl->txq; | ||
1824 | |||
1825 | ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); | 1779 | ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); |
1826 | 1780 | ||
1827 | /* upon ath_tx_processq() this TX queue will be resumed, we | 1781 | /* upon ath_tx_processq() this TX queue will be resumed, we |
@@ -1829,7 +1783,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1829 | * we will at least have to run TX completionon one buffer | 1783 | * we will at least have to run TX completionon one buffer |
1830 | * on the queue */ | 1784 | * on the queue */ |
1831 | spin_lock_bh(&txq->axq_lock); | 1785 | spin_lock_bh(&txq->axq_lock); |
1832 | if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { | 1786 | if (!txq->stopped && txq->axq_depth > 1) { |
1833 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); | 1787 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); |
1834 | txq->stopped = 1; | 1788 | txq->stopped = 1; |
1835 | } | 1789 | } |
@@ -1840,6 +1794,17 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1840 | return r; | 1794 | return r; |
1841 | } | 1795 | } |
1842 | 1796 | ||
1797 | q = skb_get_queue_mapping(skb); | ||
1798 | if (q >= 4) | ||
1799 | q = 0; | ||
1800 | |||
1801 | spin_lock_bh(&txq->axq_lock); | ||
1802 | if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { | ||
1803 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); | ||
1804 | txq->stopped = 1; | ||
1805 | } | ||
1806 | spin_unlock_bh(&txq->axq_lock); | ||
1807 | |||
1843 | ath_tx_start_dma(sc, bf, txctl); | 1808 | ath_tx_start_dma(sc, bf, txctl); |
1844 | 1809 | ||
1845 | return 0; | 1810 | return 0; |
@@ -1909,7 +1874,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1909 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1874 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1910 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1875 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1911 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | 1876 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; |
1912 | int padpos, padsize; | 1877 | int q, padpos, padsize; |
1913 | 1878 | ||
1914 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1879 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1915 | 1880 | ||
@@ -1948,8 +1913,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1948 | 1913 | ||
1949 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) | 1914 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) |
1950 | ath9k_tx_status(hw, skb); | 1915 | ath9k_tx_status(hw, skb); |
1951 | else | 1916 | else { |
1917 | q = skb_get_queue_mapping(skb); | ||
1918 | if (q >= 4) | ||
1919 | q = 0; | ||
1920 | |||
1921 | if (--sc->tx.pending_frames[q] < 0) | ||
1922 | sc->tx.pending_frames[q] = 0; | ||
1923 | |||
1952 | ieee80211_tx_status(hw, skb); | 1924 | ieee80211_tx_status(hw, skb); |
1925 | } | ||
1953 | } | 1926 | } |
1954 | 1927 | ||
1955 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1928 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
@@ -1971,8 +1944,18 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1971 | } | 1944 | } |
1972 | 1945 | ||
1973 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1946 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1974 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | 1947 | |
1975 | ath_debug_stat_tx(sc, txq, bf, ts); | 1948 | if (bf->bf_state.bfs_paprd) { |
1949 | if (time_after(jiffies, | ||
1950 | bf->bf_state.bfs_paprd_timestamp + | ||
1951 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) | ||
1952 | dev_kfree_skb_any(skb); | ||
1953 | else | ||
1954 | complete(&sc->paprd_complete); | ||
1955 | } else { | ||
1956 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | ||
1957 | ath_debug_stat_tx(sc, txq, bf, ts); | ||
1958 | } | ||
1976 | 1959 | ||
1977 | /* | 1960 | /* |
1978 | * Return the list of ath_buf of this mpdu to free queue | 1961 | * Return the list of ath_buf of this mpdu to free queue |
@@ -2057,14 +2040,14 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | |||
2057 | { | 2040 | { |
2058 | int qnum; | 2041 | int qnum; |
2059 | 2042 | ||
2043 | qnum = ath_get_mac80211_qnum(txq->axq_class, sc); | ||
2044 | if (qnum == -1) | ||
2045 | return; | ||
2046 | |||
2060 | spin_lock_bh(&txq->axq_lock); | 2047 | spin_lock_bh(&txq->axq_lock); |
2061 | if (txq->stopped && | 2048 | if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { |
2062 | sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) { | 2049 | ath_mac80211_start_queue(sc, qnum); |
2063 | qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); | 2050 | txq->stopped = 0; |
2064 | if (qnum != -1) { | ||
2065 | ath_mac80211_start_queue(sc, qnum); | ||
2066 | txq->stopped = 0; | ||
2067 | } | ||
2068 | } | 2051 | } |
2069 | spin_unlock_bh(&txq->axq_lock); | 2052 | spin_unlock_bh(&txq->axq_lock); |
2070 | } | 2053 | } |
@@ -2279,6 +2262,17 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2279 | 2262 | ||
2280 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); | 2263 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); |
2281 | 2264 | ||
2265 | /* | ||
2266 | * Make sure null func frame is acked before configuring | ||
2267 | * hw into ps mode. | ||
2268 | */ | ||
2269 | if (bf->bf_isnullfunc && txok) { | ||
2270 | if ((sc->ps_flags & PS_ENABLED)) | ||
2271 | ath9k_enable_ps(sc); | ||
2272 | else | ||
2273 | sc->ps_flags |= PS_NULLFUNC_COMPLETED; | ||
2274 | } | ||
2275 | |||
2282 | if (!bf_isampdu(bf)) { | 2276 | if (!bf_isampdu(bf)) { |
2283 | bf->bf_retries = txs.ts_longretry; | 2277 | bf->bf_retries = txs.ts_longretry; |
2284 | if (txs.ts_status & ATH9K_TXERR_XRETRY) | 2278 | if (txs.ts_status & ATH9K_TXERR_XRETRY) |
@@ -2424,26 +2418,8 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2424 | for (acno = 0, ac = &an->ac[acno]; | 2418 | for (acno = 0, ac = &an->ac[acno]; |
2425 | acno < WME_NUM_AC; acno++, ac++) { | 2419 | acno < WME_NUM_AC; acno++, ac++) { |
2426 | ac->sched = false; | 2420 | ac->sched = false; |
2421 | ac->qnum = sc->tx.hwq_map[acno]; | ||
2427 | INIT_LIST_HEAD(&ac->tid_q); | 2422 | INIT_LIST_HEAD(&ac->tid_q); |
2428 | |||
2429 | switch (acno) { | ||
2430 | case WME_AC_BE: | ||
2431 | ac->qnum = ath_tx_get_qnum(sc, | ||
2432 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
2433 | break; | ||
2434 | case WME_AC_BK: | ||
2435 | ac->qnum = ath_tx_get_qnum(sc, | ||
2436 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); | ||
2437 | break; | ||
2438 | case WME_AC_VI: | ||
2439 | ac->qnum = ath_tx_get_qnum(sc, | ||
2440 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); | ||
2441 | break; | ||
2442 | case WME_AC_VO: | ||
2443 | ac->qnum = ath_tx_get_qnum(sc, | ||
2444 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); | ||
2445 | break; | ||
2446 | } | ||
2447 | } | 2423 | } |
2448 | } | 2424 | } |
2449 | 2425 | ||
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index fa40fdfea719..10d0aaf754c5 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -333,11 +333,11 @@ static inline | |||
333 | dma_addr_t dmaaddr; | 333 | dma_addr_t dmaaddr; |
334 | 334 | ||
335 | if (tx) { | 335 | if (tx) { |
336 | dmaaddr = ssb_dma_map_single(ring->dev->dev, | 336 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, |
337 | buf, len, DMA_TO_DEVICE); | 337 | buf, len, DMA_TO_DEVICE); |
338 | } else { | 338 | } else { |
339 | dmaaddr = ssb_dma_map_single(ring->dev->dev, | 339 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, |
340 | buf, len, DMA_FROM_DEVICE); | 340 | buf, len, DMA_FROM_DEVICE); |
341 | } | 341 | } |
342 | 342 | ||
343 | return dmaaddr; | 343 | return dmaaddr; |
@@ -348,11 +348,11 @@ static inline | |||
348 | dma_addr_t addr, size_t len, int tx) | 348 | dma_addr_t addr, size_t len, int tx) |
349 | { | 349 | { |
350 | if (tx) { | 350 | if (tx) { |
351 | ssb_dma_unmap_single(ring->dev->dev, | 351 | dma_unmap_single(ring->dev->dev->dma_dev, |
352 | addr, len, DMA_TO_DEVICE); | 352 | addr, len, DMA_TO_DEVICE); |
353 | } else { | 353 | } else { |
354 | ssb_dma_unmap_single(ring->dev->dev, | 354 | dma_unmap_single(ring->dev->dev->dma_dev, |
355 | addr, len, DMA_FROM_DEVICE); | 355 | addr, len, DMA_FROM_DEVICE); |
356 | } | 356 | } |
357 | } | 357 | } |
358 | 358 | ||
@@ -361,7 +361,7 @@ static inline | |||
361 | dma_addr_t addr, size_t len) | 361 | dma_addr_t addr, size_t len) |
362 | { | 362 | { |
363 | B43_WARN_ON(ring->tx); | 363 | B43_WARN_ON(ring->tx); |
364 | ssb_dma_sync_single_for_cpu(ring->dev->dev, | 364 | dma_sync_single_for_cpu(ring->dev->dev->dma_dev, |
365 | addr, len, DMA_FROM_DEVICE); | 365 | addr, len, DMA_FROM_DEVICE); |
366 | } | 366 | } |
367 | 367 | ||
@@ -370,8 +370,8 @@ static inline | |||
370 | dma_addr_t addr, size_t len) | 370 | dma_addr_t addr, size_t len) |
371 | { | 371 | { |
372 | B43_WARN_ON(ring->tx); | 372 | B43_WARN_ON(ring->tx); |
373 | ssb_dma_sync_single_for_device(ring->dev->dev, | 373 | dma_sync_single_for_device(ring->dev->dev->dma_dev, |
374 | addr, len, DMA_FROM_DEVICE); | 374 | addr, len, DMA_FROM_DEVICE); |
375 | } | 375 | } |
376 | 376 | ||
377 | static inline | 377 | static inline |
@@ -401,9 +401,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring) | |||
401 | */ | 401 | */ |
402 | if (ring->type == B43_DMA_64BIT) | 402 | if (ring->type == B43_DMA_64BIT) |
403 | flags |= GFP_DMA; | 403 | flags |= GFP_DMA; |
404 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, | 404 | ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, |
405 | B43_DMA_RINGMEMSIZE, | 405 | B43_DMA_RINGMEMSIZE, |
406 | &(ring->dmabase), flags); | 406 | &(ring->dmabase), flags); |
407 | if (!ring->descbase) { | 407 | if (!ring->descbase) { |
408 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); | 408 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); |
409 | return -ENOMEM; | 409 | return -ENOMEM; |
@@ -420,8 +420,8 @@ static void free_ringmemory(struct b43_dmaring *ring) | |||
420 | if (ring->type == B43_DMA_64BIT) | 420 | if (ring->type == B43_DMA_64BIT) |
421 | flags |= GFP_DMA; | 421 | flags |= GFP_DMA; |
422 | 422 | ||
423 | ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, | 423 | dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, |
424 | ring->descbase, ring->dmabase, flags); | 424 | ring->descbase, ring->dmabase); |
425 | } | 425 | } |
426 | 426 | ||
427 | /* Reset the RX DMA channel */ | 427 | /* Reset the RX DMA channel */ |
@@ -528,7 +528,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, | |||
528 | dma_addr_t addr, | 528 | dma_addr_t addr, |
529 | size_t buffersize, bool dma_to_device) | 529 | size_t buffersize, bool dma_to_device) |
530 | { | 530 | { |
531 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) | 531 | if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr))) |
532 | return 1; | 532 | return 1; |
533 | 533 | ||
534 | switch (ring->type) { | 534 | switch (ring->type) { |
@@ -874,10 +874,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
874 | goto err_kfree_meta; | 874 | goto err_kfree_meta; |
875 | 875 | ||
876 | /* test for ability to dma to txhdr_cache */ | 876 | /* test for ability to dma to txhdr_cache */ |
877 | dma_test = ssb_dma_map_single(dev->dev, | 877 | dma_test = dma_map_single(dev->dev->dma_dev, |
878 | ring->txhdr_cache, | 878 | ring->txhdr_cache, |
879 | b43_txhdr_size(dev), | 879 | b43_txhdr_size(dev), |
880 | DMA_TO_DEVICE); | 880 | DMA_TO_DEVICE); |
881 | 881 | ||
882 | if (b43_dma_mapping_error(ring, dma_test, | 882 | if (b43_dma_mapping_error(ring, dma_test, |
883 | b43_txhdr_size(dev), 1)) { | 883 | b43_txhdr_size(dev), 1)) { |
@@ -889,10 +889,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
889 | if (!ring->txhdr_cache) | 889 | if (!ring->txhdr_cache) |
890 | goto err_kfree_meta; | 890 | goto err_kfree_meta; |
891 | 891 | ||
892 | dma_test = ssb_dma_map_single(dev->dev, | 892 | dma_test = dma_map_single(dev->dev->dma_dev, |
893 | ring->txhdr_cache, | 893 | ring->txhdr_cache, |
894 | b43_txhdr_size(dev), | 894 | b43_txhdr_size(dev), |
895 | DMA_TO_DEVICE); | 895 | DMA_TO_DEVICE); |
896 | 896 | ||
897 | if (b43_dma_mapping_error(ring, dma_test, | 897 | if (b43_dma_mapping_error(ring, dma_test, |
898 | b43_txhdr_size(dev), 1)) { | 898 | b43_txhdr_size(dev), 1)) { |
@@ -903,9 +903,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
903 | } | 903 | } |
904 | } | 904 | } |
905 | 905 | ||
906 | ssb_dma_unmap_single(dev->dev, | 906 | dma_unmap_single(dev->dev->dma_dev, |
907 | dma_test, b43_txhdr_size(dev), | 907 | dma_test, b43_txhdr_size(dev), |
908 | DMA_TO_DEVICE); | 908 | DMA_TO_DEVICE); |
909 | } | 909 | } |
910 | 910 | ||
911 | err = alloc_ringmemory(ring); | 911 | err = alloc_ringmemory(ring); |
@@ -1018,9 +1018,12 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) | |||
1018 | /* Try to set the DMA mask. If it fails, try falling back to a | 1018 | /* Try to set the DMA mask. If it fails, try falling back to a |
1019 | * lower mask, as we can always also support a lower one. */ | 1019 | * lower mask, as we can always also support a lower one. */ |
1020 | while (1) { | 1020 | while (1) { |
1021 | err = ssb_dma_set_mask(dev->dev, mask); | 1021 | err = dma_set_mask(dev->dev->dma_dev, mask); |
1022 | if (!err) | 1022 | if (!err) { |
1023 | break; | 1023 | err = dma_set_coherent_mask(dev->dev->dma_dev, mask); |
1024 | if (!err) | ||
1025 | break; | ||
1026 | } | ||
1024 | if (mask == DMA_BIT_MASK(64)) { | 1027 | if (mask == DMA_BIT_MASK(64)) { |
1025 | mask = DMA_BIT_MASK(32); | 1028 | mask = DMA_BIT_MASK(32); |
1026 | fallback = 1; | 1029 | fallback = 1; |
@@ -1221,14 +1224,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1221 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1224 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1222 | /* create a bounce buffer in zone_dma on mapping failure. */ | 1225 | /* create a bounce buffer in zone_dma on mapping failure. */ |
1223 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { | 1226 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { |
1224 | priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA); | 1227 | priv_info->bouncebuffer = kmemdup(skb->data, skb->len, |
1228 | GFP_ATOMIC | GFP_DMA); | ||
1225 | if (!priv_info->bouncebuffer) { | 1229 | if (!priv_info->bouncebuffer) { |
1226 | ring->current_slot = old_top_slot; | 1230 | ring->current_slot = old_top_slot; |
1227 | ring->used_slots = old_used_slots; | 1231 | ring->used_slots = old_used_slots; |
1228 | err = -ENOMEM; | 1232 | err = -ENOMEM; |
1229 | goto out_unmap_hdr; | 1233 | goto out_unmap_hdr; |
1230 | } | 1234 | } |
1231 | memcpy(priv_info->bouncebuffer, skb->data, skb->len); | ||
1232 | 1235 | ||
1233 | meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1); | 1236 | meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1); |
1234 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { | 1237 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7965b70efbab..8e243798ae93 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1804,7 +1804,7 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1804 | dma_reason[2], dma_reason[3], | 1804 | dma_reason[2], dma_reason[3], |
1805 | dma_reason[4], dma_reason[5]); | 1805 | dma_reason[4], dma_reason[5]); |
1806 | b43err(dev->wl, "This device does not support DMA " | 1806 | b43err(dev->wl, "This device does not support DMA " |
1807 | "on your system. Please use PIO instead.\n"); | 1807 | "on your system. It will now be switched to PIO.\n"); |
1808 | /* Fall back to PIO transfers if we get fatal DMA errors! */ | 1808 | /* Fall back to PIO transfers if we get fatal DMA errors! */ |
1809 | dev->use_pio = 1; | 1809 | dev->use_pio = 1; |
1810 | b43_controller_restart(dev, "DMA error"); | 1810 | b43_controller_restart(dev, "DMA error"); |
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index e91520d0312e..e03e01d0bc35 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -394,11 +394,11 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring, | |||
394 | dma_addr_t dmaaddr; | 394 | dma_addr_t dmaaddr; |
395 | 395 | ||
396 | if (tx) | 396 | if (tx) |
397 | dmaaddr = ssb_dma_map_single(ring->dev->dev, | 397 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, |
398 | buf, len, | 398 | buf, len, |
399 | DMA_TO_DEVICE); | 399 | DMA_TO_DEVICE); |
400 | else | 400 | else |
401 | dmaaddr = ssb_dma_map_single(ring->dev->dev, | 401 | dmaaddr = dma_map_single(ring->dev->dev->dma_dev, |
402 | buf, len, | 402 | buf, len, |
403 | DMA_FROM_DEVICE); | 403 | DMA_FROM_DEVICE); |
404 | 404 | ||
@@ -412,11 +412,11 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring, | |||
412 | int tx) | 412 | int tx) |
413 | { | 413 | { |
414 | if (tx) | 414 | if (tx) |
415 | ssb_dma_unmap_single(ring->dev->dev, | 415 | dma_unmap_single(ring->dev->dev->dma_dev, |
416 | addr, len, | 416 | addr, len, |
417 | DMA_TO_DEVICE); | 417 | DMA_TO_DEVICE); |
418 | else | 418 | else |
419 | ssb_dma_unmap_single(ring->dev->dev, | 419 | dma_unmap_single(ring->dev->dev->dma_dev, |
420 | addr, len, | 420 | addr, len, |
421 | DMA_FROM_DEVICE); | 421 | DMA_FROM_DEVICE); |
422 | } | 422 | } |
@@ -428,8 +428,8 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring, | |||
428 | { | 428 | { |
429 | B43legacy_WARN_ON(ring->tx); | 429 | B43legacy_WARN_ON(ring->tx); |
430 | 430 | ||
431 | ssb_dma_sync_single_for_cpu(ring->dev->dev, | 431 | dma_sync_single_for_cpu(ring->dev->dev->dma_dev, |
432 | addr, len, DMA_FROM_DEVICE); | 432 | addr, len, DMA_FROM_DEVICE); |
433 | } | 433 | } |
434 | 434 | ||
435 | static inline | 435 | static inline |
@@ -439,8 +439,8 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring, | |||
439 | { | 439 | { |
440 | B43legacy_WARN_ON(ring->tx); | 440 | B43legacy_WARN_ON(ring->tx); |
441 | 441 | ||
442 | ssb_dma_sync_single_for_device(ring->dev->dev, | 442 | dma_sync_single_for_device(ring->dev->dev->dma_dev, |
443 | addr, len, DMA_FROM_DEVICE); | 443 | addr, len, DMA_FROM_DEVICE); |
444 | } | 444 | } |
445 | 445 | ||
446 | static inline | 446 | static inline |
@@ -460,10 +460,10 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring, | |||
460 | static int alloc_ringmemory(struct b43legacy_dmaring *ring) | 460 | static int alloc_ringmemory(struct b43legacy_dmaring *ring) |
461 | { | 461 | { |
462 | /* GFP flags must match the flags in free_ringmemory()! */ | 462 | /* GFP flags must match the flags in free_ringmemory()! */ |
463 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, | 463 | ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, |
464 | B43legacy_DMA_RINGMEMSIZE, | 464 | B43legacy_DMA_RINGMEMSIZE, |
465 | &(ring->dmabase), | 465 | &(ring->dmabase), |
466 | GFP_KERNEL); | 466 | GFP_KERNEL); |
467 | if (!ring->descbase) { | 467 | if (!ring->descbase) { |
468 | b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" | 468 | b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" |
469 | " failed\n"); | 469 | " failed\n"); |
@@ -476,8 +476,8 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring) | |||
476 | 476 | ||
477 | static void free_ringmemory(struct b43legacy_dmaring *ring) | 477 | static void free_ringmemory(struct b43legacy_dmaring *ring) |
478 | { | 478 | { |
479 | ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE, | 479 | dma_free_coherent(ring->dev->dev->dma_dev, B43legacy_DMA_RINGMEMSIZE, |
480 | ring->descbase, ring->dmabase, GFP_KERNEL); | 480 | ring->descbase, ring->dmabase); |
481 | } | 481 | } |
482 | 482 | ||
483 | /* Reset the RX DMA channel */ | 483 | /* Reset the RX DMA channel */ |
@@ -589,7 +589,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, | |||
589 | size_t buffersize, | 589 | size_t buffersize, |
590 | bool dma_to_device) | 590 | bool dma_to_device) |
591 | { | 591 | { |
592 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) | 592 | if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr))) |
593 | return 1; | 593 | return 1; |
594 | 594 | ||
595 | switch (ring->type) { | 595 | switch (ring->type) { |
@@ -906,7 +906,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
906 | goto err_kfree_meta; | 906 | goto err_kfree_meta; |
907 | 907 | ||
908 | /* test for ability to dma to txhdr_cache */ | 908 | /* test for ability to dma to txhdr_cache */ |
909 | dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache, | 909 | dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache, |
910 | sizeof(struct b43legacy_txhdr_fw3), | 910 | sizeof(struct b43legacy_txhdr_fw3), |
911 | DMA_TO_DEVICE); | 911 | DMA_TO_DEVICE); |
912 | 912 | ||
@@ -920,7 +920,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
920 | if (!ring->txhdr_cache) | 920 | if (!ring->txhdr_cache) |
921 | goto err_kfree_meta; | 921 | goto err_kfree_meta; |
922 | 922 | ||
923 | dma_test = ssb_dma_map_single(dev->dev, | 923 | dma_test = dma_map_single(dev->dev->dma_dev, |
924 | ring->txhdr_cache, | 924 | ring->txhdr_cache, |
925 | sizeof(struct b43legacy_txhdr_fw3), | 925 | sizeof(struct b43legacy_txhdr_fw3), |
926 | DMA_TO_DEVICE); | 926 | DMA_TO_DEVICE); |
@@ -930,9 +930,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | |||
930 | goto err_kfree_txhdr_cache; | 930 | goto err_kfree_txhdr_cache; |
931 | } | 931 | } |
932 | 932 | ||
933 | ssb_dma_unmap_single(dev->dev, dma_test, | 933 | dma_unmap_single(dev->dev->dma_dev, dma_test, |
934 | sizeof(struct b43legacy_txhdr_fw3), | 934 | sizeof(struct b43legacy_txhdr_fw3), |
935 | DMA_TO_DEVICE); | 935 | DMA_TO_DEVICE); |
936 | } | 936 | } |
937 | 937 | ||
938 | ring->nr_slots = nr_slots; | 938 | ring->nr_slots = nr_slots; |
@@ -1040,9 +1040,12 @@ static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask) | |||
1040 | /* Try to set the DMA mask. If it fails, try falling back to a | 1040 | /* Try to set the DMA mask. If it fails, try falling back to a |
1041 | * lower mask, as we can always also support a lower one. */ | 1041 | * lower mask, as we can always also support a lower one. */ |
1042 | while (1) { | 1042 | while (1) { |
1043 | err = ssb_dma_set_mask(dev->dev, mask); | 1043 | err = dma_set_mask(dev->dev->dma_dev, mask); |
1044 | if (!err) | 1044 | if (!err) { |
1045 | break; | 1045 | err = dma_set_coherent_mask(dev->dev->dma_dev, mask); |
1046 | if (!err) | ||
1047 | break; | ||
1048 | } | ||
1046 | if (mask == DMA_BIT_MASK(64)) { | 1049 | if (mask == DMA_BIT_MASK(64)) { |
1047 | mask = DMA_BIT_MASK(32); | 1050 | mask = DMA_BIT_MASK(32); |
1048 | fallback = 1; | 1051 | fallback = 1; |
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 231dbd77f5f5..9cadaa296fac 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
@@ -688,7 +688,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data) | |||
688 | struct ap_data *ap = data; | 688 | struct ap_data *ap = data; |
689 | struct net_device *dev = ap->local->dev; | 689 | struct net_device *dev = ap->local->dev; |
690 | struct ieee80211_hdr *hdr; | 690 | struct ieee80211_hdr *hdr; |
691 | u16 fc, status; | 691 | u16 status; |
692 | __le16 *pos; | 692 | __le16 *pos; |
693 | struct sta_info *sta = NULL; | 693 | struct sta_info *sta = NULL; |
694 | char *txt = NULL; | 694 | char *txt = NULL; |
@@ -699,7 +699,6 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data) | |||
699 | } | 699 | } |
700 | 700 | ||
701 | hdr = (struct ieee80211_hdr *) skb->data; | 701 | hdr = (struct ieee80211_hdr *) skb->data; |
702 | fc = le16_to_cpu(hdr->frame_control); | ||
703 | if ((!ieee80211_is_assoc_resp(hdr->frame_control) && | 702 | if ((!ieee80211_is_assoc_resp(hdr->frame_control) && |
704 | !ieee80211_is_reassoc_resp(hdr->frame_control)) || | 703 | !ieee80211_is_reassoc_resp(hdr->frame_control)) || |
705 | skb->len < IEEE80211_MGMT_HDR_LEN + 4) { | 704 | skb->len < IEEE80211_MGMT_HDR_LEN + 4) { |
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index eb57d1ea361f..eaee84b55887 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c | |||
@@ -741,9 +741,7 @@ void hostap_set_multicast_list_queue(struct work_struct *work) | |||
741 | local_info_t *local = | 741 | local_info_t *local = |
742 | container_of(work, local_info_t, set_multicast_list_queue); | 742 | container_of(work, local_info_t, set_multicast_list_queue); |
743 | struct net_device *dev = local->dev; | 743 | struct net_device *dev = local->dev; |
744 | struct hostap_interface *iface; | ||
745 | 744 | ||
746 | iface = netdev_priv(dev); | ||
747 | if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, | 745 | if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, |
748 | local->is_promisc)) { | 746 | local->is_promisc)) { |
749 | printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", | 747 | printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 0bd4dfa59a8a..18ebd602670d 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -3467,10 +3467,8 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) | |||
3467 | dma_addr_t p; | 3467 | dma_addr_t p; |
3468 | 3468 | ||
3469 | priv->msg_buffers = | 3469 | priv->msg_buffers = |
3470 | (struct ipw2100_tx_packet *)kmalloc(IPW_COMMAND_POOL_SIZE * | 3470 | kmalloc(IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet), |
3471 | sizeof(struct | 3471 | GFP_KERNEL); |
3472 | ipw2100_tx_packet), | ||
3473 | GFP_KERNEL); | ||
3474 | if (!priv->msg_buffers) { | 3472 | if (!priv->msg_buffers) { |
3475 | printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg " | 3473 | printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg " |
3476 | "buffers.\n", priv->net_dev->name); | 3474 | "buffers.\n", priv->net_dev->name); |
@@ -4499,10 +4497,8 @@ static int ipw2100_tx_allocate(struct ipw2100_priv *priv) | |||
4499 | } | 4497 | } |
4500 | 4498 | ||
4501 | priv->tx_buffers = | 4499 | priv->tx_buffers = |
4502 | (struct ipw2100_tx_packet *)kmalloc(TX_PENDED_QUEUE_LENGTH * | 4500 | kmalloc(TX_PENDED_QUEUE_LENGTH * sizeof(struct ipw2100_tx_packet), |
4503 | sizeof(struct | 4501 | GFP_ATOMIC); |
4504 | ipw2100_tx_packet), | ||
4505 | GFP_ATOMIC); | ||
4506 | if (!priv->tx_buffers) { | 4502 | if (!priv->tx_buffers) { |
4507 | printk(KERN_ERR DRV_NAME | 4503 | printk(KERN_ERR DRV_NAME |
4508 | ": %s: alloc failed form tx buffers.\n", | 4504 | ": %s: alloc failed form tx buffers.\n", |
@@ -4651,9 +4647,9 @@ static int ipw2100_rx_allocate(struct ipw2100_priv *priv) | |||
4651 | /* | 4647 | /* |
4652 | * allocate packets | 4648 | * allocate packets |
4653 | */ | 4649 | */ |
4654 | priv->rx_buffers = (struct ipw2100_rx_packet *) | 4650 | priv->rx_buffers = kmalloc(RX_QUEUE_LENGTH * |
4655 | kmalloc(RX_QUEUE_LENGTH * sizeof(struct ipw2100_rx_packet), | 4651 | sizeof(struct ipw2100_rx_packet), |
4656 | GFP_KERNEL); | 4652 | GFP_KERNEL); |
4657 | if (!priv->rx_buffers) { | 4653 | if (!priv->rx_buffers) { |
4658 | IPW_DEBUG_INFO("can't allocate rx packet buffer table\n"); | 4654 | IPW_DEBUG_INFO("can't allocate rx packet buffer table\n"); |
4659 | 4655 | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 3aa3bb18f615..cb2552a6777c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -96,7 +96,7 @@ static int network_mode = 0; | |||
96 | static u32 ipw_debug_level; | 96 | static u32 ipw_debug_level; |
97 | static int associate; | 97 | static int associate; |
98 | static int auto_create = 1; | 98 | static int auto_create = 1; |
99 | static int led_support = 0; | 99 | static int led_support = 1; |
100 | static int disable = 0; | 100 | static int disable = 0; |
101 | static int bt_coexist = 0; | 101 | static int bt_coexist = 0; |
102 | static int hwcrypto = 0; | 102 | static int hwcrypto = 0; |
@@ -6624,13 +6624,12 @@ static int ipw_wx_set_genie(struct net_device *dev, | |||
6624 | return -EINVAL; | 6624 | return -EINVAL; |
6625 | 6625 | ||
6626 | if (wrqu->data.length) { | 6626 | if (wrqu->data.length) { |
6627 | buf = kmalloc(wrqu->data.length, GFP_KERNEL); | 6627 | buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); |
6628 | if (buf == NULL) { | 6628 | if (buf == NULL) { |
6629 | err = -ENOMEM; | 6629 | err = -ENOMEM; |
6630 | goto out; | 6630 | goto out; |
6631 | } | 6631 | } |
6632 | 6632 | ||
6633 | memcpy(buf, extra, wrqu->data.length); | ||
6634 | kfree(ieee->wpa_ie); | 6633 | kfree(ieee->wpa_ie); |
6635 | ieee->wpa_ie = buf; | 6634 | ieee->wpa_ie = buf; |
6636 | ieee->wpa_ie_len = wrqu->data.length; | 6635 | ieee->wpa_ie_len = wrqu->data.length; |
@@ -12083,7 +12082,7 @@ module_param(auto_create, int, 0444); | |||
12083 | MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); | 12082 | MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); |
12084 | 12083 | ||
12085 | module_param_named(led, led_support, int, 0444); | 12084 | module_param_named(led, led_support, int, 0444); |
12086 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); | 12085 | MODULE_PARM_DESC(led, "enable led control on some systems (default 1 on)"); |
12087 | 12086 | ||
12088 | module_param(debug, int, 0444); | 12087 | module_param(debug, int, 0444); |
12089 | MODULE_PARM_DESC(debug, "debug output mask"); | 12088 | MODULE_PARM_DESC(debug, "debug output mask"); |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index dc8ed1527666..6491e27baac5 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -30,9 +30,11 @@ config IWLWIFI_DEBUG | |||
30 | 30 | ||
31 | config IWLWIFI_DEBUGFS | 31 | config IWLWIFI_DEBUGFS |
32 | bool "iwlagn debugfs support" | 32 | bool "iwlagn debugfs support" |
33 | depends on IWLWIFI && IWLWIFI_DEBUG && MAC80211_DEBUGFS | 33 | depends on IWLWIFI && MAC80211_DEBUGFS |
34 | ---help--- | 34 | ---help--- |
35 | Enable creation of debugfs files for the iwlwifi drivers. | 35 | Enable creation of debugfs files for the iwlwifi drivers. This |
36 | is a low-impact option that allows getting insight into the | ||
37 | driver's state at runtime. | ||
36 | 38 | ||
37 | config IWLWIFI_DEVICE_TRACING | 39 | config IWLWIFI_DEVICE_TRACING |
38 | bool "iwlwifi device access tracing" | 40 | bool "iwlwifi device access tracing" |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 7c7235385513..728bb858ba97 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o | 1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o |
2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o | 2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o |
3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o | 3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o |
4 | iwlcore-objs += iwl-scan.o iwl-led.o | 4 | iwlcore-objs += iwl-scan.o iwl-led.o |
5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
6 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 6 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
@@ -11,7 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src) | |||
11 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 11 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | 13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o |
14 | iwlagn-objs += iwl-agn-lib.o | 14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o |
15 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | 15 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o |
16 | 16 | ||
17 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 17 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 6be2992f8f21..dba91e0233b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -158,6 +158,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
158 | BIT(IWL_CALIB_TX_IQ_PERD) | | 158 | BIT(IWL_CALIB_TX_IQ_PERD) | |
159 | BIT(IWL_CALIB_BASE_BAND); | 159 | BIT(IWL_CALIB_BASE_BAND); |
160 | 160 | ||
161 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
162 | |||
161 | return 0; | 163 | return 0; |
162 | } | 164 | } |
163 | 165 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c index 6a9c64a50e36..ef0835b01b6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c | |||
@@ -28,6 +28,28 @@ | |||
28 | 28 | ||
29 | #include "iwl-3945-debugfs.h" | 29 | #include "iwl-3945-debugfs.h" |
30 | 30 | ||
31 | |||
32 | static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
33 | { | ||
34 | int p = 0; | ||
35 | |||
36 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
37 | le32_to_cpu(priv->_3945.statistics.flag)); | ||
38 | if (le32_to_cpu(priv->_3945.statistics.flag) & | ||
39 | UCODE_STATISTICS_CLEAR_MSK) | ||
40 | p += scnprintf(buf + p, bufsz - p, | ||
41 | "\tStatistics have been cleared\n"); | ||
42 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
43 | (le32_to_cpu(priv->_3945.statistics.flag) & | ||
44 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
45 | ? "2.4 GHz" : "5.2 GHz"); | ||
46 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
47 | (le32_to_cpu(priv->_3945.statistics.flag) & | ||
48 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
49 | ? "enabled" : "disabled"); | ||
50 | return p; | ||
51 | } | ||
52 | |||
31 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | 53 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, |
32 | char __user *user_buf, | 54 | char __user *user_buf, |
33 | size_t count, loff_t *ppos) | 55 | size_t count, loff_t *ppos) |
@@ -70,7 +92,7 @@ ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | |||
70 | max_cck = &priv->_3945.max_delta.rx.cck; | 92 | max_cck = &priv->_3945.max_delta.rx.cck; |
71 | max_general = &priv->_3945.max_delta.rx.general; | 93 | max_general = &priv->_3945.max_delta.rx.general; |
72 | 94 | ||
73 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 95 | pos += iwl3945_statistics_flag(priv, buf, bufsz); |
74 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 96 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
75 | "acumulative delta max\n", | 97 | "acumulative delta max\n", |
76 | "Statistics_Rx - OFDM:"); | 98 | "Statistics_Rx - OFDM:"); |
@@ -331,7 +353,7 @@ ssize_t iwl3945_ucode_tx_stats_read(struct file *file, | |||
331 | accum_tx = &priv->_3945.accum_statistics.tx; | 353 | accum_tx = &priv->_3945.accum_statistics.tx; |
332 | delta_tx = &priv->_3945.delta_statistics.tx; | 354 | delta_tx = &priv->_3945.delta_statistics.tx; |
333 | max_tx = &priv->_3945.max_delta.tx; | 355 | max_tx = &priv->_3945.max_delta.tx; |
334 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 356 | pos += iwl3945_statistics_flag(priv, buf, bufsz); |
335 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 357 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
336 | "acumulative delta max\n", | 358 | "acumulative delta max\n", |
337 | "Statistics_Tx:"); | 359 | "Statistics_Tx:"); |
@@ -438,7 +460,7 @@ ssize_t iwl3945_ucode_general_stats_read(struct file *file, | |||
438 | accum_div = &priv->_3945.accum_statistics.general.div; | 460 | accum_div = &priv->_3945.accum_statistics.general.div; |
439 | delta_div = &priv->_3945.delta_statistics.general.div; | 461 | delta_div = &priv->_3945.delta_statistics.general.div; |
440 | max_div = &priv->_3945.max_delta.general.div; | 462 | max_div = &priv->_3945.max_delta.general.div; |
441 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 463 | pos += iwl3945_statistics_flag(priv, buf, bufsz); |
442 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 464 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
443 | "acumulative delta max\n", | 465 | "acumulative delta max\n", |
444 | "Statistics_General:"); | 466 | "Statistics_General:"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index c44a303e62ed..93d513e14186 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -279,8 +279,8 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | |||
279 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 279 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
280 | 280 | ||
281 | tx_info = &txq->txb[txq->q.read_ptr]; | 281 | tx_info = &txq->txb[txq->q.read_ptr]; |
282 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); | 282 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); |
283 | tx_info->skb[0] = NULL; | 283 | tx_info->skb = NULL; |
284 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 284 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); |
285 | } | 285 | } |
286 | 286 | ||
@@ -315,7 +315,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
315 | return; | 315 | return; |
316 | } | 316 | } |
317 | 317 | ||
318 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 318 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
319 | ieee80211_tx_info_clear_status(info); | 319 | ieee80211_tx_info_clear_status(info); |
320 | 320 | ||
321 | /* Fill the MRR chain with some info about on-chip retransmissions */ | 321 | /* Fill the MRR chain with some info about on-chip retransmissions */ |
@@ -352,7 +352,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
352 | * RX handler implementations | 352 | * RX handler implementations |
353 | * | 353 | * |
354 | *****************************************************************************/ | 354 | *****************************************************************************/ |
355 | #ifdef CONFIG_IWLWIFI_DEBUG | 355 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
356 | /* | 356 | /* |
357 | * based on the assumption of all statistics counter are in DWORD | 357 | * based on the assumption of all statistics counter are in DWORD |
358 | * FIXME: This function is for debugging, do not deal with | 358 | * FIXME: This function is for debugging, do not deal with |
@@ -460,7 +460,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | |||
460 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 460 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
461 | (int)sizeof(struct iwl3945_notif_statistics), | 461 | (int)sizeof(struct iwl3945_notif_statistics), |
462 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 462 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
463 | #ifdef CONFIG_IWLWIFI_DEBUG | 463 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
464 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); | 464 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); |
465 | #endif | 465 | #endif |
466 | iwl_recover_from_statistics(priv, pkt); | 466 | iwl_recover_from_statistics(priv, pkt); |
@@ -475,7 +475,7 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, | |||
475 | __le32 *flag = (__le32 *)&pkt->u.raw; | 475 | __le32 *flag = (__le32 *)&pkt->u.raw; |
476 | 476 | ||
477 | if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { | 477 | if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { |
478 | #ifdef CONFIG_IWLWIFI_DEBUG | 478 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
479 | memset(&priv->_3945.accum_statistics, 0, | 479 | memset(&priv->_3945.accum_statistics, 0, |
480 | sizeof(struct iwl3945_notif_statistics)); | 480 | sizeof(struct iwl3945_notif_statistics)); |
481 | memset(&priv->_3945.delta_statistics, 0, | 481 | memset(&priv->_3945.delta_statistics, 0, |
@@ -494,158 +494,6 @@ void iwl3945_reply_statistics(struct iwl_priv *priv, | |||
494 | * Misc. internal state and helper functions | 494 | * Misc. internal state and helper functions |
495 | * | 495 | * |
496 | ******************************************************************************/ | 496 | ******************************************************************************/ |
497 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
498 | |||
499 | /** | ||
500 | * iwl3945_report_frame - dump frame to syslog during debug sessions | ||
501 | * | ||
502 | * You may hack this function to show different aspects of received frames, | ||
503 | * including selective frame dumps. | ||
504 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
505 | */ | ||
506 | static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, | ||
507 | struct iwl_rx_packet *pkt, | ||
508 | struct ieee80211_hdr *header, int group100) | ||
509 | { | ||
510 | u32 to_us; | ||
511 | u32 print_summary = 0; | ||
512 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
513 | u32 hundred = 0; | ||
514 | u32 dataframe = 0; | ||
515 | __le16 fc; | ||
516 | u16 seq_ctl; | ||
517 | u16 channel; | ||
518 | u16 phy_flags; | ||
519 | u16 length; | ||
520 | u16 status; | ||
521 | u16 bcn_tmr; | ||
522 | u32 tsf_low; | ||
523 | u64 tsf; | ||
524 | u8 rssi; | ||
525 | u8 agc; | ||
526 | u16 sig_avg; | ||
527 | u16 noise_diff; | ||
528 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
529 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
530 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
531 | u8 *data = IWL_RX_DATA(pkt); | ||
532 | |||
533 | /* MAC header */ | ||
534 | fc = header->frame_control; | ||
535 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
536 | |||
537 | /* metadata */ | ||
538 | channel = le16_to_cpu(rx_hdr->channel); | ||
539 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
540 | length = le16_to_cpu(rx_hdr->len); | ||
541 | |||
542 | /* end-of-frame status and timestamp */ | ||
543 | status = le32_to_cpu(rx_end->status); | ||
544 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
545 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
546 | tsf = le64_to_cpu(rx_end->timestamp); | ||
547 | |||
548 | /* signal statistics */ | ||
549 | rssi = rx_stats->rssi; | ||
550 | agc = rx_stats->agc; | ||
551 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
552 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
553 | |||
554 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
555 | |||
556 | /* if data frame is to us and all is good, | ||
557 | * (optionally) print summary for only 1 out of every 100 */ | ||
558 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
559 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
560 | dataframe = 1; | ||
561 | if (!group100) | ||
562 | print_summary = 1; /* print each frame */ | ||
563 | else if (priv->framecnt_to_us < 100) { | ||
564 | priv->framecnt_to_us++; | ||
565 | print_summary = 0; | ||
566 | } else { | ||
567 | priv->framecnt_to_us = 0; | ||
568 | print_summary = 1; | ||
569 | hundred = 1; | ||
570 | } | ||
571 | } else { | ||
572 | /* print summary for all other frames */ | ||
573 | print_summary = 1; | ||
574 | } | ||
575 | |||
576 | if (print_summary) { | ||
577 | char *title; | ||
578 | int rate; | ||
579 | |||
580 | if (hundred) | ||
581 | title = "100Frames"; | ||
582 | else if (ieee80211_has_retry(fc)) | ||
583 | title = "Retry"; | ||
584 | else if (ieee80211_is_assoc_resp(fc)) | ||
585 | title = "AscRsp"; | ||
586 | else if (ieee80211_is_reassoc_resp(fc)) | ||
587 | title = "RasRsp"; | ||
588 | else if (ieee80211_is_probe_resp(fc)) { | ||
589 | title = "PrbRsp"; | ||
590 | print_dump = 1; /* dump frame contents */ | ||
591 | } else if (ieee80211_is_beacon(fc)) { | ||
592 | title = "Beacon"; | ||
593 | print_dump = 1; /* dump frame contents */ | ||
594 | } else if (ieee80211_is_atim(fc)) | ||
595 | title = "ATIM"; | ||
596 | else if (ieee80211_is_auth(fc)) | ||
597 | title = "Auth"; | ||
598 | else if (ieee80211_is_deauth(fc)) | ||
599 | title = "DeAuth"; | ||
600 | else if (ieee80211_is_disassoc(fc)) | ||
601 | title = "DisAssoc"; | ||
602 | else | ||
603 | title = "Frame"; | ||
604 | |||
605 | rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); | ||
606 | if (rate == -1) | ||
607 | rate = 0; | ||
608 | else | ||
609 | rate = iwl3945_rates[rate].ieee / 2; | ||
610 | |||
611 | /* print frame summary. | ||
612 | * MAC addresses show just the last byte (for brevity), | ||
613 | * but you can hack it to show more, if you'd like to. */ | ||
614 | if (dataframe) | ||
615 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
616 | "len=%u, rssi=%d, chnl=%d, rate=%d,\n", | ||
617 | title, le16_to_cpu(fc), header->addr1[5], | ||
618 | length, rssi, channel, rate); | ||
619 | else { | ||
620 | /* src/dst addresses assume managed mode */ | ||
621 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, " | ||
622 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
623 | "phy=0x%02x, chnl=%d\n", | ||
624 | title, le16_to_cpu(fc), header->addr1[5], | ||
625 | header->addr3[5], rssi, | ||
626 | tsf_low - priv->scan_start_tsf, | ||
627 | phy_flags, channel); | ||
628 | } | ||
629 | } | ||
630 | if (print_dump) | ||
631 | iwl_print_hex_dump(priv, IWL_DL_RX, data, length); | ||
632 | } | ||
633 | |||
634 | static void iwl3945_dbg_report_frame(struct iwl_priv *priv, | ||
635 | struct iwl_rx_packet *pkt, | ||
636 | struct ieee80211_hdr *header, int group100) | ||
637 | { | ||
638 | if (iwl_get_debug_level(priv) & IWL_DL_RX) | ||
639 | _iwl3945_dbg_report_frame(priv, pkt, header, group100); | ||
640 | } | ||
641 | |||
642 | #else | ||
643 | static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv, | ||
644 | struct iwl_rx_packet *pkt, | ||
645 | struct ieee80211_hdr *header, int group100) | ||
646 | { | ||
647 | } | ||
648 | #endif | ||
649 | 497 | ||
650 | /* This is necessary only for a number of statistics, see the caller. */ | 498 | /* This is necessary only for a number of statistics, see the caller. */ |
651 | static int iwl3945_is_network_packet(struct iwl_priv *priv, | 499 | static int iwl3945_is_network_packet(struct iwl_priv *priv, |
@@ -777,8 +625,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
777 | rx_status.signal, rx_status.signal, | 625 | rx_status.signal, rx_status.signal, |
778 | rx_status.rate_idx); | 626 | rx_status.rate_idx); |
779 | 627 | ||
780 | /* Set "1" to report good data frames in groups of 100 */ | ||
781 | iwl3945_dbg_report_frame(priv, pkt, header, 1); | ||
782 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); | 628 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); |
783 | 629 | ||
784 | if (network_packet) { | 630 | if (network_packet) { |
@@ -850,25 +696,28 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
850 | /* Unmap tx_cmd */ | 696 | /* Unmap tx_cmd */ |
851 | if (counter) | 697 | if (counter) |
852 | pci_unmap_single(dev, | 698 | pci_unmap_single(dev, |
853 | pci_unmap_addr(&txq->meta[index], mapping), | 699 | dma_unmap_addr(&txq->meta[index], mapping), |
854 | pci_unmap_len(&txq->meta[index], len), | 700 | dma_unmap_len(&txq->meta[index], len), |
855 | PCI_DMA_TODEVICE); | 701 | PCI_DMA_TODEVICE); |
856 | 702 | ||
857 | /* unmap chunks if any */ | 703 | /* unmap chunks if any */ |
858 | 704 | ||
859 | for (i = 1; i < counter; i++) { | 705 | for (i = 1; i < counter; i++) |
860 | pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), | 706 | pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), |
861 | le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); | 707 | le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); |
862 | if (txq->txb[txq->q.read_ptr].skb[0]) { | 708 | |
863 | struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0]; | 709 | /* free SKB */ |
864 | if (txq->txb[txq->q.read_ptr].skb[0]) { | 710 | if (txq->txb) { |
865 | /* Can be called from interrupt context */ | 711 | struct sk_buff *skb; |
866 | dev_kfree_skb_any(skb); | 712 | |
867 | txq->txb[txq->q.read_ptr].skb[0] = NULL; | 713 | skb = txq->txb[txq->q.read_ptr].skb; |
868 | } | 714 | |
715 | /* can be called from irqs-disabled context */ | ||
716 | if (skb) { | ||
717 | dev_kfree_skb_any(skb); | ||
718 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
869 | } | 719 | } |
870 | } | 720 | } |
871 | return ; | ||
872 | } | 721 | } |
873 | 722 | ||
874 | /** | 723 | /** |
@@ -947,8 +796,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
947 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); | 796 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
948 | } | 797 | } |
949 | 798 | ||
950 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, | 799 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate) |
951 | u16 tx_rate, u8 flags) | ||
952 | { | 800 | { |
953 | unsigned long flags_spin; | 801 | unsigned long flags_spin; |
954 | struct iwl_station_entry *station; | 802 | struct iwl_station_entry *station; |
@@ -962,10 +810,9 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, | |||
962 | station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; | 810 | station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; |
963 | station->sta.rate_n_flags = cpu_to_le16(tx_rate); | 811 | station->sta.rate_n_flags = cpu_to_le16(tx_rate); |
964 | station->sta.mode = STA_CONTROL_MODIFY_MSK; | 812 | station->sta.mode = STA_CONTROL_MODIFY_MSK; |
965 | 813 | iwl_send_add_sta(priv, &station->sta, CMD_ASYNC); | |
966 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 814 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
967 | 815 | ||
968 | iwl_send_add_sta(priv, &station->sta, flags); | ||
969 | IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", | 816 | IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", |
970 | sta_id, tx_rate); | 817 | sta_id, tx_rate); |
971 | return sta_id; | 818 | return sta_id; |
@@ -997,7 +844,7 @@ static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) | |||
997 | 844 | ||
998 | static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | 845 | static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) |
999 | { | 846 | { |
1000 | iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); | 847 | iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma); |
1001 | iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); | 848 | iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); |
1002 | iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); | 849 | iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); |
1003 | iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), | 850 | iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), |
@@ -2473,8 +2320,7 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv, | |||
2473 | 2320 | ||
2474 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, | 2321 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, |
2475 | (priv->band == IEEE80211_BAND_5GHZ) ? | 2322 | (priv->band == IEEE80211_BAND_5GHZ) ? |
2476 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, | 2323 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP); |
2477 | CMD_ASYNC); | ||
2478 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); | 2324 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); |
2479 | 2325 | ||
2480 | return 0; | 2326 | return 0; |
@@ -2590,6 +2436,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2590 | 2436 | ||
2591 | priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; | 2437 | priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; |
2592 | priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; | 2438 | priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; |
2439 | priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS; | ||
2593 | 2440 | ||
2594 | return 0; | 2441 | return 0; |
2595 | } | 2442 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d3afddae8d9f..67526a1be025 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -346,9 +346,19 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) | |||
346 | { | 346 | { |
347 | struct iwl_chain_noise_data *data = &(priv->chain_noise_data); | 347 | struct iwl_chain_noise_data *data = &(priv->chain_noise_data); |
348 | 348 | ||
349 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | 349 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && |
350 | iwl_is_associated(priv)) { | ||
350 | struct iwl_calib_diff_gain_cmd cmd; | 351 | struct iwl_calib_diff_gain_cmd cmd; |
351 | 352 | ||
353 | /* clear data for chain noise calibration algorithm */ | ||
354 | data->chain_noise_a = 0; | ||
355 | data->chain_noise_b = 0; | ||
356 | data->chain_noise_c = 0; | ||
357 | data->chain_signal_a = 0; | ||
358 | data->chain_signal_b = 0; | ||
359 | data->chain_signal_c = 0; | ||
360 | data->beacon_count = 0; | ||
361 | |||
352 | memset(&cmd, 0, sizeof(cmd)); | 362 | memset(&cmd, 0, sizeof(cmd)); |
353 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; | 363 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; |
354 | cmd.diff_gain_a = 0; | 364 | cmd.diff_gain_a = 0; |
@@ -419,13 +429,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
419 | /* Mark so we run this algo only once! */ | 429 | /* Mark so we run this algo only once! */ |
420 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | 430 | data->state = IWL_CHAIN_NOISE_CALIBRATED; |
421 | } | 431 | } |
422 | data->chain_noise_a = 0; | ||
423 | data->chain_noise_b = 0; | ||
424 | data->chain_noise_c = 0; | ||
425 | data->chain_signal_a = 0; | ||
426 | data->chain_signal_b = 0; | ||
427 | data->chain_signal_c = 0; | ||
428 | data->beacon_count = 0; | ||
429 | } | 432 | } |
430 | 433 | ||
431 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 434 | static void iwl4965_bg_txpower_work(struct work_struct *work) |
@@ -669,6 +672,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
669 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | 672 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); |
670 | 673 | ||
671 | priv->hw_params.sens = &iwl4965_sensitivity; | 674 | priv->hw_params.sens = &iwl4965_sensitivity; |
675 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
672 | 676 | ||
673 | return 0; | 677 | return 0; |
674 | } | 678 | } |
@@ -1441,7 +1445,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | |||
1441 | return ret; | 1445 | return ret; |
1442 | } | 1446 | } |
1443 | 1447 | ||
1444 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 1448 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, |
1449 | struct ieee80211_channel_switch *ch_switch) | ||
1445 | { | 1450 | { |
1446 | int rc; | 1451 | int rc; |
1447 | u8 band = 0; | 1452 | u8 band = 0; |
@@ -1449,11 +1454,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1449 | u8 ctrl_chan_high = 0; | 1454 | u8 ctrl_chan_high = 0; |
1450 | struct iwl4965_channel_switch_cmd cmd; | 1455 | struct iwl4965_channel_switch_cmd cmd; |
1451 | const struct iwl_channel_info *ch_info; | 1456 | const struct iwl_channel_info *ch_info; |
1452 | 1457 | u32 switch_time_in_usec, ucode_switch_time; | |
1458 | u16 ch; | ||
1459 | u32 tsf_low; | ||
1460 | u8 switch_count; | ||
1461 | u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); | ||
1462 | struct ieee80211_vif *vif = priv->vif; | ||
1453 | band = priv->band == IEEE80211_BAND_2GHZ; | 1463 | band = priv->band == IEEE80211_BAND_2GHZ; |
1454 | 1464 | ||
1455 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
1456 | |||
1457 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); | 1465 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); |
1458 | 1466 | ||
1459 | if (is_ht40 && | 1467 | if (is_ht40 && |
@@ -1462,26 +1470,56 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1462 | 1470 | ||
1463 | cmd.band = band; | 1471 | cmd.band = band; |
1464 | cmd.expect_beacon = 0; | 1472 | cmd.expect_beacon = 0; |
1465 | cmd.channel = cpu_to_le16(channel); | 1473 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); |
1474 | cmd.channel = cpu_to_le16(ch); | ||
1466 | cmd.rxon_flags = priv->staging_rxon.flags; | 1475 | cmd.rxon_flags = priv->staging_rxon.flags; |
1467 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 1476 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
1468 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1477 | switch_count = ch_switch->count; |
1478 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
1479 | /* | ||
1480 | * calculate the ucode channel switch time | ||
1481 | * adding TSF as one of the factor for when to switch | ||
1482 | */ | ||
1483 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
1484 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
1485 | beacon_interval)) { | ||
1486 | switch_count -= (priv->ucode_beacon_time - | ||
1487 | tsf_low) / beacon_interval; | ||
1488 | } else | ||
1489 | switch_count = 0; | ||
1490 | } | ||
1491 | if (switch_count <= 1) | ||
1492 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
1493 | else { | ||
1494 | switch_time_in_usec = | ||
1495 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
1496 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
1497 | switch_time_in_usec, | ||
1498 | beacon_interval); | ||
1499 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
1500 | priv->ucode_beacon_time, | ||
1501 | ucode_switch_time, | ||
1502 | beacon_interval); | ||
1503 | } | ||
1504 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
1505 | cmd.switch_time); | ||
1506 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
1469 | if (ch_info) | 1507 | if (ch_info) |
1470 | cmd.expect_beacon = is_channel_radar(ch_info); | 1508 | cmd.expect_beacon = is_channel_radar(ch_info); |
1471 | else { | 1509 | else { |
1472 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | 1510 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
1473 | priv->active_rxon.channel, channel); | 1511 | priv->active_rxon.channel, ch); |
1474 | return -EFAULT; | 1512 | return -EFAULT; |
1475 | } | 1513 | } |
1476 | 1514 | ||
1477 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, | 1515 | rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40, |
1478 | ctrl_chan_high, &cmd.tx_power); | 1516 | ctrl_chan_high, &cmd.tx_power); |
1479 | if (rc) { | 1517 | if (rc) { |
1480 | IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); | 1518 | IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); |
1481 | return rc; | 1519 | return rc; |
1482 | } | 1520 | } |
1483 | 1521 | ||
1484 | priv->switch_rxon.channel = cpu_to_le16(channel); | 1522 | priv->switch_rxon.channel = cmd.channel; |
1485 | priv->switch_rxon.switch_in_progress = true; | 1523 | priv->switch_rxon.switch_in_progress = true; |
1486 | 1524 | ||
1487 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | 1525 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); |
@@ -1542,7 +1580,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv) | |||
1542 | u32 R4; | 1580 | u32 R4; |
1543 | 1581 | ||
1544 | if (test_bit(STATUS_TEMPERATURE, &priv->status) && | 1582 | if (test_bit(STATUS_TEMPERATURE, &priv->status) && |
1545 | (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) { | 1583 | (priv->_agn.statistics.flag & |
1584 | STATISTICS_REPLY_FLG_HT40_MODE_MSK)) { | ||
1546 | IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n"); | 1585 | IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n"); |
1547 | R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); | 1586 | R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); |
1548 | R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); | 1587 | R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); |
@@ -1566,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv) | |||
1566 | if (!test_bit(STATUS_TEMPERATURE, &priv->status)) | 1605 | if (!test_bit(STATUS_TEMPERATURE, &priv->status)) |
1567 | vt = sign_extend(R4, 23); | 1606 | vt = sign_extend(R4, 23); |
1568 | else | 1607 | else |
1569 | vt = sign_extend( | 1608 | vt = sign_extend(le32_to_cpu( |
1570 | le32_to_cpu(priv->statistics.general.temperature), 23); | 1609 | priv->_agn.statistics.general.temperature), 23); |
1571 | 1610 | ||
1572 | IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); | 1611 | IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); |
1573 | 1612 | ||
@@ -1747,6 +1786,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1747 | { | 1786 | { |
1748 | unsigned long flags; | 1787 | unsigned long flags; |
1749 | u16 ra_tid; | 1788 | u16 ra_tid; |
1789 | int ret; | ||
1750 | 1790 | ||
1751 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1791 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1752 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 1792 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
@@ -1762,7 +1802,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1762 | ra_tid = BUILD_RAxTID(sta_id, tid); | 1802 | ra_tid = BUILD_RAxTID(sta_id, tid); |
1763 | 1803 | ||
1764 | /* Modify device's station table to Tx this TID */ | 1804 | /* Modify device's station table to Tx this TID */ |
1765 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | 1805 | ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); |
1806 | if (ret) | ||
1807 | return ret; | ||
1766 | 1808 | ||
1767 | spin_lock_irqsave(&priv->lock, flags); | 1809 | spin_lock_irqsave(&priv->lock, flags); |
1768 | 1810 | ||
@@ -1870,7 +1912,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1870 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | 1912 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", |
1871 | agg->frame_count, agg->start_idx, idx); | 1913 | agg->frame_count, agg->start_idx, idx); |
1872 | 1914 | ||
1873 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 1915 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); |
1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1916 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1917 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1876 | info->flags |= iwl_tx_status_to_mac80211(status); | 1918 | info->flags |= iwl_tx_status_to_mac80211(status); |
@@ -2026,6 +2068,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2026 | int sta_id; | 2068 | int sta_id; |
2027 | int freed; | 2069 | int freed; |
2028 | u8 *qc = NULL; | 2070 | u8 *qc = NULL; |
2071 | unsigned long flags; | ||
2029 | 2072 | ||
2030 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | 2073 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { |
2031 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | 2074 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " |
@@ -2035,7 +2078,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2035 | return; | 2078 | return; |
2036 | } | 2079 | } |
2037 | 2080 | ||
2038 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 2081 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
2039 | memset(&info->status, 0, sizeof(info->status)); | 2082 | memset(&info->status, 0, sizeof(info->status)); |
2040 | 2083 | ||
2041 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); | 2084 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); |
@@ -2050,10 +2093,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2050 | return; | 2093 | return; |
2051 | } | 2094 | } |
2052 | 2095 | ||
2096 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2053 | if (txq->sched_retry) { | 2097 | if (txq->sched_retry) { |
2054 | const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); | 2098 | const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); |
2055 | struct iwl_ht_agg *agg = NULL; | 2099 | struct iwl_ht_agg *agg = NULL; |
2056 | |||
2057 | WARN_ON(!qc); | 2100 | WARN_ON(!qc); |
2058 | 2101 | ||
2059 | agg = &priv->stations[sta_id].tid[tid].agg; | 2102 | agg = &priv->stations[sta_id].tid[tid].agg; |
@@ -2110,6 +2153,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2110 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | 2153 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
2111 | 2154 | ||
2112 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 2155 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
2156 | |||
2157 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2113 | } | 2158 | } |
2114 | 2159 | ||
2115 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2160 | static int iwl4965_calc_rssi(struct iwl_priv *priv, |
@@ -2285,7 +2330,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2285 | * Force use of chains B and C for scan RX on 5 GHz band | 2330 | * Force use of chains B and C for scan RX on 5 GHz band |
2286 | * because the device has off-channel reception on chain A. | 2331 | * because the device has off-channel reception on chain A. |
2287 | */ | 2332 | */ |
2288 | .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, | 2333 | .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, |
2289 | }; | 2334 | }; |
2290 | 2335 | ||
2291 | /* Module firmware */ | 2336 | /* Module firmware */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a28af7eb67eb..c6ccc25d6c13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -208,6 +208,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
208 | BIT(IWL_CALIB_TX_IQ_PERD) | | 208 | BIT(IWL_CALIB_TX_IQ_PERD) | |
209 | BIT(IWL_CALIB_BASE_BAND); | 209 | BIT(IWL_CALIB_BASE_BAND); |
210 | 210 | ||
211 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
212 | |||
211 | return 0; | 213 | return 0; |
212 | } | 214 | } |
213 | 215 | ||
@@ -252,6 +254,8 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
252 | BIT(IWL_CALIB_TX_IQ) | | 254 | BIT(IWL_CALIB_TX_IQ) | |
253 | BIT(IWL_CALIB_BASE_BAND); | 255 | BIT(IWL_CALIB_BASE_BAND); |
254 | 256 | ||
257 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
258 | |||
255 | return 0; | 259 | return 0; |
256 | } | 260 | } |
257 | 261 | ||
@@ -260,40 +264,76 @@ static void iwl5150_temperature(struct iwl_priv *priv) | |||
260 | u32 vt = 0; | 264 | u32 vt = 0; |
261 | s32 offset = iwl_temp_calib_to_offset(priv); | 265 | s32 offset = iwl_temp_calib_to_offset(priv); |
262 | 266 | ||
263 | vt = le32_to_cpu(priv->statistics.general.temperature); | 267 | vt = le32_to_cpu(priv->_agn.statistics.general.temperature); |
264 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | 268 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; |
265 | /* now vt hold the temperature in Kelvin */ | 269 | /* now vt hold the temperature in Kelvin */ |
266 | priv->temperature = KELVIN_TO_CELSIUS(vt); | 270 | priv->temperature = KELVIN_TO_CELSIUS(vt); |
267 | iwl_tt_handler(priv); | 271 | iwl_tt_handler(priv); |
268 | } | 272 | } |
269 | 273 | ||
270 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 274 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, |
275 | struct ieee80211_channel_switch *ch_switch) | ||
271 | { | 276 | { |
272 | struct iwl5000_channel_switch_cmd cmd; | 277 | struct iwl5000_channel_switch_cmd cmd; |
273 | const struct iwl_channel_info *ch_info; | 278 | const struct iwl_channel_info *ch_info; |
279 | u32 switch_time_in_usec, ucode_switch_time; | ||
280 | u16 ch; | ||
281 | u32 tsf_low; | ||
282 | u8 switch_count; | ||
283 | u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); | ||
284 | struct ieee80211_vif *vif = priv->vif; | ||
274 | struct iwl_host_cmd hcmd = { | 285 | struct iwl_host_cmd hcmd = { |
275 | .id = REPLY_CHANNEL_SWITCH, | 286 | .id = REPLY_CHANNEL_SWITCH, |
276 | .len = sizeof(cmd), | 287 | .len = sizeof(cmd), |
277 | .flags = CMD_SIZE_HUGE, | 288 | .flags = CMD_SYNC, |
278 | .data = &cmd, | 289 | .data = &cmd, |
279 | }; | 290 | }; |
280 | 291 | ||
281 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
282 | priv->active_rxon.channel, channel); | ||
283 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 292 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
284 | cmd.channel = cpu_to_le16(channel); | 293 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); |
294 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
295 | priv->active_rxon.channel, ch); | ||
296 | cmd.channel = cpu_to_le16(ch); | ||
285 | cmd.rxon_flags = priv->staging_rxon.flags; | 297 | cmd.rxon_flags = priv->staging_rxon.flags; |
286 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 298 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
287 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 299 | switch_count = ch_switch->count; |
288 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | 300 | tsf_low = ch_switch->timestamp & 0x0ffffffff; |
301 | /* | ||
302 | * calculate the ucode channel switch time | ||
303 | * adding TSF as one of the factor for when to switch | ||
304 | */ | ||
305 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
306 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
307 | beacon_interval)) { | ||
308 | switch_count -= (priv->ucode_beacon_time - | ||
309 | tsf_low) / beacon_interval; | ||
310 | } else | ||
311 | switch_count = 0; | ||
312 | } | ||
313 | if (switch_count <= 1) | ||
314 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
315 | else { | ||
316 | switch_time_in_usec = | ||
317 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
318 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
319 | switch_time_in_usec, | ||
320 | beacon_interval); | ||
321 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
322 | priv->ucode_beacon_time, | ||
323 | ucode_switch_time, | ||
324 | beacon_interval); | ||
325 | } | ||
326 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
327 | cmd.switch_time); | ||
328 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
289 | if (ch_info) | 329 | if (ch_info) |
290 | cmd.expect_beacon = is_channel_radar(ch_info); | 330 | cmd.expect_beacon = is_channel_radar(ch_info); |
291 | else { | 331 | else { |
292 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | 332 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
293 | priv->active_rxon.channel, channel); | 333 | priv->active_rxon.channel, ch); |
294 | return -EFAULT; | 334 | return -EFAULT; |
295 | } | 335 | } |
296 | priv->switch_rxon.channel = cpu_to_le16(channel); | 336 | priv->switch_rxon.channel = cmd.channel; |
297 | priv->switch_rxon.switch_in_progress = true; | 337 | priv->switch_rxon.switch_in_progress = true; |
298 | 338 | ||
299 | return iwl_send_cmd_sync(priv, &hcmd); | 339 | return iwl_send_cmd_sync(priv, &hcmd); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9fbf54cd3e1a..afdeec56b13f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -71,6 +71,10 @@ | |||
71 | #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" | 71 | #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" |
72 | #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) | 72 | #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) |
73 | 73 | ||
74 | #define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-" | ||
75 | #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" | ||
76 | #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) | ||
77 | |||
74 | 78 | ||
75 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | 79 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) |
76 | { | 80 | { |
@@ -183,6 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
183 | BIT(IWL_CALIB_TX_IQ) | | 187 | BIT(IWL_CALIB_TX_IQ) | |
184 | BIT(IWL_CALIB_BASE_BAND); | 188 | BIT(IWL_CALIB_BASE_BAND); |
185 | 189 | ||
190 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
191 | |||
186 | return 0; | 192 | return 0; |
187 | } | 193 | } |
188 | 194 | ||
@@ -228,37 +234,74 @@ static int iwl6050_hw_set_hw_params(struct iwl_priv *priv) | |||
228 | BIT(IWL_CALIB_TX_IQ) | | 234 | BIT(IWL_CALIB_TX_IQ) | |
229 | BIT(IWL_CALIB_BASE_BAND); | 235 | BIT(IWL_CALIB_BASE_BAND); |
230 | 236 | ||
237 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
238 | |||
231 | return 0; | 239 | return 0; |
232 | } | 240 | } |
233 | 241 | ||
234 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 242 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, |
243 | struct ieee80211_channel_switch *ch_switch) | ||
235 | { | 244 | { |
236 | struct iwl6000_channel_switch_cmd cmd; | 245 | struct iwl6000_channel_switch_cmd cmd; |
237 | const struct iwl_channel_info *ch_info; | 246 | const struct iwl_channel_info *ch_info; |
247 | u32 switch_time_in_usec, ucode_switch_time; | ||
248 | u16 ch; | ||
249 | u32 tsf_low; | ||
250 | u8 switch_count; | ||
251 | u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); | ||
252 | struct ieee80211_vif *vif = priv->vif; | ||
238 | struct iwl_host_cmd hcmd = { | 253 | struct iwl_host_cmd hcmd = { |
239 | .id = REPLY_CHANNEL_SWITCH, | 254 | .id = REPLY_CHANNEL_SWITCH, |
240 | .len = sizeof(cmd), | 255 | .len = sizeof(cmd), |
241 | .flags = CMD_SIZE_HUGE, | 256 | .flags = CMD_SYNC, |
242 | .data = &cmd, | 257 | .data = &cmd, |
243 | }; | 258 | }; |
244 | 259 | ||
245 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
246 | priv->active_rxon.channel, channel); | ||
247 | |||
248 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 260 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
249 | cmd.channel = cpu_to_le16(channel); | 261 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); |
262 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | ||
263 | priv->active_rxon.channel, ch); | ||
264 | cmd.channel = cpu_to_le16(ch); | ||
250 | cmd.rxon_flags = priv->staging_rxon.flags; | 265 | cmd.rxon_flags = priv->staging_rxon.flags; |
251 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 266 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
252 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 267 | switch_count = ch_switch->count; |
253 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | 268 | tsf_low = ch_switch->timestamp & 0x0ffffffff; |
269 | /* | ||
270 | * calculate the ucode channel switch time | ||
271 | * adding TSF as one of the factor for when to switch | ||
272 | */ | ||
273 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
274 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
275 | beacon_interval)) { | ||
276 | switch_count -= (priv->ucode_beacon_time - | ||
277 | tsf_low) / beacon_interval; | ||
278 | } else | ||
279 | switch_count = 0; | ||
280 | } | ||
281 | if (switch_count <= 1) | ||
282 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
283 | else { | ||
284 | switch_time_in_usec = | ||
285 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
286 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
287 | switch_time_in_usec, | ||
288 | beacon_interval); | ||
289 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
290 | priv->ucode_beacon_time, | ||
291 | ucode_switch_time, | ||
292 | beacon_interval); | ||
293 | } | ||
294 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
295 | cmd.switch_time); | ||
296 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
254 | if (ch_info) | 297 | if (ch_info) |
255 | cmd.expect_beacon = is_channel_radar(ch_info); | 298 | cmd.expect_beacon = is_channel_radar(ch_info); |
256 | else { | 299 | else { |
257 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | 300 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
258 | priv->active_rxon.channel, channel); | 301 | priv->active_rxon.channel, ch); |
259 | return -EFAULT; | 302 | return -EFAULT; |
260 | } | 303 | } |
261 | priv->switch_rxon.channel = cpu_to_le16(channel); | 304 | priv->switch_rxon.channel = cmd.channel; |
262 | priv->switch_rxon.switch_in_progress = true; | 305 | priv->switch_rxon.switch_in_progress = true; |
263 | 306 | ||
264 | return iwl_send_cmd_sync(priv, &hcmd); | 307 | return iwl_send_cmd_sync(priv, &hcmd); |
@@ -335,6 +378,25 @@ static const struct iwl_ops iwl6000_ops = { | |||
335 | .led = &iwlagn_led_ops, | 378 | .led = &iwlagn_led_ops, |
336 | }; | 379 | }; |
337 | 380 | ||
381 | static void do_not_send_bt_config(struct iwl_priv *priv) | ||
382 | { | ||
383 | } | ||
384 | |||
385 | static struct iwl_hcmd_ops iwl6000g2b_hcmd = { | ||
386 | .rxon_assoc = iwlagn_send_rxon_assoc, | ||
387 | .commit_rxon = iwl_commit_rxon, | ||
388 | .set_rxon_chain = iwl_set_rxon_chain, | ||
389 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
390 | .send_bt_config = do_not_send_bt_config, | ||
391 | }; | ||
392 | |||
393 | static const struct iwl_ops iwl6000g2b_ops = { | ||
394 | .lib = &iwl6000_lib, | ||
395 | .hcmd = &iwl6000g2b_hcmd, | ||
396 | .utils = &iwlagn_hcmd_utils, | ||
397 | .led = &iwlagn_led_ops, | ||
398 | }; | ||
399 | |||
338 | static struct iwl_lib_ops iwl6050_lib = { | 400 | static struct iwl_lib_ops iwl6050_lib = { |
339 | .set_hw_params = iwl6050_hw_set_hw_params, | 401 | .set_hw_params = iwl6050_hw_set_hw_params, |
340 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | 402 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
@@ -445,6 +507,268 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { | |||
445 | .chain_noise_calib_by_driver = true, | 507 | .chain_noise_calib_by_driver = true, |
446 | }; | 508 | }; |
447 | 509 | ||
510 | struct iwl_cfg iwl6000g2a_2abg_cfg = { | ||
511 | .name = "6000 Series 2x2 ABG Gen2a", | ||
512 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
513 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
514 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
515 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
516 | .ops = &iwl6000_ops, | ||
517 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
518 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
519 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
520 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
521 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
522 | .mod_params = &iwlagn_mod_params, | ||
523 | .valid_tx_ant = ANT_AB, | ||
524 | .valid_rx_ant = ANT_AB, | ||
525 | .pll_cfg_val = 0, | ||
526 | .set_l0s = true, | ||
527 | .use_bsm = false, | ||
528 | .pa_type = IWL_PA_SYSTEM, | ||
529 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
530 | .shadow_ram_support = true, | ||
531 | .led_compensation = 51, | ||
532 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
533 | .supports_idle = true, | ||
534 | .adv_thermal_throttle = true, | ||
535 | .support_ct_kill_exit = true, | ||
536 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
537 | .chain_noise_scale = 1000, | ||
538 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
539 | .max_event_log_size = 512, | ||
540 | }; | ||
541 | |||
542 | struct iwl_cfg iwl6000g2a_2bg_cfg = { | ||
543 | .name = "6000 Series 2x2 BG Gen2a", | ||
544 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
545 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
546 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
547 | .sku = IWL_SKU_G, | ||
548 | .ops = &iwl6000_ops, | ||
549 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
550 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
551 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
552 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
553 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
554 | .mod_params = &iwlagn_mod_params, | ||
555 | .valid_tx_ant = ANT_AB, | ||
556 | .valid_rx_ant = ANT_AB, | ||
557 | .pll_cfg_val = 0, | ||
558 | .set_l0s = true, | ||
559 | .use_bsm = false, | ||
560 | .pa_type = IWL_PA_SYSTEM, | ||
561 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
562 | .shadow_ram_support = true, | ||
563 | .led_compensation = 51, | ||
564 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
565 | .supports_idle = true, | ||
566 | .adv_thermal_throttle = true, | ||
567 | .support_ct_kill_exit = true, | ||
568 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
569 | .chain_noise_scale = 1000, | ||
570 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
571 | .max_event_log_size = 512, | ||
572 | }; | ||
573 | |||
574 | struct iwl_cfg iwl6000g2b_2agn_cfg = { | ||
575 | .name = "6000 Series 2x2 AGN Gen2b", | ||
576 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
577 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
578 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
579 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
580 | .ops = &iwl6000g2b_ops, | ||
581 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
582 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
583 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
584 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
585 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
586 | .mod_params = &iwlagn_mod_params, | ||
587 | .valid_tx_ant = ANT_AB, | ||
588 | .valid_rx_ant = ANT_AB, | ||
589 | .pll_cfg_val = 0, | ||
590 | .set_l0s = true, | ||
591 | .use_bsm = false, | ||
592 | .pa_type = IWL_PA_SYSTEM, | ||
593 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
594 | .shadow_ram_support = true, | ||
595 | .ht_greenfield_support = true, | ||
596 | .led_compensation = 51, | ||
597 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
598 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
599 | .supports_idle = true, | ||
600 | .adv_thermal_throttle = true, | ||
601 | .support_ct_kill_exit = true, | ||
602 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
603 | .chain_noise_scale = 1000, | ||
604 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
605 | .max_event_log_size = 512, | ||
606 | }; | ||
607 | |||
608 | struct iwl_cfg iwl6000g2b_2abg_cfg = { | ||
609 | .name = "6000 Series 2x2 ABG Gen2b", | ||
610 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
611 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
612 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
613 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
614 | .ops = &iwl6000g2b_ops, | ||
615 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
616 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
617 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
618 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
619 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
620 | .mod_params = &iwlagn_mod_params, | ||
621 | .valid_tx_ant = ANT_AB, | ||
622 | .valid_rx_ant = ANT_AB, | ||
623 | .pll_cfg_val = 0, | ||
624 | .set_l0s = true, | ||
625 | .use_bsm = false, | ||
626 | .pa_type = IWL_PA_SYSTEM, | ||
627 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
628 | .shadow_ram_support = true, | ||
629 | .led_compensation = 51, | ||
630 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
631 | .supports_idle = true, | ||
632 | .adv_thermal_throttle = true, | ||
633 | .support_ct_kill_exit = true, | ||
634 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
635 | .chain_noise_scale = 1000, | ||
636 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
637 | .max_event_log_size = 512, | ||
638 | }; | ||
639 | |||
640 | struct iwl_cfg iwl6000g2b_2bgn_cfg = { | ||
641 | .name = "6000 Series 2x2 BGN Gen2b", | ||
642 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
643 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
644 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
645 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
646 | .ops = &iwl6000g2b_ops, | ||
647 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
648 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
649 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
650 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
651 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
652 | .mod_params = &iwlagn_mod_params, | ||
653 | .valid_tx_ant = ANT_AB, | ||
654 | .valid_rx_ant = ANT_AB, | ||
655 | .pll_cfg_val = 0, | ||
656 | .set_l0s = true, | ||
657 | .use_bsm = false, | ||
658 | .pa_type = IWL_PA_SYSTEM, | ||
659 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
660 | .shadow_ram_support = true, | ||
661 | .ht_greenfield_support = true, | ||
662 | .led_compensation = 51, | ||
663 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
664 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
665 | .supports_idle = true, | ||
666 | .adv_thermal_throttle = true, | ||
667 | .support_ct_kill_exit = true, | ||
668 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
669 | .chain_noise_scale = 1000, | ||
670 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
671 | .max_event_log_size = 512, | ||
672 | }; | ||
673 | |||
674 | struct iwl_cfg iwl6000g2b_2bg_cfg = { | ||
675 | .name = "6000 Series 2x2 BG Gen2b", | ||
676 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
677 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
678 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
679 | .sku = IWL_SKU_G, | ||
680 | .ops = &iwl6000g2b_ops, | ||
681 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
682 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
683 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
684 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
685 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
686 | .mod_params = &iwlagn_mod_params, | ||
687 | .valid_tx_ant = ANT_AB, | ||
688 | .valid_rx_ant = ANT_AB, | ||
689 | .pll_cfg_val = 0, | ||
690 | .set_l0s = true, | ||
691 | .use_bsm = false, | ||
692 | .pa_type = IWL_PA_SYSTEM, | ||
693 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
694 | .shadow_ram_support = true, | ||
695 | .led_compensation = 51, | ||
696 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
697 | .supports_idle = true, | ||
698 | .adv_thermal_throttle = true, | ||
699 | .support_ct_kill_exit = true, | ||
700 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
701 | .chain_noise_scale = 1000, | ||
702 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
703 | .max_event_log_size = 512, | ||
704 | }; | ||
705 | |||
706 | struct iwl_cfg iwl6000g2b_bgn_cfg = { | ||
707 | .name = "6000 Series 1x2 BGN Gen2b", | ||
708 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
709 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
710 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
711 | .sku = IWL_SKU_G|IWL_SKU_N, | ||
712 | .ops = &iwl6000g2b_ops, | ||
713 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
714 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
715 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
716 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
717 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
718 | .mod_params = &iwlagn_mod_params, | ||
719 | .valid_tx_ant = ANT_A, | ||
720 | .valid_rx_ant = ANT_AB, | ||
721 | .pll_cfg_val = 0, | ||
722 | .set_l0s = true, | ||
723 | .use_bsm = false, | ||
724 | .pa_type = IWL_PA_SYSTEM, | ||
725 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
726 | .shadow_ram_support = true, | ||
727 | .ht_greenfield_support = true, | ||
728 | .led_compensation = 51, | ||
729 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
730 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
731 | .supports_idle = true, | ||
732 | .adv_thermal_throttle = true, | ||
733 | .support_ct_kill_exit = true, | ||
734 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
735 | .chain_noise_scale = 1000, | ||
736 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
737 | .max_event_log_size = 512, | ||
738 | }; | ||
739 | |||
740 | struct iwl_cfg iwl6000g2b_bg_cfg = { | ||
741 | .name = "6000 Series 1x2 BG Gen2b", | ||
742 | .fw_name_pre = IWL6000G2B_FW_PRE, | ||
743 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
744 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
745 | .sku = IWL_SKU_G, | ||
746 | .ops = &iwl6000g2b_ops, | ||
747 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
748 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
749 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
750 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
751 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
752 | .mod_params = &iwlagn_mod_params, | ||
753 | .valid_tx_ant = ANT_A, | ||
754 | .valid_rx_ant = ANT_AB, | ||
755 | .pll_cfg_val = 0, | ||
756 | .set_l0s = true, | ||
757 | .use_bsm = false, | ||
758 | .pa_type = IWL_PA_SYSTEM, | ||
759 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
760 | .shadow_ram_support = true, | ||
761 | .led_compensation = 51, | ||
762 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
763 | .supports_idle = true, | ||
764 | .adv_thermal_throttle = true, | ||
765 | .support_ct_kill_exit = true, | ||
766 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
767 | .chain_noise_scale = 1000, | ||
768 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
769 | .max_event_log_size = 512, | ||
770 | }; | ||
771 | |||
448 | /* | 772 | /* |
449 | * "i": Internal configuration, use internal Power Amplifier | 773 | * "i": Internal configuration, use internal Power Amplifier |
450 | */ | 774 | */ |
@@ -667,3 +991,4 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
667 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 991 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
668 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); | 992 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); |
669 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | 993 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); |
994 | MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 7e8227773213..400eb312b555 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -96,17 +96,16 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
96 | hcmd.len = priv->calib_results[i].buf_len; | 96 | hcmd.len = priv->calib_results[i].buf_len; |
97 | hcmd.data = priv->calib_results[i].buf; | 97 | hcmd.data = priv->calib_results[i].buf; |
98 | ret = iwl_send_cmd_sync(priv, &hcmd); | 98 | ret = iwl_send_cmd_sync(priv, &hcmd); |
99 | if (ret) | 99 | if (ret) { |
100 | goto err; | 100 | IWL_ERR(priv, "Error %d iteration %d\n", |
101 | ret, i); | ||
102 | break; | ||
103 | } | ||
101 | } | 104 | } |
102 | } | 105 | } |
103 | 106 | ||
104 | return 0; | ||
105 | err: | ||
106 | IWL_ERR(priv, "Error %d iteration %d\n", ret, i); | ||
107 | return ret; | 107 | return ret; |
108 | } | 108 | } |
109 | EXPORT_SYMBOL(iwl_send_calib_results); | ||
110 | 109 | ||
111 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) | 110 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) |
112 | { | 111 | { |
@@ -121,7 +120,6 @@ int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) | |||
121 | memcpy(res->buf, buf, len); | 120 | memcpy(res->buf, buf, len); |
122 | return 0; | 121 | return 0; |
123 | } | 122 | } |
124 | EXPORT_SYMBOL(iwl_calib_set); | ||
125 | 123 | ||
126 | void iwl_calib_free_results(struct iwl_priv *priv) | 124 | void iwl_calib_free_results(struct iwl_priv *priv) |
127 | { | 125 | { |
@@ -133,7 +131,6 @@ void iwl_calib_free_results(struct iwl_priv *priv) | |||
133 | priv->calib_results[i].buf_len = 0; | 131 | priv->calib_results[i].buf_len = 0; |
134 | } | 132 | } |
135 | } | 133 | } |
136 | EXPORT_SYMBOL(iwl_calib_free_results); | ||
137 | 134 | ||
138 | /***************************************************************************** | 135 | /***************************************************************************** |
139 | * RUNTIME calibrations framework | 136 | * RUNTIME calibrations framework |
@@ -533,7 +530,6 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
533 | ret |= iwl_sensitivity_write(priv); | 530 | ret |= iwl_sensitivity_write(priv); |
534 | IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); | 531 | IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); |
535 | } | 532 | } |
536 | EXPORT_SYMBOL(iwl_init_sensitivity); | ||
537 | 533 | ||
538 | void iwl_sensitivity_calibration(struct iwl_priv *priv, | 534 | void iwl_sensitivity_calibration(struct iwl_priv *priv, |
539 | struct iwl_notif_statistics *resp) | 535 | struct iwl_notif_statistics *resp) |
@@ -639,7 +635,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
639 | iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); | 635 | iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); |
640 | iwl_sensitivity_write(priv); | 636 | iwl_sensitivity_write(priv); |
641 | } | 637 | } |
642 | EXPORT_SYMBOL(iwl_sensitivity_calibration); | ||
643 | 638 | ||
644 | static inline u8 find_first_chain(u8 mask) | 639 | static inline u8 find_first_chain(u8 mask) |
645 | { | 640 | { |
@@ -846,6 +841,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
846 | } | 841 | } |
847 | } | 842 | } |
848 | 843 | ||
844 | if (active_chains != priv->hw_params.valid_rx_ant && | ||
845 | active_chains != priv->chain_noise_data.active_chains) | ||
846 | IWL_WARN(priv, | ||
847 | "Detected that not all antennas are connected! " | ||
848 | "Connected: %#x, valid: %#x.\n", | ||
849 | active_chains, priv->hw_params.valid_rx_ant); | ||
850 | |||
849 | /* Save for use within RXON, TX, SCAN commands, etc. */ | 851 | /* Save for use within RXON, TX, SCAN commands, etc. */ |
850 | priv->chain_noise_data.active_chains = active_chains; | 852 | priv->chain_noise_data.active_chains = active_chains; |
851 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", | 853 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", |
@@ -890,8 +892,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
890 | data->state = IWL_CHAIN_NOISE_DONE; | 892 | data->state = IWL_CHAIN_NOISE_DONE; |
891 | iwl_power_update_mode(priv, false); | 893 | iwl_power_update_mode(priv, false); |
892 | } | 894 | } |
893 | EXPORT_SYMBOL(iwl_chain_noise_calibration); | ||
894 | |||
895 | 895 | ||
896 | void iwl_reset_run_time_calib(struct iwl_priv *priv) | 896 | void iwl_reset_run_time_calib(struct iwl_priv *priv) |
897 | { | 897 | { |
@@ -908,5 +908,3 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv) | |||
908 | * periodically after association */ | 908 | * periodically after association */ |
909 | iwl_send_statistics_request(priv, CMD_ASYNC, true); | 909 | iwl_send_statistics_request(priv, CMD_ASYNC, true); |
910 | } | 910 | } |
911 | EXPORT_SYMBOL(iwl_reset_run_time_calib); | ||
912 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 48c023b4ca36..75d6bfcbc607 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -28,6 +28,27 @@ | |||
28 | 28 | ||
29 | #include "iwl-agn-debugfs.h" | 29 | #include "iwl-agn-debugfs.h" |
30 | 30 | ||
31 | static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
32 | { | ||
33 | int p = 0; | ||
34 | |||
35 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
36 | le32_to_cpu(priv->_agn.statistics.flag)); | ||
37 | if (le32_to_cpu(priv->_agn.statistics.flag) & | ||
38 | UCODE_STATISTICS_CLEAR_MSK) | ||
39 | p += scnprintf(buf + p, bufsz - p, | ||
40 | "\tStatistics have been cleared\n"); | ||
41 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
42 | (le32_to_cpu(priv->_agn.statistics.flag) & | ||
43 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
44 | ? "2.4 GHz" : "5.2 GHz"); | ||
45 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
46 | (le32_to_cpu(priv->_agn.statistics.flag) & | ||
47 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
48 | ? "enabled" : "disabled"); | ||
49 | return p; | ||
50 | } | ||
51 | |||
31 | ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | 52 | ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, |
32 | size_t count, loff_t *ppos) | 53 | size_t count, loff_t *ppos) |
33 | { | 54 | { |
@@ -58,24 +79,24 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | |||
58 | * the last statistics notification from uCode | 79 | * the last statistics notification from uCode |
59 | * might not reflect the current uCode activity | 80 | * might not reflect the current uCode activity |
60 | */ | 81 | */ |
61 | ofdm = &priv->statistics.rx.ofdm; | 82 | ofdm = &priv->_agn.statistics.rx.ofdm; |
62 | cck = &priv->statistics.rx.cck; | 83 | cck = &priv->_agn.statistics.rx.cck; |
63 | general = &priv->statistics.rx.general; | 84 | general = &priv->_agn.statistics.rx.general; |
64 | ht = &priv->statistics.rx.ofdm_ht; | 85 | ht = &priv->_agn.statistics.rx.ofdm_ht; |
65 | accum_ofdm = &priv->accum_statistics.rx.ofdm; | 86 | accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; |
66 | accum_cck = &priv->accum_statistics.rx.cck; | 87 | accum_cck = &priv->_agn.accum_statistics.rx.cck; |
67 | accum_general = &priv->accum_statistics.rx.general; | 88 | accum_general = &priv->_agn.accum_statistics.rx.general; |
68 | accum_ht = &priv->accum_statistics.rx.ofdm_ht; | 89 | accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; |
69 | delta_ofdm = &priv->delta_statistics.rx.ofdm; | 90 | delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; |
70 | delta_cck = &priv->delta_statistics.rx.cck; | 91 | delta_cck = &priv->_agn.delta_statistics.rx.cck; |
71 | delta_general = &priv->delta_statistics.rx.general; | 92 | delta_general = &priv->_agn.delta_statistics.rx.general; |
72 | delta_ht = &priv->delta_statistics.rx.ofdm_ht; | 93 | delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; |
73 | max_ofdm = &priv->max_delta.rx.ofdm; | 94 | max_ofdm = &priv->_agn.max_delta.rx.ofdm; |
74 | max_cck = &priv->max_delta.rx.cck; | 95 | max_cck = &priv->_agn.max_delta.rx.cck; |
75 | max_general = &priv->max_delta.rx.general; | 96 | max_general = &priv->_agn.max_delta.rx.general; |
76 | max_ht = &priv->max_delta.rx.ofdm_ht; | 97 | max_ht = &priv->_agn.max_delta.rx.ofdm_ht; |
77 | 98 | ||
78 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 99 | pos += iwl_statistics_flag(priv, buf, bufsz); |
79 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 100 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
80 | "acumulative delta max\n", | 101 | "acumulative delta max\n", |
81 | "Statistics_Rx - OFDM:"); | 102 | "Statistics_Rx - OFDM:"); |
@@ -539,11 +560,11 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, | |||
539 | * the last statistics notification from uCode | 560 | * the last statistics notification from uCode |
540 | * might not reflect the current uCode activity | 561 | * might not reflect the current uCode activity |
541 | */ | 562 | */ |
542 | tx = &priv->statistics.tx; | 563 | tx = &priv->_agn.statistics.tx; |
543 | accum_tx = &priv->accum_statistics.tx; | 564 | accum_tx = &priv->_agn.accum_statistics.tx; |
544 | delta_tx = &priv->delta_statistics.tx; | 565 | delta_tx = &priv->_agn.delta_statistics.tx; |
545 | max_tx = &priv->max_delta.tx; | 566 | max_tx = &priv->_agn.max_delta.tx; |
546 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 567 | pos += iwl_statistics_flag(priv, buf, bufsz); |
547 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 568 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
548 | "acumulative delta max\n", | 569 | "acumulative delta max\n", |
549 | "Statistics_Tx:"); | 570 | "Statistics_Tx:"); |
@@ -756,19 +777,19 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
756 | * the last statistics notification from uCode | 777 | * the last statistics notification from uCode |
757 | * might not reflect the current uCode activity | 778 | * might not reflect the current uCode activity |
758 | */ | 779 | */ |
759 | general = &priv->statistics.general; | 780 | general = &priv->_agn.statistics.general; |
760 | dbg = &priv->statistics.general.dbg; | 781 | dbg = &priv->_agn.statistics.general.dbg; |
761 | div = &priv->statistics.general.div; | 782 | div = &priv->_agn.statistics.general.div; |
762 | accum_general = &priv->accum_statistics.general; | 783 | accum_general = &priv->_agn.accum_statistics.general; |
763 | delta_general = &priv->delta_statistics.general; | 784 | delta_general = &priv->_agn.delta_statistics.general; |
764 | max_general = &priv->max_delta.general; | 785 | max_general = &priv->_agn.max_delta.general; |
765 | accum_dbg = &priv->accum_statistics.general.dbg; | 786 | accum_dbg = &priv->_agn.accum_statistics.general.dbg; |
766 | delta_dbg = &priv->delta_statistics.general.dbg; | 787 | delta_dbg = &priv->_agn.delta_statistics.general.dbg; |
767 | max_dbg = &priv->max_delta.general.dbg; | 788 | max_dbg = &priv->_agn.max_delta.general.dbg; |
768 | accum_div = &priv->accum_statistics.general.div; | 789 | accum_div = &priv->_agn.accum_statistics.general.div; |
769 | delta_div = &priv->delta_statistics.general.div; | 790 | delta_div = &priv->_agn.delta_statistics.general.div; |
770 | max_div = &priv->max_delta.general.div; | 791 | max_div = &priv->_agn.max_delta.general.div; |
771 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 792 | pos += iwl_statistics_flag(priv, buf, bufsz); |
772 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | 793 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" |
773 | "acumulative delta max\n", | 794 | "acumulative delta max\n", |
774 | "Statistics_General:"); | 795 | "Statistics_General:"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 01658cf82d39..d89a11c6558e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
38 | #include "iwl-agn.h" | 38 | #include "iwl-agn.h" |
39 | 39 | ||
40 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | 40 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv) |
41 | { | 41 | { |
42 | int ret = 0; | 42 | int ret = 0; |
43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | 43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; |
@@ -84,7 +84,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | |||
84 | return ret; | 84 | return ret; |
85 | } | 85 | } |
86 | 86 | ||
87 | static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | 87 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) |
88 | { | 88 | { |
89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | 89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { |
90 | .valid = cpu_to_le32(valid_tx_ant), | 90 | .valid = cpu_to_le32(valid_tx_ant), |
@@ -176,14 +176,6 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, | |||
176 | data->radio_write = 1; | 176 | data->radio_write = 1; |
177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | 177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; |
178 | } | 178 | } |
179 | |||
180 | data->chain_noise_a = 0; | ||
181 | data->chain_noise_b = 0; | ||
182 | data->chain_noise_c = 0; | ||
183 | data->chain_signal_a = 0; | ||
184 | data->chain_signal_b = 0; | ||
185 | data->chain_signal_c = 0; | ||
186 | data->beacon_count = 0; | ||
187 | } | 179 | } |
188 | 180 | ||
189 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | 181 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) |
@@ -191,10 +183,20 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | |||
191 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 183 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
192 | int ret; | 184 | int ret; |
193 | 185 | ||
194 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | 186 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && |
187 | iwl_is_associated(priv)) { | ||
195 | struct iwl_calib_chain_noise_reset_cmd cmd; | 188 | struct iwl_calib_chain_noise_reset_cmd cmd; |
196 | memset(&cmd, 0, sizeof(cmd)); | ||
197 | 189 | ||
190 | /* clear data for chain noise calibration algorithm */ | ||
191 | data->chain_noise_a = 0; | ||
192 | data->chain_noise_b = 0; | ||
193 | data->chain_noise_c = 0; | ||
194 | data->chain_signal_a = 0; | ||
195 | data->chain_signal_b = 0; | ||
196 | data->chain_signal_c = 0; | ||
197 | data->beacon_count = 0; | ||
198 | |||
199 | memset(&cmd, 0, sizeof(cmd)); | ||
198 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | 200 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; |
199 | cmd.hdr.first_group = 0; | 201 | cmd.hdr.first_group = 0; |
200 | cmd.hdr.groups_num = 1; | 202 | cmd.hdr.groups_num = 1; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0f292a210ed9..5f1e7d802cbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -77,7 +77,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
77 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | 77 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", |
78 | agg->frame_count, agg->start_idx, idx); | 78 | agg->frame_count, agg->start_idx, idx); |
79 | 79 | ||
80 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 80 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); |
81 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 81 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
82 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 82 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
83 | info->flags |= iwl_tx_status_to_mac80211(status); | 83 | info->flags |= iwl_tx_status_to_mac80211(status); |
@@ -93,6 +93,12 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
93 | } else { | 93 | } else { |
94 | /* Two or more frames were attempted; expect block-ack */ | 94 | /* Two or more frames were attempted; expect block-ack */ |
95 | u64 bitmap = 0; | 95 | u64 bitmap = 0; |
96 | |||
97 | /* | ||
98 | * Start is the lowest frame sent. It may not be the first | ||
99 | * frame in the batch; we figure this out dynamically during | ||
100 | * the following loop. | ||
101 | */ | ||
96 | int start = agg->start_idx; | 102 | int start = agg->start_idx; |
97 | 103 | ||
98 | /* Construct bit-map of pending frames within Tx window */ | 104 | /* Construct bit-map of pending frames within Tx window */ |
@@ -131,25 +137,58 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | |||
131 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | 137 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", |
132 | i, idx, SEQ_TO_SN(sc)); | 138 | i, idx, SEQ_TO_SN(sc)); |
133 | 139 | ||
140 | /* | ||
141 | * sh -> how many frames ahead of the starting frame is | ||
142 | * the current one? | ||
143 | * | ||
144 | * Note that all frames sent in the batch must be in a | ||
145 | * 64-frame window, so this number should be in [0,63]. | ||
146 | * If outside of this window, then we've found a new | ||
147 | * "first" frame in the batch and need to change start. | ||
148 | */ | ||
134 | sh = idx - start; | 149 | sh = idx - start; |
135 | if (sh > 64) { | 150 | |
136 | sh = (start - idx) + 0xff; | 151 | /* |
152 | * If >= 64, out of window. start must be at the front | ||
153 | * of the circular buffer, idx must be near the end of | ||
154 | * the buffer, and idx is the new "first" frame. Shift | ||
155 | * the indices around. | ||
156 | */ | ||
157 | if (sh >= 64) { | ||
158 | /* Shift bitmap by start - idx, wrapped */ | ||
159 | sh = 0x100 - idx + start; | ||
137 | bitmap = bitmap << sh; | 160 | bitmap = bitmap << sh; |
161 | /* Now idx is the new start so sh = 0 */ | ||
138 | sh = 0; | 162 | sh = 0; |
139 | start = idx; | 163 | start = idx; |
140 | } else if (sh < -64) | 164 | /* |
141 | sh = 0xff - (start - idx); | 165 | * If <= -64 then wraps the 256-pkt circular buffer |
142 | else if (sh < 0) { | 166 | * (e.g., start = 255 and idx = 0, sh should be 1) |
167 | */ | ||
168 | } else if (sh <= -64) { | ||
169 | sh = 0x100 - start + idx; | ||
170 | /* | ||
171 | * If < 0 but > -64, out of window. idx is before start | ||
172 | * but not wrapped. Shift the indices around. | ||
173 | */ | ||
174 | } else if (sh < 0) { | ||
175 | /* Shift by how far start is ahead of idx */ | ||
143 | sh = start - idx; | 176 | sh = start - idx; |
144 | start = idx; | ||
145 | bitmap = bitmap << sh; | 177 | bitmap = bitmap << sh; |
178 | /* Now idx is the new start so sh = 0 */ | ||
179 | start = idx; | ||
146 | sh = 0; | 180 | sh = 0; |
147 | } | 181 | } |
182 | /* Sequence number start + sh was sent in this batch */ | ||
148 | bitmap |= 1ULL << sh; | 183 | bitmap |= 1ULL << sh; |
149 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | 184 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", |
150 | start, (unsigned long long)bitmap); | 185 | start, (unsigned long long)bitmap); |
151 | } | 186 | } |
152 | 187 | ||
188 | /* | ||
189 | * Store the bitmap and possibly the new start, if we wrapped | ||
190 | * the buffer above | ||
191 | */ | ||
153 | agg->bitmap = bitmap; | 192 | agg->bitmap = bitmap; |
154 | agg->start_idx = start; | 193 | agg->start_idx = start; |
155 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | 194 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", |
@@ -184,6 +223,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
184 | int tid; | 223 | int tid; |
185 | int sta_id; | 224 | int sta_id; |
186 | int freed; | 225 | int freed; |
226 | unsigned long flags; | ||
187 | 227 | ||
188 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | 228 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { |
189 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | 229 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " |
@@ -193,15 +233,16 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
193 | return; | 233 | return; |
194 | } | 234 | } |
195 | 235 | ||
196 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 236 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); |
197 | memset(&info->status, 0, sizeof(info->status)); | 237 | memset(&info->status, 0, sizeof(info->status)); |
198 | 238 | ||
199 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | 239 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; |
200 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | 240 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; |
201 | 241 | ||
242 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
202 | if (txq->sched_retry) { | 243 | if (txq->sched_retry) { |
203 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); | 244 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); |
204 | struct iwl_ht_agg *agg = NULL; | 245 | struct iwl_ht_agg *agg; |
205 | 246 | ||
206 | agg = &priv->stations[sta_id].tid[tid].agg; | 247 | agg = &priv->stations[sta_id].tid[tid].agg; |
207 | 248 | ||
@@ -256,6 +297,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | |||
256 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | 297 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
257 | 298 | ||
258 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 299 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
300 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
259 | } | 301 | } |
260 | 302 | ||
261 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) | 303 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) |
@@ -319,7 +361,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
319 | void iwlagn_temperature(struct iwl_priv *priv) | 361 | void iwlagn_temperature(struct iwl_priv *priv) |
320 | { | 362 | { |
321 | /* store temperature from statistics (in Celsius) */ | 363 | /* store temperature from statistics (in Celsius) */ |
322 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | 364 | priv->temperature = |
365 | le32_to_cpu(priv->_agn.statistics.general.temperature); | ||
323 | iwl_tt_handler(priv); | 366 | iwl_tt_handler(priv); |
324 | } | 367 | } |
325 | 368 | ||
@@ -444,7 +487,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
444 | 487 | ||
445 | /* Tell device where to find RBD circular buffer in DRAM */ | 488 | /* Tell device where to find RBD circular buffer in DRAM */ |
446 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | 489 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, |
447 | (u32)(rxq->dma_addr >> 8)); | 490 | (u32)(rxq->bd_dma >> 8)); |
448 | 491 | ||
449 | /* Tell device where in DRAM to update its Rx status */ | 492 | /* Tell device where in DRAM to update its Rx status */ |
450 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | 493 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, |
@@ -709,7 +752,7 @@ void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
709 | } | 752 | } |
710 | 753 | ||
711 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 754 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
712 | rxq->dma_addr); | 755 | rxq->bd_dma); |
713 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | 756 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
714 | rxq->rb_stts, rxq->rb_stts_dma); | 757 | rxq->rb_stts, rxq->rb_stts_dma); |
715 | rxq->bd = NULL; | 758 | rxq->bd = NULL; |
@@ -755,132 +798,6 @@ static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
755 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | 798 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); |
756 | } | 799 | } |
757 | 800 | ||
758 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
759 | /** | ||
760 | * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions | ||
761 | * | ||
762 | * You may hack this function to show different aspects of received frames, | ||
763 | * including selective frame dumps. | ||
764 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
765 | * All beacon and probe response frames are printed. | ||
766 | */ | ||
767 | static void iwlagn_dbg_report_frame(struct iwl_priv *priv, | ||
768 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
769 | struct ieee80211_hdr *header, int group100) | ||
770 | { | ||
771 | u32 to_us; | ||
772 | u32 print_summary = 0; | ||
773 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
774 | u32 hundred = 0; | ||
775 | u32 dataframe = 0; | ||
776 | __le16 fc; | ||
777 | u16 seq_ctl; | ||
778 | u16 channel; | ||
779 | u16 phy_flags; | ||
780 | u32 rate_n_flags; | ||
781 | u32 tsf_low; | ||
782 | int rssi; | ||
783 | |||
784 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
785 | return; | ||
786 | |||
787 | /* MAC header */ | ||
788 | fc = header->frame_control; | ||
789 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
790 | |||
791 | /* metadata */ | ||
792 | channel = le16_to_cpu(phy_res->channel); | ||
793 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
794 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
795 | |||
796 | /* signal statistics */ | ||
797 | rssi = iwlagn_calc_rssi(priv, phy_res); | ||
798 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
799 | |||
800 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
801 | |||
802 | /* if data frame is to us and all is good, | ||
803 | * (optionally) print summary for only 1 out of every 100 */ | ||
804 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
805 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
806 | dataframe = 1; | ||
807 | if (!group100) | ||
808 | print_summary = 1; /* print each frame */ | ||
809 | else if (priv->framecnt_to_us < 100) { | ||
810 | priv->framecnt_to_us++; | ||
811 | print_summary = 0; | ||
812 | } else { | ||
813 | priv->framecnt_to_us = 0; | ||
814 | print_summary = 1; | ||
815 | hundred = 1; | ||
816 | } | ||
817 | } else { | ||
818 | /* print summary for all other frames */ | ||
819 | print_summary = 1; | ||
820 | } | ||
821 | |||
822 | if (print_summary) { | ||
823 | char *title; | ||
824 | int rate_idx; | ||
825 | u32 bitrate; | ||
826 | |||
827 | if (hundred) | ||
828 | title = "100Frames"; | ||
829 | else if (ieee80211_has_retry(fc)) | ||
830 | title = "Retry"; | ||
831 | else if (ieee80211_is_assoc_resp(fc)) | ||
832 | title = "AscRsp"; | ||
833 | else if (ieee80211_is_reassoc_resp(fc)) | ||
834 | title = "RasRsp"; | ||
835 | else if (ieee80211_is_probe_resp(fc)) { | ||
836 | title = "PrbRsp"; | ||
837 | print_dump = 1; /* dump frame contents */ | ||
838 | } else if (ieee80211_is_beacon(fc)) { | ||
839 | title = "Beacon"; | ||
840 | print_dump = 1; /* dump frame contents */ | ||
841 | } else if (ieee80211_is_atim(fc)) | ||
842 | title = "ATIM"; | ||
843 | else if (ieee80211_is_auth(fc)) | ||
844 | title = "Auth"; | ||
845 | else if (ieee80211_is_deauth(fc)) | ||
846 | title = "DeAuth"; | ||
847 | else if (ieee80211_is_disassoc(fc)) | ||
848 | title = "DisAssoc"; | ||
849 | else | ||
850 | title = "Frame"; | ||
851 | |||
852 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
853 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
854 | bitrate = 0; | ||
855 | WARN_ON_ONCE(1); | ||
856 | } else { | ||
857 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
858 | } | ||
859 | |||
860 | /* print frame summary. | ||
861 | * MAC addresses show just the last byte (for brevity), | ||
862 | * but you can hack it to show more, if you'd like to. */ | ||
863 | if (dataframe) | ||
864 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
865 | "len=%u, rssi=%d, chnl=%d, rate=%u,\n", | ||
866 | title, le16_to_cpu(fc), header->addr1[5], | ||
867 | length, rssi, channel, bitrate); | ||
868 | else { | ||
869 | /* src/dst addresses assume managed mode */ | ||
870 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
871 | "len=%u, rssi=%d, tim=%lu usec, " | ||
872 | "phy=0x%02x, chnl=%d\n", | ||
873 | title, le16_to_cpu(fc), header->addr1[5], | ||
874 | header->addr3[5], length, rssi, | ||
875 | tsf_low - priv->scan_start_tsf, | ||
876 | phy_flags, channel); | ||
877 | } | ||
878 | } | ||
879 | if (print_dump) | ||
880 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
881 | } | ||
882 | #endif | ||
883 | |||
884 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | 801 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) |
885 | { | 802 | { |
886 | u32 decrypt_out = 0; | 803 | u32 decrypt_out = 0; |
@@ -988,7 +905,7 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
988 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 905 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
989 | struct iwl_rx_phy_res *phy_res; | 906 | struct iwl_rx_phy_res *phy_res; |
990 | __le32 rx_pkt_status; | 907 | __le32 rx_pkt_status; |
991 | struct iwl4965_rx_mpdu_res_start *amsdu; | 908 | struct iwl_rx_mpdu_res_start *amsdu; |
992 | u32 len; | 909 | u32 len; |
993 | u32 ampdu_status; | 910 | u32 ampdu_status; |
994 | u32 rate_n_flags; | 911 | u32 rate_n_flags; |
@@ -1017,7 +934,7 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
1017 | return; | 934 | return; |
1018 | } | 935 | } |
1019 | phy_res = &priv->_agn.last_phy_res; | 936 | phy_res = &priv->_agn.last_phy_res; |
1020 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | 937 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; |
1021 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | 938 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); |
1022 | len = le16_to_cpu(amsdu->byte_count); | 939 | len = le16_to_cpu(amsdu->byte_count); |
1023 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | 940 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); |
@@ -1060,11 +977,6 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
1060 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | 977 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ |
1061 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | 978 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); |
1062 | 979 | ||
1063 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1064 | /* Set "1" to report good data frames in groups of 100 */ | ||
1065 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1066 | iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1067 | #endif | ||
1068 | iwl_dbg_log_rx_data_frame(priv, len, header); | 980 | iwl_dbg_log_rx_data_frame(priv, len, header); |
1069 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | 981 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", |
1070 | rx_status.signal, (unsigned long long)rx_status.mactime); | 982 | rx_status.signal, (unsigned long long)rx_status.mactime); |
@@ -1252,6 +1164,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1252 | bool is_active = false; | 1164 | bool is_active = false; |
1253 | int chan_mod; | 1165 | int chan_mod; |
1254 | u8 active_chains; | 1166 | u8 active_chains; |
1167 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | ||
1255 | 1168 | ||
1256 | conf = ieee80211_get_hw_conf(priv->hw); | 1169 | conf = ieee80211_get_hw_conf(priv->hw); |
1257 | 1170 | ||
@@ -1403,11 +1316,14 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1403 | 1316 | ||
1404 | band = priv->scan_band; | 1317 | band = priv->scan_band; |
1405 | 1318 | ||
1406 | if (priv->cfg->scan_antennas[band]) | 1319 | if (priv->cfg->scan_rx_antennas[band]) |
1407 | rx_ant = priv->cfg->scan_antennas[band]; | 1320 | rx_ant = priv->cfg->scan_rx_antennas[band]; |
1408 | 1321 | ||
1409 | priv->scan_tx_ant[band] = | 1322 | if (priv->cfg->scan_tx_antennas[band]) |
1410 | iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); | 1323 | scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; |
1324 | |||
1325 | priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], | ||
1326 | scan_tx_antennas); | ||
1411 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | 1327 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); |
1412 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | 1328 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); |
1413 | 1329 | ||
@@ -1433,13 +1349,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1433 | if (!priv->is_internal_short_scan) { | 1349 | if (!priv->is_internal_short_scan) { |
1434 | cmd_len = iwl_fill_probe_req(priv, | 1350 | cmd_len = iwl_fill_probe_req(priv, |
1435 | (struct ieee80211_mgmt *)scan->data, | 1351 | (struct ieee80211_mgmt *)scan->data, |
1352 | vif->addr, | ||
1436 | priv->scan_request->ie, | 1353 | priv->scan_request->ie, |
1437 | priv->scan_request->ie_len, | 1354 | priv->scan_request->ie_len, |
1438 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 1355 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); |
1439 | } else { | 1356 | } else { |
1357 | /* use bcast addr, will not be transmitted but must be valid */ | ||
1440 | cmd_len = iwl_fill_probe_req(priv, | 1358 | cmd_len = iwl_fill_probe_req(priv, |
1441 | (struct ieee80211_mgmt *)scan->data, | 1359 | (struct ieee80211_mgmt *)scan->data, |
1442 | NULL, 0, | 1360 | iwl_bcast_addr, NULL, 0, |
1443 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 1361 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); |
1444 | 1362 | ||
1445 | } | 1363 | } |
@@ -1502,3 +1420,18 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
1502 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, | 1420 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, |
1503 | vif->bss_conf.bssid); | 1421 | vif->bss_conf.bssid); |
1504 | } | 1422 | } |
1423 | |||
1424 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
1425 | int sta_id, int tid, int freed) | ||
1426 | { | ||
1427 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | ||
1428 | |||
1429 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | ||
1430 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
1431 | else { | ||
1432 | IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", | ||
1433 | priv->stations[sta_id].tid[tid].tfds_in_queue, | ||
1434 | freed); | ||
1435 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | ||
1436 | } | ||
1437 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cf4a95bae4ff..40933a5de027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -313,8 +313,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
313 | */ | 313 | */ |
314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | 314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", |
315 | tid); | 315 | tid); |
316 | ieee80211_stop_tx_ba_session(sta, tid, | 316 | ieee80211_stop_tx_ba_session(sta, tid); |
317 | WLAN_BACK_INITIATOR); | ||
318 | } | 317 | } |
319 | } else | 318 | } else |
320 | IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); | 319 | IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c new file mode 100644 index 000000000000..ad2bead25c82 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-calib.h" | ||
38 | #include "iwl-sta.h" | ||
39 | #include "iwl-io.h" | ||
40 | #include "iwl-helpers.h" | ||
41 | #include "iwl-agn-hw.h" | ||
42 | #include "iwl-agn.h" | ||
43 | |||
44 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
45 | struct iwl_rx_mem_buffer *rxb) | ||
46 | |||
47 | { | ||
48 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
49 | struct iwl_missed_beacon_notif *missed_beacon; | ||
50 | |||
51 | missed_beacon = &pkt->u.missed_beacon; | ||
52 | if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) > | ||
53 | priv->missed_beacon_threshold) { | ||
54 | IWL_DEBUG_CALIB(priv, | ||
55 | "missed bcn cnsq %d totl %d rcd %d expctd %d\n", | ||
56 | le32_to_cpu(missed_beacon->consecutive_missed_beacons), | ||
57 | le32_to_cpu(missed_beacon->total_missed_becons), | ||
58 | le32_to_cpu(missed_beacon->num_recvd_beacons), | ||
59 | le32_to_cpu(missed_beacon->num_expected_beacons)); | ||
60 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
61 | iwl_init_sensitivity(priv); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | /* Calculate noise level, based on measurements during network silence just | ||
66 | * before arriving beacon. This measurement can be done only if we know | ||
67 | * exactly when to expect beacons, therefore only when we're associated. */ | ||
68 | static void iwl_rx_calc_noise(struct iwl_priv *priv) | ||
69 | { | ||
70 | struct statistics_rx_non_phy *rx_info | ||
71 | = &(priv->_agn.statistics.rx.general); | ||
72 | int num_active_rx = 0; | ||
73 | int total_silence = 0; | ||
74 | int bcn_silence_a = | ||
75 | le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; | ||
76 | int bcn_silence_b = | ||
77 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | ||
78 | int bcn_silence_c = | ||
79 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | ||
80 | int last_rx_noise; | ||
81 | |||
82 | if (bcn_silence_a) { | ||
83 | total_silence += bcn_silence_a; | ||
84 | num_active_rx++; | ||
85 | } | ||
86 | if (bcn_silence_b) { | ||
87 | total_silence += bcn_silence_b; | ||
88 | num_active_rx++; | ||
89 | } | ||
90 | if (bcn_silence_c) { | ||
91 | total_silence += bcn_silence_c; | ||
92 | num_active_rx++; | ||
93 | } | ||
94 | |||
95 | /* Average among active antennas */ | ||
96 | if (num_active_rx) | ||
97 | last_rx_noise = (total_silence / num_active_rx) - 107; | ||
98 | else | ||
99 | last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
100 | |||
101 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", | ||
102 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | ||
103 | last_rx_noise); | ||
104 | } | ||
105 | |||
106 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
107 | /* | ||
108 | * based on the assumption of all statistics counter are in DWORD | ||
109 | * FIXME: This function is for debugging, do not deal with | ||
110 | * the case of counters roll-over. | ||
111 | */ | ||
112 | static void iwl_accumulative_statistics(struct iwl_priv *priv, | ||
113 | __le32 *stats) | ||
114 | { | ||
115 | int i; | ||
116 | __le32 *prev_stats; | ||
117 | u32 *accum_stats; | ||
118 | u32 *delta, *max_delta; | ||
119 | |||
120 | prev_stats = (__le32 *)&priv->_agn.statistics; | ||
121 | accum_stats = (u32 *)&priv->_agn.accum_statistics; | ||
122 | delta = (u32 *)&priv->_agn.delta_statistics; | ||
123 | max_delta = (u32 *)&priv->_agn.max_delta; | ||
124 | |||
125 | for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); | ||
126 | i += sizeof(__le32), stats++, prev_stats++, delta++, | ||
127 | max_delta++, accum_stats++) { | ||
128 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { | ||
129 | *delta = (le32_to_cpu(*stats) - | ||
130 | le32_to_cpu(*prev_stats)); | ||
131 | *accum_stats += *delta; | ||
132 | if (*delta > *max_delta) | ||
133 | *max_delta = *delta; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* reset accumulative statistics for "no-counter" type statistics */ | ||
138 | priv->_agn.accum_statistics.general.temperature = | ||
139 | priv->_agn.statistics.general.temperature; | ||
140 | priv->_agn.accum_statistics.general.temperature_m = | ||
141 | priv->_agn.statistics.general.temperature_m; | ||
142 | priv->_agn.accum_statistics.general.ttl_timestamp = | ||
143 | priv->_agn.statistics.general.ttl_timestamp; | ||
144 | priv->_agn.accum_statistics.tx.tx_power.ant_a = | ||
145 | priv->_agn.statistics.tx.tx_power.ant_a; | ||
146 | priv->_agn.accum_statistics.tx.tx_power.ant_b = | ||
147 | priv->_agn.statistics.tx.tx_power.ant_b; | ||
148 | priv->_agn.accum_statistics.tx.tx_power.ant_c = | ||
149 | priv->_agn.statistics.tx.tx_power.ant_c; | ||
150 | } | ||
151 | #endif | ||
152 | |||
153 | #define REG_RECALIB_PERIOD (60) | ||
154 | |||
155 | /** | ||
156 | * iwl_good_plcp_health - checks for plcp error. | ||
157 | * | ||
158 | * When the plcp error is exceeding the thresholds, reset the radio | ||
159 | * to improve the throughput. | ||
160 | */ | ||
161 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
162 | struct iwl_rx_packet *pkt) | ||
163 | { | ||
164 | bool rc = true; | ||
165 | int combined_plcp_delta; | ||
166 | unsigned int plcp_msec; | ||
167 | unsigned long plcp_received_jiffies; | ||
168 | |||
169 | /* | ||
170 | * check for plcp_err and trigger radio reset if it exceeds | ||
171 | * the plcp error threshold plcp_delta. | ||
172 | */ | ||
173 | plcp_received_jiffies = jiffies; | ||
174 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
175 | (long) priv->plcp_jiffies); | ||
176 | priv->plcp_jiffies = plcp_received_jiffies; | ||
177 | /* | ||
178 | * check to make sure plcp_msec is not 0 to prevent division | ||
179 | * by zero. | ||
180 | */ | ||
181 | if (plcp_msec) { | ||
182 | combined_plcp_delta = | ||
183 | (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - | ||
184 | le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) + | ||
185 | (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - | ||
186 | le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err)); | ||
187 | |||
188 | if ((combined_plcp_delta > 0) && | ||
189 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
190 | priv->cfg->plcp_delta_threshold) { | ||
191 | /* | ||
192 | * if plcp_err exceed the threshold, | ||
193 | * the following data is printed in csv format: | ||
194 | * Text: plcp_err exceeded %d, | ||
195 | * Received ofdm.plcp_err, | ||
196 | * Current ofdm.plcp_err, | ||
197 | * Received ofdm_ht.plcp_err, | ||
198 | * Current ofdm_ht.plcp_err, | ||
199 | * combined_plcp_delta, | ||
200 | * plcp_msec | ||
201 | */ | ||
202 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | ||
203 | "%u, %u, %u, %u, %d, %u mSecs\n", | ||
204 | priv->cfg->plcp_delta_threshold, | ||
205 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | ||
206 | le32_to_cpu( | ||
207 | priv->_agn.statistics.rx.ofdm.plcp_err), | ||
208 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | ||
209 | le32_to_cpu( | ||
210 | priv->_agn.statistics.rx.ofdm_ht.plcp_err), | ||
211 | combined_plcp_delta, plcp_msec); | ||
212 | rc = false; | ||
213 | } | ||
214 | } | ||
215 | return rc; | ||
216 | } | ||
217 | |||
218 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
219 | struct iwl_rx_mem_buffer *rxb) | ||
220 | { | ||
221 | int change; | ||
222 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
223 | |||
224 | |||
225 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
226 | (int)sizeof(priv->_agn.statistics), | ||
227 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
228 | |||
229 | change = ((priv->_agn.statistics.general.temperature != | ||
230 | pkt->u.stats.general.temperature) || | ||
231 | ((priv->_agn.statistics.flag & | ||
232 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | ||
233 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | ||
234 | |||
235 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
236 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
237 | #endif | ||
238 | iwl_recover_from_statistics(priv, pkt); | ||
239 | |||
240 | memcpy(&priv->_agn.statistics, &pkt->u.stats, | ||
241 | sizeof(priv->_agn.statistics)); | ||
242 | |||
243 | set_bit(STATUS_STATISTICS, &priv->status); | ||
244 | |||
245 | /* Reschedule the statistics timer to occur in | ||
246 | * REG_RECALIB_PERIOD seconds to ensure we get a | ||
247 | * thermal update even if the uCode doesn't give | ||
248 | * us one */ | ||
249 | mod_timer(&priv->statistics_periodic, jiffies + | ||
250 | msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); | ||
251 | |||
252 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | ||
253 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { | ||
254 | iwl_rx_calc_noise(priv); | ||
255 | queue_work(priv->workqueue, &priv->run_time_calib_work); | ||
256 | } | ||
257 | if (priv->cfg->ops->lib->temp_ops.temperature && change) | ||
258 | priv->cfg->ops->lib->temp_ops.temperature(priv); | ||
259 | } | ||
260 | |||
261 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
262 | struct iwl_rx_mem_buffer *rxb) | ||
263 | { | ||
264 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
265 | |||
266 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { | ||
267 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
268 | memset(&priv->_agn.accum_statistics, 0, | ||
269 | sizeof(struct iwl_notif_statistics)); | ||
270 | memset(&priv->_agn.delta_statistics, 0, | ||
271 | sizeof(struct iwl_notif_statistics)); | ||
272 | memset(&priv->_agn.max_delta, 0, | ||
273 | sizeof(struct iwl_notif_statistics)); | ||
274 | #endif | ||
275 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | ||
276 | } | ||
277 | iwl_rx_statistics(priv, rxb); | ||
278 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7d614c4d3c62..2573234e4db1 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; |
@@ -1009,6 +1021,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1009 | if (ret) | 1021 | if (ret) |
1010 | return ret; | 1022 | return ret; |
1011 | 1023 | ||
1024 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1025 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1012 | if (tid_data->tfds_in_queue == 0) { | 1026 | if (tid_data->tfds_in_queue == 0) { |
1013 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1027 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1014 | tid_data->agg.state = IWL_AGG_ON; | 1028 | tid_data->agg.state = IWL_AGG_ON; |
@@ -1018,6 +1032,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1018 | tid_data->tfds_in_queue); | 1032 | tid_data->tfds_in_queue); |
1019 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | 1033 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; |
1020 | } | 1034 | } |
1035 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1021 | return ret; | 1036 | return ret; |
1022 | } | 1037 | } |
1023 | 1038 | ||
@@ -1040,11 +1055,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1040 | return -ENXIO; | 1055 | return -ENXIO; |
1041 | } | 1056 | } |
1042 | 1057 | ||
1058 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1059 | |||
1043 | if (priv->stations[sta_id].tid[tid].agg.state == | 1060 | if (priv->stations[sta_id].tid[tid].agg.state == |
1044 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | 1061 | IWL_EMPTYING_HW_QUEUE_ADDBA) { |
1045 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | 1062 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); |
1046 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1063 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1047 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1064 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1065 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1048 | return 0; | 1066 | return 0; |
1049 | } | 1067 | } |
1050 | 1068 | ||
@@ -1062,13 +1080,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"); | 1080 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); |
1063 | priv->stations[sta_id].tid[tid].agg.state = | 1081 | priv->stations[sta_id].tid[tid].agg.state = |
1064 | IWL_EMPTYING_HW_QUEUE_DELBA; | 1082 | IWL_EMPTYING_HW_QUEUE_DELBA; |
1083 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1065 | return 0; | 1084 | return 0; |
1066 | } | 1085 | } |
1067 | 1086 | ||
1068 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1087 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1069 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1088 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1070 | 1089 | ||
1071 | spin_lock_irqsave(&priv->lock, flags); | 1090 | /* do not restore/save irqs */ |
1091 | spin_unlock(&priv->sta_lock); | ||
1092 | spin_lock(&priv->lock); | ||
1093 | |||
1072 | /* | 1094 | /* |
1073 | * the only reason this call can fail is queue number out of range, | 1095 | * 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 | 1096 | * which can happen if uCode is reloaded and all the station |
@@ -1092,6 +1114,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1092 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | 1114 | u8 *addr = priv->stations[sta_id].sta.sta.addr; |
1093 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | 1115 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; |
1094 | 1116 | ||
1117 | WARN_ON(!spin_is_locked(&priv->sta_lock)); | ||
1118 | |||
1095 | switch (priv->stations[sta_id].tid[tid].agg.state) { | 1119 | switch (priv->stations[sta_id].tid[tid].agg.state) { |
1096 | case IWL_EMPTYING_HW_QUEUE_DELBA: | 1120 | case IWL_EMPTYING_HW_QUEUE_DELBA: |
1097 | /* We are reclaiming the last packet of the */ | 1121 | /* We are reclaiming the last packet of the */ |
@@ -1116,6 +1140,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1116 | } | 1140 | } |
1117 | break; | 1141 | break; |
1118 | } | 1142 | } |
1143 | |||
1119 | return 0; | 1144 | return 0; |
1120 | } | 1145 | } |
1121 | 1146 | ||
@@ -1159,12 +1184,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)) { | 1184 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1160 | 1185 | ||
1161 | tx_info = &txq->txb[txq->q.read_ptr]; | 1186 | tx_info = &txq->txb[txq->q.read_ptr]; |
1162 | iwlagn_tx_status(priv, tx_info->skb[0]); | 1187 | iwlagn_tx_status(priv, tx_info->skb); |
1163 | 1188 | ||
1164 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | 1189 | hdr = (struct ieee80211_hdr *)tx_info->skb->data; |
1165 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | 1190 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) |
1166 | nfreed++; | 1191 | nfreed++; |
1167 | tx_info->skb[0] = NULL; | 1192 | tx_info->skb = NULL; |
1168 | 1193 | ||
1169 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | 1194 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) |
1170 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | 1195 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); |
@@ -1188,7 +1213,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1188 | int i, sh, ack; | 1213 | int i, sh, ack; |
1189 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | 1214 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); |
1190 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 1215 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
1191 | u64 bitmap; | 1216 | u64 bitmap, sent_bitmap; |
1192 | int successes = 0; | 1217 | int successes = 0; |
1193 | struct ieee80211_tx_info *info; | 1218 | struct ieee80211_tx_info *info; |
1194 | 1219 | ||
@@ -1216,24 +1241,26 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1216 | 1241 | ||
1217 | /* check for success or failure according to the | 1242 | /* check for success or failure according to the |
1218 | * transmitted bitmap and block-ack bitmap */ | 1243 | * transmitted bitmap and block-ack bitmap */ |
1219 | bitmap &= agg->bitmap; | 1244 | sent_bitmap = bitmap & agg->bitmap; |
1220 | 1245 | ||
1221 | /* For each frame attempted in aggregation, | 1246 | /* For each frame attempted in aggregation, |
1222 | * update driver's record of tx frame's status. */ | 1247 | * update driver's record of tx frame's status. */ |
1223 | for (i = 0; i < agg->frame_count ; i++) { | 1248 | i = 0; |
1224 | ack = bitmap & (1ULL << i); | 1249 | while (sent_bitmap) { |
1225 | successes += !!ack; | 1250 | ack = sent_bitmap & 1ULL; |
1251 | successes += ack; | ||
1226 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | 1252 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", |
1227 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | 1253 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, |
1228 | agg->start_idx + i); | 1254 | agg->start_idx + i); |
1255 | sent_bitmap >>= 1; | ||
1256 | ++i; | ||
1229 | } | 1257 | } |
1230 | 1258 | ||
1231 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | 1259 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); |
1232 | memset(&info->status, 0, sizeof(info->status)); | 1260 | memset(&info->status, 0, sizeof(info->status)); |
1233 | info->flags |= IEEE80211_TX_STAT_ACK; | 1261 | info->flags |= IEEE80211_TX_STAT_ACK; |
1234 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 1262 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
1235 | info->status.ampdu_ack_len = successes; | 1263 | info->status.ampdu_ack_len = successes; |
1236 | info->status.ampdu_ack_map = bitmap; | ||
1237 | info->status.ampdu_len = agg->frame_count; | 1264 | info->status.ampdu_len = agg->frame_count; |
1238 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | 1265 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); |
1239 | 1266 | ||
@@ -1281,6 +1308,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1281 | int index; | 1308 | int index; |
1282 | int sta_id; | 1309 | int sta_id; |
1283 | int tid; | 1310 | int tid; |
1311 | unsigned long flags; | ||
1284 | 1312 | ||
1285 | /* "flow" corresponds to Tx queue */ | 1313 | /* "flow" corresponds to Tx queue */ |
1286 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | 1314 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); |
@@ -1308,7 +1336,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1308 | /* Find index just before block-ack window */ | 1336 | /* Find index just before block-ack window */ |
1309 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | 1337 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); |
1310 | 1338 | ||
1311 | /* TODO: Need to get this copy more safely - now good for debug */ | 1339 | spin_lock_irqsave(&priv->sta_lock, flags); |
1312 | 1340 | ||
1313 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | 1341 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " |
1314 | "sta_id = %d\n", | 1342 | "sta_id = %d\n", |
@@ -1344,4 +1372,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1344 | 1372 | ||
1345 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); | 1373 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); |
1346 | } | 1374 | } |
1375 | |||
1376 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1347 | } | 1377 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 637286c396fe..6f77441cb65a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -423,3 +423,126 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
423 | 423 | ||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | |||
427 | |||
428 | /** | ||
429 | * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, | ||
430 | * using sample data 100 bytes apart. If these sample points are good, | ||
431 | * it's a pretty good bet that everything between them is good, too. | ||
432 | */ | ||
433 | static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) | ||
434 | { | ||
435 | u32 val; | ||
436 | int ret = 0; | ||
437 | u32 errcnt = 0; | ||
438 | u32 i; | ||
439 | |||
440 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
441 | |||
442 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | ||
443 | /* read data comes through single port, auto-incr addr */ | ||
444 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
445 | * if IWL_DL_IO is set */ | ||
446 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
447 | i + IWLAGN_RTC_INST_LOWER_BOUND); | ||
448 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
449 | if (val != le32_to_cpu(*image)) { | ||
450 | ret = -EIO; | ||
451 | errcnt++; | ||
452 | if (errcnt >= 3) | ||
453 | break; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | /** | ||
461 | * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, | ||
462 | * looking at all data. | ||
463 | */ | ||
464 | static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, | ||
465 | u32 len) | ||
466 | { | ||
467 | u32 val; | ||
468 | u32 save_len = len; | ||
469 | int ret = 0; | ||
470 | u32 errcnt; | ||
471 | |||
472 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
473 | |||
474 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
475 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
476 | |||
477 | errcnt = 0; | ||
478 | for (; len > 0; len -= sizeof(u32), image++) { | ||
479 | /* read data comes through single port, auto-incr addr */ | ||
480 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
481 | * if IWL_DL_IO is set */ | ||
482 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
483 | if (val != le32_to_cpu(*image)) { | ||
484 | IWL_ERR(priv, "uCode INST section is invalid at " | ||
485 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
486 | save_len - len, val, le32_to_cpu(*image)); | ||
487 | ret = -EIO; | ||
488 | errcnt++; | ||
489 | if (errcnt >= 20) | ||
490 | break; | ||
491 | } | ||
492 | } | ||
493 | |||
494 | if (!errcnt) | ||
495 | IWL_DEBUG_INFO(priv, | ||
496 | "ucode image in INSTRUCTION memory is good\n"); | ||
497 | |||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | /** | ||
502 | * iwl_verify_ucode - determine which instruction image is in SRAM, | ||
503 | * and verify its contents | ||
504 | */ | ||
505 | int iwl_verify_ucode(struct iwl_priv *priv) | ||
506 | { | ||
507 | __le32 *image; | ||
508 | u32 len; | ||
509 | int ret; | ||
510 | |||
511 | /* Try bootstrap */ | ||
512 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
513 | len = priv->ucode_boot.len; | ||
514 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
515 | if (!ret) { | ||
516 | IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* Try initialize */ | ||
521 | image = (__le32 *)priv->ucode_init.v_addr; | ||
522 | len = priv->ucode_init.len; | ||
523 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
524 | if (!ret) { | ||
525 | IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /* Try runtime/protocol */ | ||
530 | image = (__le32 *)priv->ucode_code.v_addr; | ||
531 | len = priv->ucode_code.len; | ||
532 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
533 | if (!ret) { | ||
534 | IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); | ||
539 | |||
540 | /* Since nothing seems to match, show first several data entries in | ||
541 | * instruction SRAM, so maybe visual inspection will give a clue. | ||
542 | * Selection of bootstrap image (vs. other images) is arbitrary. */ | ||
543 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
544 | len = priv->ucode_boot.len; | ||
545 | ret = iwl_verify_inst_full(priv, image, len); | ||
546 | |||
547 | return ret; | ||
548 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 24aff654fa9c..7488a68b83b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -120,7 +120,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
120 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { | 120 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { |
121 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | 121 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", |
122 | le16_to_cpu(priv->switch_rxon.channel)); | 122 | le16_to_cpu(priv->switch_rxon.channel)); |
123 | priv->switch_rxon.switch_in_progress = false; | 123 | iwl_chswitch_done(priv, false); |
124 | } | 124 | } |
125 | 125 | ||
126 | /* If we don't need to send a full RXON, we can use | 126 | /* If we don't need to send a full RXON, we can use |
@@ -367,7 +367,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
367 | 367 | ||
368 | /* Set up packet rate and flags */ | 368 | /* Set up packet rate and flags */ |
369 | rate = iwl_rate_get_lowest_plcp(priv); | 369 | rate = iwl_rate_get_lowest_plcp(priv); |
370 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | 370 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
371 | priv->hw_params.valid_tx_ant); | ||
371 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 372 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
372 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) | 373 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) |
373 | rate_flags |= RATE_MCS_CCK_MSK; | 374 | rate_flags |= RATE_MCS_CCK_MSK; |
@@ -474,18 +475,25 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
474 | /* Unmap tx_cmd */ | 475 | /* Unmap tx_cmd */ |
475 | if (num_tbs) | 476 | if (num_tbs) |
476 | pci_unmap_single(dev, | 477 | pci_unmap_single(dev, |
477 | pci_unmap_addr(&txq->meta[index], mapping), | 478 | dma_unmap_addr(&txq->meta[index], mapping), |
478 | pci_unmap_len(&txq->meta[index], len), | 479 | dma_unmap_len(&txq->meta[index], len), |
479 | PCI_DMA_BIDIRECTIONAL); | 480 | PCI_DMA_BIDIRECTIONAL); |
480 | 481 | ||
481 | /* Unmap chunks, if any. */ | 482 | /* Unmap chunks, if any. */ |
482 | for (i = 1; i < num_tbs; i++) { | 483 | for (i = 1; i < num_tbs; i++) |
483 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), | 484 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), |
484 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); | 485 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); |
485 | 486 | ||
486 | if (txq->txb) { | 487 | /* free SKB */ |
487 | dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); | 488 | if (txq->txb) { |
488 | txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; | 489 | struct sk_buff *skb; |
490 | |||
491 | skb = txq->txb[txq->q.read_ptr].skb; | ||
492 | |||
493 | /* can be called from irqs-disabled context */ | ||
494 | if (skb) { | ||
495 | dev_kfree_skb_any(skb); | ||
496 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
489 | } | 497 | } |
490 | } | 498 | } |
491 | } | 499 | } |
@@ -933,6 +941,8 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
933 | fill_rx = 1; | 941 | fill_rx = 1; |
934 | 942 | ||
935 | while (i != r) { | 943 | while (i != r) { |
944 | int len; | ||
945 | |||
936 | rxb = rxq->queue[i]; | 946 | rxb = rxq->queue[i]; |
937 | 947 | ||
938 | /* If an RXB doesn't have a Rx queue slot associated with it, | 948 | /* If an RXB doesn't have a Rx queue slot associated with it, |
@@ -947,8 +957,9 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
947 | PCI_DMA_FROMDEVICE); | 957 | PCI_DMA_FROMDEVICE); |
948 | pkt = rxb_addr(rxb); | 958 | pkt = rxb_addr(rxb); |
949 | 959 | ||
950 | trace_iwlwifi_dev_rx(priv, pkt, | 960 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
951 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 961 | len += sizeof(u32); /* account for status word */ |
962 | trace_iwlwifi_dev_rx(priv, pkt, len); | ||
952 | 963 | ||
953 | /* Reclaim a command buffer only if this packet is a response | 964 | /* Reclaim a command buffer only if this packet is a response |
954 | * to a (driver-originated) command. | 965 | * to a (driver-originated) command. |
@@ -1450,13 +1461,13 @@ bool iwl_good_ack_health(struct iwl_priv *priv, | |||
1450 | 1461 | ||
1451 | actual_ack_cnt_delta = | 1462 | actual_ack_cnt_delta = |
1452 | le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | 1463 | le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - |
1453 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | 1464 | le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt); |
1454 | expected_ack_cnt_delta = | 1465 | expected_ack_cnt_delta = |
1455 | le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - | 1466 | le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - |
1456 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | 1467 | le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt); |
1457 | ba_timeout_delta = | 1468 | ba_timeout_delta = |
1458 | le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - | 1469 | le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - |
1459 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | 1470 | le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout); |
1460 | if ((priv->_agn.agg_tids_count > 0) && | 1471 | if ((priv->_agn.agg_tids_count > 0) && |
1461 | (expected_ack_cnt_delta > 0) && | 1472 | (expected_ack_cnt_delta > 0) && |
1462 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) | 1473 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) |
@@ -1466,12 +1477,17 @@ bool iwl_good_ack_health(struct iwl_priv *priv, | |||
1466 | " expected_ack_cnt = %d\n", | 1477 | " expected_ack_cnt = %d\n", |
1467 | actual_ack_cnt_delta, expected_ack_cnt_delta); | 1478 | actual_ack_cnt_delta, expected_ack_cnt_delta); |
1468 | 1479 | ||
1469 | #ifdef CONFIG_IWLWIFI_DEBUG | 1480 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1481 | /* | ||
1482 | * This is ifdef'ed on DEBUGFS because otherwise the | ||
1483 | * statistics aren't available. If DEBUGFS is set but | ||
1484 | * DEBUG is not, these will just compile out. | ||
1485 | */ | ||
1470 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | 1486 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", |
1471 | priv->delta_statistics.tx.rx_detected_cnt); | 1487 | priv->_agn.delta_statistics.tx.rx_detected_cnt); |
1472 | IWL_DEBUG_RADIO(priv, | 1488 | IWL_DEBUG_RADIO(priv, |
1473 | "ack_or_ba_timeout_collision delta = %d\n", | 1489 | "ack_or_ba_timeout_collision delta = %d\n", |
1474 | priv->delta_statistics.tx. | 1490 | priv->_agn.delta_statistics.tx. |
1475 | ack_or_ba_timeout_collision); | 1491 | ack_or_ba_timeout_collision); |
1476 | #endif | 1492 | #endif |
1477 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | 1493 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", |
@@ -1694,6 +1710,9 @@ struct iwlagn_firmware_pieces { | |||
1694 | size_t inst_size, data_size, init_size, init_data_size, boot_size; | 1710 | size_t inst_size, data_size, init_size, init_data_size, boot_size; |
1695 | 1711 | ||
1696 | u32 build; | 1712 | u32 build; |
1713 | |||
1714 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1715 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1697 | }; | 1716 | }; |
1698 | 1717 | ||
1699 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | 1718 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, |
@@ -1871,6 +1890,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, | |||
1871 | capa->max_probe_length = | 1890 | capa->max_probe_length = |
1872 | le32_to_cpup((__le32 *)tlv_data); | 1891 | le32_to_cpup((__le32 *)tlv_data); |
1873 | break; | 1892 | break; |
1893 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | ||
1894 | if (tlv_len != 4) | ||
1895 | return -EINVAL; | ||
1896 | pieces->init_evtlog_ptr = | ||
1897 | le32_to_cpup((__le32 *)tlv_data); | ||
1898 | break; | ||
1899 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | ||
1900 | if (tlv_len != 4) | ||
1901 | return -EINVAL; | ||
1902 | pieces->init_evtlog_size = | ||
1903 | le32_to_cpup((__le32 *)tlv_data); | ||
1904 | break; | ||
1905 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | ||
1906 | if (tlv_len != 4) | ||
1907 | return -EINVAL; | ||
1908 | pieces->init_errlog_ptr = | ||
1909 | le32_to_cpup((__le32 *)tlv_data); | ||
1910 | break; | ||
1911 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | ||
1912 | if (tlv_len != 4) | ||
1913 | return -EINVAL; | ||
1914 | pieces->inst_evtlog_ptr = | ||
1915 | le32_to_cpup((__le32 *)tlv_data); | ||
1916 | break; | ||
1917 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | ||
1918 | if (tlv_len != 4) | ||
1919 | return -EINVAL; | ||
1920 | pieces->inst_evtlog_size = | ||
1921 | le32_to_cpup((__le32 *)tlv_data); | ||
1922 | break; | ||
1923 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | ||
1924 | if (tlv_len != 4) | ||
1925 | return -EINVAL; | ||
1926 | pieces->inst_errlog_ptr = | ||
1927 | le32_to_cpup((__le32 *)tlv_data); | ||
1928 | break; | ||
1874 | default: | 1929 | default: |
1875 | break; | 1930 | break; |
1876 | } | 1931 | } |
@@ -2063,6 +2118,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
2063 | goto err_pci_alloc; | 2118 | goto err_pci_alloc; |
2064 | } | 2119 | } |
2065 | 2120 | ||
2121 | /* Now that we can no longer fail, copy information */ | ||
2122 | |||
2123 | /* | ||
2124 | * The (size - 16) / 12 formula is based on the information recorded | ||
2125 | * for each event, which is of mode 1 (including timestamp) for all | ||
2126 | * new microcodes that include this information. | ||
2127 | */ | ||
2128 | priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr; | ||
2129 | if (pieces.init_evtlog_size) | ||
2130 | priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | ||
2131 | else | ||
2132 | priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size; | ||
2133 | priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr; | ||
2134 | priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr; | ||
2135 | if (pieces.inst_evtlog_size) | ||
2136 | priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | ||
2137 | else | ||
2138 | priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; | ||
2139 | priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; | ||
2140 | |||
2066 | /* Copy images into buffers for card's bus-master reads ... */ | 2141 | /* Copy images into buffers for card's bus-master reads ... */ |
2067 | 2142 | ||
2068 | /* Runtime instructions (first block of data in file) */ | 2143 | /* Runtime instructions (first block of data in file) */ |
@@ -2195,10 +2270,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
2195 | u32 blink1, blink2, ilink1, ilink2; | 2270 | u32 blink1, blink2, ilink1, ilink2; |
2196 | u32 pc, hcmd; | 2271 | u32 pc, hcmd; |
2197 | 2272 | ||
2198 | if (priv->ucode_type == UCODE_INIT) | 2273 | if (priv->ucode_type == UCODE_INIT) { |
2199 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | 2274 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); |
2200 | else | 2275 | if (!base) |
2276 | base = priv->_agn.init_errlog_ptr; | ||
2277 | } else { | ||
2201 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | 2278 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); |
2279 | if (!base) | ||
2280 | base = priv->_agn.inst_errlog_ptr; | ||
2281 | } | ||
2202 | 2282 | ||
2203 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2283 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2204 | IWL_ERR(priv, | 2284 | IWL_ERR(priv, |
@@ -2230,9 +2310,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
2230 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, | 2310 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, |
2231 | blink1, blink2, ilink1, ilink2); | 2311 | blink1, blink2, ilink1, ilink2); |
2232 | 2312 | ||
2233 | IWL_ERR(priv, "Desc Time " | 2313 | IWL_ERR(priv, "Desc Time " |
2234 | "data1 data2 line\n"); | 2314 | "data1 data2 line\n"); |
2235 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | 2315 | IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n", |
2236 | desc_lookup(desc), desc, time, data1, data2, line); | 2316 | desc_lookup(desc), desc, time, data1, data2, line); |
2237 | IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); | 2317 | IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); |
2238 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", | 2318 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", |
@@ -2258,10 +2338,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
2258 | 2338 | ||
2259 | if (num_events == 0) | 2339 | if (num_events == 0) |
2260 | return pos; | 2340 | return pos; |
2261 | if (priv->ucode_type == UCODE_INIT) | 2341 | |
2342 | if (priv->ucode_type == UCODE_INIT) { | ||
2262 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2343 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2263 | else | 2344 | if (!base) |
2345 | base = priv->_agn.init_evtlog_ptr; | ||
2346 | } else { | ||
2264 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2347 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2348 | if (!base) | ||
2349 | base = priv->_agn.inst_evtlog_ptr; | ||
2350 | } | ||
2265 | 2351 | ||
2266 | if (mode == 0) | 2352 | if (mode == 0) |
2267 | event_size = 2 * sizeof(u32); | 2353 | event_size = 2 * sizeof(u32); |
@@ -2363,13 +2449,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2363 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 2449 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
2364 | u32 next_entry; /* index of next entry to be written by uCode */ | 2450 | u32 next_entry; /* index of next entry to be written by uCode */ |
2365 | u32 size; /* # entries that we'll print */ | 2451 | u32 size; /* # entries that we'll print */ |
2452 | u32 logsize; | ||
2366 | int pos = 0; | 2453 | int pos = 0; |
2367 | size_t bufsz = 0; | 2454 | size_t bufsz = 0; |
2368 | 2455 | ||
2369 | if (priv->ucode_type == UCODE_INIT) | 2456 | if (priv->ucode_type == UCODE_INIT) { |
2370 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 2457 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
2371 | else | 2458 | logsize = priv->_agn.init_evtlog_size; |
2459 | if (!base) | ||
2460 | base = priv->_agn.init_evtlog_ptr; | ||
2461 | } else { | ||
2372 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 2462 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
2463 | logsize = priv->_agn.inst_evtlog_size; | ||
2464 | if (!base) | ||
2465 | base = priv->_agn.inst_evtlog_ptr; | ||
2466 | } | ||
2373 | 2467 | ||
2374 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 2468 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
2375 | IWL_ERR(priv, | 2469 | IWL_ERR(priv, |
@@ -2384,16 +2478,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2384 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2478 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
2385 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2479 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
2386 | 2480 | ||
2387 | if (capacity > priv->cfg->max_event_log_size) { | 2481 | if (capacity > logsize) { |
2388 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 2482 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
2389 | capacity, priv->cfg->max_event_log_size); | 2483 | capacity, logsize); |
2390 | capacity = priv->cfg->max_event_log_size; | 2484 | capacity = logsize; |
2391 | } | 2485 | } |
2392 | 2486 | ||
2393 | if (next_entry > priv->cfg->max_event_log_size) { | 2487 | if (next_entry > logsize) { |
2394 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 2488 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
2395 | next_entry, priv->cfg->max_event_log_size); | 2489 | next_entry, logsize); |
2396 | next_entry = priv->cfg->max_event_log_size; | 2490 | next_entry = logsize; |
2397 | } | 2491 | } |
2398 | 2492 | ||
2399 | size = num_wraps ? capacity : next_entry; | 2493 | size = num_wraps ? capacity : next_entry; |
@@ -2518,8 +2612,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2518 | 2612 | ||
2519 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2613 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2520 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2614 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2521 | |||
2522 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | ||
2523 | } | 2615 | } |
2524 | 2616 | ||
2525 | /* Configure Bluetooth device coexistence support */ | 2617 | /* Configure Bluetooth device coexistence support */ |
@@ -2843,9 +2935,9 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
2843 | } | 2935 | } |
2844 | 2936 | ||
2845 | if (priv->start_calib) { | 2937 | if (priv->start_calib) { |
2846 | iwl_chain_noise_calibration(priv, &priv->statistics); | 2938 | iwl_chain_noise_calibration(priv, &priv->_agn.statistics); |
2847 | 2939 | ||
2848 | iwl_sensitivity_calibration(priv, &priv->statistics); | 2940 | iwl_sensitivity_calibration(priv, &priv->_agn.statistics); |
2849 | } | 2941 | } |
2850 | 2942 | ||
2851 | mutex_unlock(&priv->mutex); | 2943 | mutex_unlock(&priv->mutex); |
@@ -2934,20 +3026,16 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2934 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3026 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
2935 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | 3027 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
2936 | 3028 | ||
2937 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3029 | if (vif->bss_conf.use_short_preamble) |
2938 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3030 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2939 | else | 3031 | else |
2940 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3032 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2941 | 3033 | ||
2942 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3034 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2943 | if (vif->bss_conf.assoc_capability & | 3035 | if (vif->bss_conf.use_short_slot) |
2944 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2945 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3036 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2946 | else | 3037 | else |
2947 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3038 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2948 | |||
2949 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
2950 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
2951 | } | 3039 | } |
2952 | 3040 | ||
2953 | iwlcore_commit_rxon(priv); | 3041 | iwlcore_commit_rxon(priv); |
@@ -3173,8 +3261,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3173 | 3261 | ||
3174 | priv->staging_rxon.assoc_id = 0; | 3262 | priv->staging_rxon.assoc_id = 0; |
3175 | 3263 | ||
3176 | if (vif->bss_conf.assoc_capability & | 3264 | if (vif->bss_conf.use_short_preamble) |
3177 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
3178 | priv->staging_rxon.flags |= | 3265 | priv->staging_rxon.flags |= |
3179 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3266 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3180 | else | 3267 | else |
@@ -3182,17 +3269,12 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3182 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3269 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3183 | 3270 | ||
3184 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3271 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3185 | if (vif->bss_conf.assoc_capability & | 3272 | if (vif->bss_conf.use_short_slot) |
3186 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
3187 | priv->staging_rxon.flags |= | 3273 | priv->staging_rxon.flags |= |
3188 | RXON_FLG_SHORT_SLOT_MSK; | 3274 | RXON_FLG_SHORT_SLOT_MSK; |
3189 | else | 3275 | else |
3190 | priv->staging_rxon.flags &= | 3276 | priv->staging_rxon.flags &= |
3191 | ~RXON_FLG_SHORT_SLOT_MSK; | 3277 | ~RXON_FLG_SHORT_SLOT_MSK; |
3192 | |||
3193 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3194 | priv->staging_rxon.flags &= | ||
3195 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
3196 | } | 3278 | } |
3197 | /* restore RXON assoc */ | 3279 | /* restore RXON assoc */ |
3198 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3280 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
@@ -3238,17 +3320,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3238 | return -EOPNOTSUPP; | 3320 | return -EOPNOTSUPP; |
3239 | } | 3321 | } |
3240 | 3322 | ||
3241 | if (sta) { | 3323 | sta_id = iwl_sta_id_or_broadcast(priv, sta); |
3242 | sta_id = iwl_sta_id(sta); | 3324 | if (sta_id == IWL_INVALID_STATION) |
3243 | 3325 | return -EINVAL; | |
3244 | if (sta_id == IWL_INVALID_STATION) { | ||
3245 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
3246 | sta->addr); | ||
3247 | return -EINVAL; | ||
3248 | } | ||
3249 | } else { | ||
3250 | sta_id = priv->hw_params.bcast_sta_id; | ||
3251 | } | ||
3252 | 3326 | ||
3253 | mutex_lock(&priv->mutex); | 3327 | mutex_lock(&priv->mutex); |
3254 | iwl_scan_cancel_timeout(priv, 100); | 3328 | iwl_scan_cancel_timeout(priv, 100); |
@@ -3300,7 +3374,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3300 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 3374 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
3301 | { | 3375 | { |
3302 | struct iwl_priv *priv = hw->priv; | 3376 | struct iwl_priv *priv = hw->priv; |
3303 | int ret; | 3377 | int ret = -EINVAL; |
3304 | 3378 | ||
3305 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | 3379 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", |
3306 | sta->addr, tid); | 3380 | sta->addr, tid); |
@@ -3308,17 +3382,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3308 | if (!(priv->cfg->sku & IWL_SKU_N)) | 3382 | if (!(priv->cfg->sku & IWL_SKU_N)) |
3309 | return -EACCES; | 3383 | return -EACCES; |
3310 | 3384 | ||
3385 | mutex_lock(&priv->mutex); | ||
3386 | |||
3311 | switch (action) { | 3387 | switch (action) { |
3312 | case IEEE80211_AMPDU_RX_START: | 3388 | case IEEE80211_AMPDU_RX_START: |
3313 | IWL_DEBUG_HT(priv, "start Rx\n"); | 3389 | IWL_DEBUG_HT(priv, "start Rx\n"); |
3314 | return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); | 3390 | ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); |
3391 | break; | ||
3315 | case IEEE80211_AMPDU_RX_STOP: | 3392 | case IEEE80211_AMPDU_RX_STOP: |
3316 | IWL_DEBUG_HT(priv, "stop Rx\n"); | 3393 | IWL_DEBUG_HT(priv, "stop Rx\n"); |
3317 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); | 3394 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
3318 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3395 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3319 | return 0; | 3396 | ret = 0; |
3320 | else | 3397 | break; |
3321 | return ret; | ||
3322 | case IEEE80211_AMPDU_TX_START: | 3398 | case IEEE80211_AMPDU_TX_START: |
3323 | IWL_DEBUG_HT(priv, "start Tx\n"); | 3399 | IWL_DEBUG_HT(priv, "start Tx\n"); |
3324 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); | 3400 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
@@ -3327,7 +3403,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3327 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 3403 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
3328 | priv->_agn.agg_tids_count); | 3404 | priv->_agn.agg_tids_count); |
3329 | } | 3405 | } |
3330 | return ret; | 3406 | break; |
3331 | case IEEE80211_AMPDU_TX_STOP: | 3407 | case IEEE80211_AMPDU_TX_STOP: |
3332 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 3408 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
3333 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); | 3409 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
@@ -3337,18 +3413,15 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3337 | priv->_agn.agg_tids_count); | 3413 | priv->_agn.agg_tids_count); |
3338 | } | 3414 | } |
3339 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3415 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3340 | return 0; | 3416 | ret = 0; |
3341 | else | 3417 | break; |
3342 | return ret; | ||
3343 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3418 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
3344 | /* do nothing */ | 3419 | /* do nothing, return value ignored */ |
3345 | return -EOPNOTSUPP; | ||
3346 | default: | ||
3347 | IWL_DEBUG_HT(priv, "unknown\n"); | ||
3348 | return -EINVAL; | ||
3349 | break; | 3420 | break; |
3350 | } | 3421 | } |
3351 | return 0; | 3422 | mutex_unlock(&priv->mutex); |
3423 | |||
3424 | return ret; | ||
3352 | } | 3425 | } |
3353 | 3426 | ||
3354 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | 3427 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, |
@@ -3423,6 +3496,98 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3423 | return 0; | 3496 | return 0; |
3424 | } | 3497 | } |
3425 | 3498 | ||
3499 | static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | ||
3500 | struct ieee80211_channel_switch *ch_switch) | ||
3501 | { | ||
3502 | struct iwl_priv *priv = hw->priv; | ||
3503 | const struct iwl_channel_info *ch_info; | ||
3504 | struct ieee80211_conf *conf = &hw->conf; | ||
3505 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
3506 | u16 ch; | ||
3507 | unsigned long flags = 0; | ||
3508 | |||
3509 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3510 | |||
3511 | if (iwl_is_rfkill(priv)) | ||
3512 | goto out_exit; | ||
3513 | |||
3514 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | ||
3515 | test_bit(STATUS_SCANNING, &priv->status)) | ||
3516 | goto out_exit; | ||
3517 | |||
3518 | if (!iwl_is_associated(priv)) | ||
3519 | goto out_exit; | ||
3520 | |||
3521 | /* channel switch in progress */ | ||
3522 | if (priv->switch_rxon.switch_in_progress == true) | ||
3523 | goto out_exit; | ||
3524 | |||
3525 | mutex_lock(&priv->mutex); | ||
3526 | if (priv->cfg->ops->lib->set_channel_switch) { | ||
3527 | |||
3528 | ch = ieee80211_frequency_to_channel( | ||
3529 | ch_switch->channel->center_freq); | ||
3530 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { | ||
3531 | ch_info = iwl_get_channel_info(priv, | ||
3532 | conf->channel->band, | ||
3533 | ch); | ||
3534 | if (!is_channel_valid(ch_info)) { | ||
3535 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | ||
3536 | goto out; | ||
3537 | } | ||
3538 | spin_lock_irqsave(&priv->lock, flags); | ||
3539 | |||
3540 | priv->current_ht_config.smps = conf->smps_mode; | ||
3541 | |||
3542 | /* Configure HT40 channels */ | ||
3543 | ht_conf->is_ht = conf_is_ht(conf); | ||
3544 | if (ht_conf->is_ht) { | ||
3545 | if (conf_is_ht40_minus(conf)) { | ||
3546 | ht_conf->extension_chan_offset = | ||
3547 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
3548 | ht_conf->is_40mhz = true; | ||
3549 | } else if (conf_is_ht40_plus(conf)) { | ||
3550 | ht_conf->extension_chan_offset = | ||
3551 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
3552 | ht_conf->is_40mhz = true; | ||
3553 | } else { | ||
3554 | ht_conf->extension_chan_offset = | ||
3555 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
3556 | ht_conf->is_40mhz = false; | ||
3557 | } | ||
3558 | } else | ||
3559 | ht_conf->is_40mhz = false; | ||
3560 | |||
3561 | /* if we are switching from ht to 2.4 clear flags | ||
3562 | * from any ht related info since 2.4 does not | ||
3563 | * support ht */ | ||
3564 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | ||
3565 | priv->staging_rxon.flags = 0; | ||
3566 | |||
3567 | iwl_set_rxon_channel(priv, conf->channel); | ||
3568 | iwl_set_rxon_ht(priv, ht_conf); | ||
3569 | iwl_set_flags_for_band(priv, conf->channel->band, | ||
3570 | priv->vif); | ||
3571 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3572 | |||
3573 | iwl_set_rate(priv); | ||
3574 | /* | ||
3575 | * at this point, staging_rxon has the | ||
3576 | * configuration for channel switch | ||
3577 | */ | ||
3578 | if (priv->cfg->ops->lib->set_channel_switch(priv, | ||
3579 | ch_switch)) | ||
3580 | priv->switch_rxon.switch_in_progress = false; | ||
3581 | } | ||
3582 | } | ||
3583 | out: | ||
3584 | mutex_unlock(&priv->mutex); | ||
3585 | out_exit: | ||
3586 | if (!priv->switch_rxon.switch_in_progress) | ||
3587 | ieee80211_chswitch_done(priv->vif, false); | ||
3588 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3589 | } | ||
3590 | |||
3426 | /***************************************************************************** | 3591 | /***************************************************************************** |
3427 | * | 3592 | * |
3428 | * driver setup and teardown | 3593 | * driver setup and teardown |
@@ -3479,6 +3644,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3479 | cancel_delayed_work(&priv->scan_check); | 3644 | cancel_delayed_work(&priv->scan_check); |
3480 | cancel_work_sync(&priv->start_internal_scan); | 3645 | cancel_work_sync(&priv->start_internal_scan); |
3481 | cancel_delayed_work(&priv->alive_start); | 3646 | cancel_delayed_work(&priv->alive_start); |
3647 | cancel_work_sync(&priv->run_time_calib_work); | ||
3482 | cancel_work_sync(&priv->beacon_update); | 3648 | cancel_work_sync(&priv->beacon_update); |
3483 | del_timer_sync(&priv->statistics_periodic); | 3649 | del_timer_sync(&priv->statistics_periodic); |
3484 | del_timer_sync(&priv->ucode_trace); | 3650 | del_timer_sync(&priv->ucode_trace); |
@@ -3594,6 +3760,7 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3594 | .sta_notify = iwl_mac_sta_notify, | 3760 | .sta_notify = iwl_mac_sta_notify, |
3595 | .sta_add = iwlagn_mac_sta_add, | 3761 | .sta_add = iwlagn_mac_sta_add, |
3596 | .sta_remove = iwl_mac_sta_remove, | 3762 | .sta_remove = iwl_mac_sta_remove, |
3763 | .channel_switch = iwl_mac_channel_switch, | ||
3597 | }; | 3764 | }; |
3598 | 3765 | ||
3599 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3766 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3604,6 +3771,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3604 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 3771 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
3605 | unsigned long flags; | 3772 | unsigned long flags; |
3606 | u16 pci_cmd; | 3773 | u16 pci_cmd; |
3774 | u8 perm_addr[ETH_ALEN]; | ||
3607 | 3775 | ||
3608 | /************************ | 3776 | /************************ |
3609 | * 1. Allocating HW data | 3777 | * 1. Allocating HW data |
@@ -3633,9 +3801,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3633 | priv->pci_dev = pdev; | 3801 | priv->pci_dev = pdev; |
3634 | priv->inta_mask = CSR_INI_SET_MASK; | 3802 | priv->inta_mask = CSR_INI_SET_MASK; |
3635 | 3803 | ||
3636 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3637 | atomic_set(&priv->restrict_refcnt, 0); | ||
3638 | #endif | ||
3639 | if (iwl_alloc_traffic_mem(priv)) | 3804 | if (iwl_alloc_traffic_mem(priv)) |
3640 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 3805 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
3641 | 3806 | ||
@@ -3724,9 +3889,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3724 | goto out_free_eeprom; | 3889 | goto out_free_eeprom; |
3725 | 3890 | ||
3726 | /* extract MAC Address */ | 3891 | /* extract MAC Address */ |
3727 | iwl_eeprom_get_mac(priv, priv->mac_addr); | 3892 | iwl_eeprom_get_mac(priv, perm_addr); |
3728 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); | 3893 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr); |
3729 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | 3894 | SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr); |
3730 | 3895 | ||
3731 | /************************ | 3896 | /************************ |
3732 | * 5. Setup HW constants | 3897 | * 5. Setup HW constants |
@@ -3993,6 +4158,47 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3993 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, | 4158 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, |
3994 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, | 4159 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, |
3995 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, | 4160 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, |
4161 | {IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)}, | ||
4162 | {IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)}, | ||
4163 | {IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)}, | ||
4164 | {IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)}, | ||
4165 | {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)}, | ||
4166 | {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)}, | ||
4167 | {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)}, | ||
4168 | {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)}, | ||
4169 | {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)}, | ||
4170 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)}, | ||
4171 | {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)}, | ||
4172 | |||
4173 | /* 6x00 Series Gen2b */ | ||
4174 | {IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)}, | ||
4175 | {IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)}, | ||
4176 | {IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)}, | ||
4177 | {IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)}, | ||
4178 | {IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)}, | ||
4179 | {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, | ||
4180 | {IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)}, | ||
4181 | {IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)}, | ||
4182 | {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, | ||
4183 | {IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)}, | ||
4184 | {IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)}, | ||
4185 | {IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)}, | ||
4186 | {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)}, | ||
4187 | {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)}, | ||
4188 | {IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)}, | ||
4189 | {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)}, | ||
4190 | {IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)}, | ||
4191 | {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)}, | ||
4192 | {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)}, | ||
4193 | {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)}, | ||
4194 | {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)}, | ||
4195 | {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)}, | ||
4196 | {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)}, | ||
4197 | {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)}, | ||
4198 | {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)}, | ||
4199 | {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)}, | ||
4200 | {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)}, | ||
4201 | {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)}, | ||
3996 | 4202 | ||
3997 | /* 6x50 WiFi/WiMax Series */ | 4203 | /* 6x50 WiFi/WiMax Series */ |
3998 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 4204 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2d748053358e..be9d298cae2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -65,6 +65,33 @@ | |||
65 | 65 | ||
66 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
67 | 67 | ||
68 | /* configuration for the _agn devices */ | ||
69 | extern struct iwl_cfg iwl4965_agn_cfg; | ||
70 | extern struct iwl_cfg iwl5300_agn_cfg; | ||
71 | extern struct iwl_cfg iwl5100_agn_cfg; | ||
72 | extern struct iwl_cfg iwl5350_agn_cfg; | ||
73 | extern struct iwl_cfg iwl5100_bgn_cfg; | ||
74 | extern struct iwl_cfg iwl5100_abg_cfg; | ||
75 | extern struct iwl_cfg iwl5150_agn_cfg; | ||
76 | extern struct iwl_cfg iwl5150_abg_cfg; | ||
77 | extern struct iwl_cfg iwl6000g2a_2agn_cfg; | ||
78 | extern struct iwl_cfg iwl6000g2a_2abg_cfg; | ||
79 | extern struct iwl_cfg iwl6000g2a_2bg_cfg; | ||
80 | extern struct iwl_cfg iwl6000g2b_bgn_cfg; | ||
81 | extern struct iwl_cfg iwl6000g2b_bg_cfg; | ||
82 | extern struct iwl_cfg iwl6000g2b_2agn_cfg; | ||
83 | extern struct iwl_cfg iwl6000g2b_2abg_cfg; | ||
84 | extern struct iwl_cfg iwl6000g2b_2bgn_cfg; | ||
85 | extern struct iwl_cfg iwl6000g2b_2bg_cfg; | ||
86 | extern struct iwl_cfg iwl6000i_2agn_cfg; | ||
87 | extern struct iwl_cfg iwl6000i_2abg_cfg; | ||
88 | extern struct iwl_cfg iwl6000i_2bg_cfg; | ||
89 | extern struct iwl_cfg iwl6000_3agn_cfg; | ||
90 | extern struct iwl_cfg iwl6050_2agn_cfg; | ||
91 | extern struct iwl_cfg iwl6050_2abg_cfg; | ||
92 | extern struct iwl_cfg iwl1000_bgn_cfg; | ||
93 | extern struct iwl_cfg iwl1000_bg_cfg; | ||
94 | |||
68 | extern struct iwl_mod_params iwlagn_mod_params; | 95 | extern struct iwl_mod_params iwlagn_mod_params; |
69 | extern struct iwl_hcmd_ops iwlagn_hcmd; | 96 | extern struct iwl_hcmd_ops iwlagn_hcmd; |
70 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; | 97 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; |
@@ -93,6 +120,8 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
93 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | 120 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, |
94 | u16 ssn_idx, u8 tx_fifo); | 121 | u16 ssn_idx, u8 tx_fifo); |
95 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); | 122 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); |
123 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
124 | int sta_id, int tid, int freed); | ||
96 | 125 | ||
97 | /* uCode */ | 126 | /* uCode */ |
98 | int iwlagn_load_ucode(struct iwl_priv *priv); | 127 | int iwlagn_load_ucode(struct iwl_priv *priv); |
@@ -102,6 +131,7 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv, | |||
102 | struct iwl_rx_mem_buffer *rxb); | 131 | struct iwl_rx_mem_buffer *rxb); |
103 | void iwlagn_init_alive_start(struct iwl_priv *priv); | 132 | void iwlagn_init_alive_start(struct iwl_priv *priv); |
104 | int iwlagn_alive_notify(struct iwl_priv *priv); | 133 | int iwlagn_alive_notify(struct iwl_priv *priv); |
134 | int iwl_verify_ucode(struct iwl_priv *priv); | ||
105 | 135 | ||
106 | /* lib */ | 136 | /* lib */ |
107 | void iwl_check_abort_status(struct iwl_priv *priv, | 137 | void iwl_check_abort_status(struct iwl_priv *priv, |
@@ -171,6 +201,16 @@ static inline bool iwl_is_tx_success(u32 status) | |||
171 | (status == TX_STATUS_DIRECT_DONE); | 201 | (status == TX_STATUS_DIRECT_DONE); |
172 | } | 202 | } |
173 | 203 | ||
204 | /* rx */ | ||
205 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
206 | struct iwl_rx_mem_buffer *rxb); | ||
207 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
208 | struct iwl_rx_packet *pkt); | ||
209 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
210 | struct iwl_rx_mem_buffer *rxb); | ||
211 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
212 | struct iwl_rx_mem_buffer *rxb); | ||
213 | |||
174 | /* scan */ | 214 | /* scan */ |
175 | void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | 215 | void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); |
176 | 216 | ||
@@ -178,4 +218,8 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | |||
178 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | 218 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, |
179 | struct ieee80211_vif *vif, bool add); | 219 | struct ieee80211_vif *vif, bool add); |
180 | 220 | ||
221 | /* hcmd */ | ||
222 | int iwlagn_send_rxon_assoc(struct iwl_priv *priv); | ||
223 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); | ||
224 | |||
181 | #endif /* __iwl_agn_h__ */ | 225 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 9aab020c474b..498492565912 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -95,7 +95,7 @@ enum { | |||
95 | 95 | ||
96 | /* Multi-Station support */ | 96 | /* Multi-Station support */ |
97 | REPLY_ADD_STA = 0x18, | 97 | REPLY_ADD_STA = 0x18, |
98 | REPLY_REMOVE_STA = 0x19, /* not used */ | 98 | REPLY_REMOVE_STA = 0x19, |
99 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ | 99 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ |
100 | 100 | ||
101 | /* Security */ | 101 | /* Security */ |
@@ -952,7 +952,6 @@ struct iwl_qosparam_cmd { | |||
952 | 952 | ||
953 | /* Special, dedicated locations within device's station table */ | 953 | /* Special, dedicated locations within device's station table */ |
954 | #define IWL_AP_ID 0 | 954 | #define IWL_AP_ID 0 |
955 | #define IWL_MULTICAST_ID 1 | ||
956 | #define IWL_STA_ID 2 | 955 | #define IWL_STA_ID 2 |
957 | #define IWL3945_BROADCAST_ID 24 | 956 | #define IWL3945_BROADCAST_ID 24 |
958 | #define IWL3945_STATION_COUNT 25 | 957 | #define IWL3945_STATION_COUNT 25 |
@@ -1367,7 +1366,7 @@ struct iwl_rx_phy_res { | |||
1367 | __le16 reserved3; | 1366 | __le16 reserved3; |
1368 | } __attribute__ ((packed)); | 1367 | } __attribute__ ((packed)); |
1369 | 1368 | ||
1370 | struct iwl4965_rx_mpdu_res_start { | 1369 | struct iwl_rx_mpdu_res_start { |
1371 | __le16 byte_count; | 1370 | __le16 byte_count; |
1372 | __le16 reserved; | 1371 | __le16 reserved; |
1373 | } __attribute__ ((packed)); | 1372 | } __attribute__ ((packed)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5bbc5298ef96..329e5107b5c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -141,13 +141,14 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
141 | } | 141 | } |
142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); | 142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); |
143 | 143 | ||
144 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | 144 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) |
145 | { | 145 | { |
146 | int i; | 146 | int i; |
147 | u8 ind = ant; | 147 | u8 ind = ant; |
148 | |||
148 | for (i = 0; i < RATE_ANT_NUM - 1; i++) { | 149 | for (i = 0; i < RATE_ANT_NUM - 1; i++) { |
149 | ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; | 150 | ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; |
150 | if (priv->hw_params.valid_tx_ant & BIT(ind)) | 151 | if (valid & BIT(ind)) |
151 | return ind; | 152 | return ind; |
152 | } | 153 | } |
153 | return ant; | 154 | return ant; |
@@ -457,7 +458,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
457 | if (!sta_ht_inf->ht_supported) | 458 | if (!sta_ht_inf->ht_supported) |
458 | return 0; | 459 | return 0; |
459 | } | 460 | } |
460 | #ifdef CONFIG_IWLWIFI_DEBUG | 461 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
461 | if (priv->disable_ht40) | 462 | if (priv->disable_ht40) |
462 | return 0; | 463 | return 0; |
463 | #endif | 464 | #endif |
@@ -506,11 +507,11 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
506 | } | 507 | } |
507 | 508 | ||
508 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | 509 | beacon_int = iwl_adjust_beacon_interval(beacon_int, |
509 | priv->hw_params.max_beacon_itrvl * 1024); | 510 | priv->hw_params.max_beacon_itrvl * TIME_UNIT); |
510 | priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); | 511 | priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); |
511 | 512 | ||
512 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ | 513 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ |
513 | interval_tm = beacon_int * 1024; | 514 | interval_tm = beacon_int * TIME_UNIT; |
514 | rem = do_div(tsf, interval_tm); | 515 | rem = do_div(tsf, interval_tm); |
515 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | 516 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); |
516 | 517 | ||
@@ -932,9 +933,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | |||
932 | } | 933 | } |
933 | EXPORT_SYMBOL(iwl_set_rxon_channel); | 934 | EXPORT_SYMBOL(iwl_set_rxon_channel); |
934 | 935 | ||
935 | static void iwl_set_flags_for_band(struct iwl_priv *priv, | 936 | void iwl_set_flags_for_band(struct iwl_priv *priv, |
936 | enum ieee80211_band band, | 937 | enum ieee80211_band band, |
937 | struct ieee80211_vif *vif) | 938 | struct ieee80211_vif *vif) |
938 | { | 939 | { |
939 | if (band == IEEE80211_BAND_5GHZ) { | 940 | if (band == IEEE80211_BAND_5GHZ) { |
940 | priv->staging_rxon.flags &= | 941 | priv->staging_rxon.flags &= |
@@ -943,19 +944,17 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv, | |||
943 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 944 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
944 | } else { | 945 | } else { |
945 | /* Copied from iwl_post_associate() */ | 946 | /* Copied from iwl_post_associate() */ |
946 | if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 947 | if (vif && vif->bss_conf.use_short_slot) |
947 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 948 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
948 | else | 949 | else |
949 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 950 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
950 | 951 | ||
951 | if (vif && vif->type == NL80211_IFTYPE_ADHOC) | ||
952 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
953 | |||
954 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; | 952 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; |
955 | priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; | 953 | priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; |
956 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; | 954 | priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; |
957 | } | 955 | } |
958 | } | 956 | } |
957 | EXPORT_SYMBOL(iwl_set_flags_for_band); | ||
959 | 958 | ||
960 | /* | 959 | /* |
961 | * initialize rxon structure with default values from eeprom | 960 | * initialize rxon structure with default values from eeprom |
@@ -1021,15 +1020,17 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
1021 | /* clear both MIX and PURE40 mode flag */ | 1020 | /* clear both MIX and PURE40 mode flag */ |
1022 | priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | 1021 | priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | |
1023 | RXON_FLG_CHANNEL_MODE_PURE_40); | 1022 | RXON_FLG_CHANNEL_MODE_PURE_40); |
1024 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | 1023 | |
1025 | memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); | 1024 | if (vif) |
1025 | memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN); | ||
1026 | |||
1026 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; | 1027 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; |
1027 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; | 1028 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; |
1028 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; | 1029 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; |
1029 | } | 1030 | } |
1030 | EXPORT_SYMBOL(iwl_connection_init_rx_config); | 1031 | EXPORT_SYMBOL(iwl_connection_init_rx_config); |
1031 | 1032 | ||
1032 | static void iwl_set_rate(struct iwl_priv *priv) | 1033 | void iwl_set_rate(struct iwl_priv *priv) |
1033 | { | 1034 | { |
1034 | const struct ieee80211_supported_band *hw = NULL; | 1035 | const struct ieee80211_supported_band *hw = NULL; |
1035 | struct ieee80211_rate *rate; | 1036 | struct ieee80211_rate *rate; |
@@ -1057,6 +1058,21 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1057 | priv->staging_rxon.ofdm_basic_rates = | 1058 | priv->staging_rxon.ofdm_basic_rates = |
1058 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 1059 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1059 | } | 1060 | } |
1061 | EXPORT_SYMBOL(iwl_set_rate); | ||
1062 | |||
1063 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | ||
1064 | { | ||
1065 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
1066 | return; | ||
1067 | |||
1068 | if (priv->switch_rxon.switch_in_progress) { | ||
1069 | ieee80211_chswitch_done(priv->vif, is_success); | ||
1070 | mutex_lock(&priv->mutex); | ||
1071 | priv->switch_rxon.switch_in_progress = false; | ||
1072 | mutex_unlock(&priv->mutex); | ||
1073 | } | ||
1074 | } | ||
1075 | EXPORT_SYMBOL(iwl_chswitch_done); | ||
1060 | 1076 | ||
1061 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1077 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1062 | { | 1078 | { |
@@ -1071,11 +1087,12 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1071 | priv->staging_rxon.channel = csa->channel; | 1087 | priv->staging_rxon.channel = csa->channel; |
1072 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | 1088 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", |
1073 | le16_to_cpu(csa->channel)); | 1089 | le16_to_cpu(csa->channel)); |
1074 | } else | 1090 | iwl_chswitch_done(priv, true); |
1091 | } else { | ||
1075 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | 1092 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", |
1076 | le16_to_cpu(csa->channel)); | 1093 | le16_to_cpu(csa->channel)); |
1077 | 1094 | iwl_chswitch_done(priv, false); | |
1078 | priv->switch_rxon.switch_in_progress = false; | 1095 | } |
1079 | } | 1096 | } |
1080 | } | 1097 | } |
1081 | EXPORT_SYMBOL(iwl_rx_csa); | 1098 | EXPORT_SYMBOL(iwl_rx_csa); |
@@ -1507,130 +1524,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1507 | } | 1524 | } |
1508 | EXPORT_SYMBOL(iwl_send_statistics_request); | 1525 | EXPORT_SYMBOL(iwl_send_statistics_request); |
1509 | 1526 | ||
1510 | /** | ||
1511 | * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, | ||
1512 | * using sample data 100 bytes apart. If these sample points are good, | ||
1513 | * it's a pretty good bet that everything between them is good, too. | ||
1514 | */ | ||
1515 | static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) | ||
1516 | { | ||
1517 | u32 val; | ||
1518 | int ret = 0; | ||
1519 | u32 errcnt = 0; | ||
1520 | u32 i; | ||
1521 | |||
1522 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
1523 | |||
1524 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | ||
1525 | /* read data comes through single port, auto-incr addr */ | ||
1526 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
1527 | * if IWL_DL_IO is set */ | ||
1528 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
1529 | i + IWL49_RTC_INST_LOWER_BOUND); | ||
1530 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1531 | if (val != le32_to_cpu(*image)) { | ||
1532 | ret = -EIO; | ||
1533 | errcnt++; | ||
1534 | if (errcnt >= 3) | ||
1535 | break; | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | return ret; | ||
1540 | } | ||
1541 | |||
1542 | /** | ||
1543 | * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, | ||
1544 | * looking at all data. | ||
1545 | */ | ||
1546 | static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, | ||
1547 | u32 len) | ||
1548 | { | ||
1549 | u32 val; | ||
1550 | u32 save_len = len; | ||
1551 | int ret = 0; | ||
1552 | u32 errcnt; | ||
1553 | |||
1554 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
1555 | |||
1556 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
1557 | IWL49_RTC_INST_LOWER_BOUND); | ||
1558 | |||
1559 | errcnt = 0; | ||
1560 | for (; len > 0; len -= sizeof(u32), image++) { | ||
1561 | /* read data comes through single port, auto-incr addr */ | ||
1562 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
1563 | * if IWL_DL_IO is set */ | ||
1564 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1565 | if (val != le32_to_cpu(*image)) { | ||
1566 | IWL_ERR(priv, "uCode INST section is invalid at " | ||
1567 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
1568 | save_len - len, val, le32_to_cpu(*image)); | ||
1569 | ret = -EIO; | ||
1570 | errcnt++; | ||
1571 | if (errcnt >= 20) | ||
1572 | break; | ||
1573 | } | ||
1574 | } | ||
1575 | |||
1576 | if (!errcnt) | ||
1577 | IWL_DEBUG_INFO(priv, | ||
1578 | "ucode image in INSTRUCTION memory is good\n"); | ||
1579 | |||
1580 | return ret; | ||
1581 | } | ||
1582 | |||
1583 | /** | ||
1584 | * iwl_verify_ucode - determine which instruction image is in SRAM, | ||
1585 | * and verify its contents | ||
1586 | */ | ||
1587 | int iwl_verify_ucode(struct iwl_priv *priv) | ||
1588 | { | ||
1589 | __le32 *image; | ||
1590 | u32 len; | ||
1591 | int ret; | ||
1592 | |||
1593 | /* Try bootstrap */ | ||
1594 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
1595 | len = priv->ucode_boot.len; | ||
1596 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
1597 | if (!ret) { | ||
1598 | IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); | ||
1599 | return 0; | ||
1600 | } | ||
1601 | |||
1602 | /* Try initialize */ | ||
1603 | image = (__le32 *)priv->ucode_init.v_addr; | ||
1604 | len = priv->ucode_init.len; | ||
1605 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
1606 | if (!ret) { | ||
1607 | IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); | ||
1608 | return 0; | ||
1609 | } | ||
1610 | |||
1611 | /* Try runtime/protocol */ | ||
1612 | image = (__le32 *)priv->ucode_code.v_addr; | ||
1613 | len = priv->ucode_code.len; | ||
1614 | ret = iwlcore_verify_inst_sparse(priv, image, len); | ||
1615 | if (!ret) { | ||
1616 | IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); | ||
1617 | return 0; | ||
1618 | } | ||
1619 | |||
1620 | IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); | ||
1621 | |||
1622 | /* Since nothing seems to match, show first several data entries in | ||
1623 | * instruction SRAM, so maybe visual inspection will give a clue. | ||
1624 | * Selection of bootstrap image (vs. other images) is arbitrary. */ | ||
1625 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
1626 | len = priv->ucode_boot.len; | ||
1627 | ret = iwl_verify_inst_full(priv, image, len); | ||
1628 | |||
1629 | return ret; | ||
1630 | } | ||
1631 | EXPORT_SYMBOL(iwl_verify_ucode); | ||
1632 | |||
1633 | |||
1634 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 1527 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
1635 | { | 1528 | { |
1636 | struct iwl_ct_kill_config cmd; | 1529 | struct iwl_ct_kill_config cmd; |
@@ -2051,8 +1944,6 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2051 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1944 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2052 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 1945 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2053 | 1946 | ||
2054 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | ||
2055 | |||
2056 | return iwlcore_commit_rxon(priv); | 1947 | return iwlcore_commit_rxon(priv); |
2057 | } | 1948 | } |
2058 | 1949 | ||
@@ -2061,7 +1952,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2061 | struct iwl_priv *priv = hw->priv; | 1952 | struct iwl_priv *priv = hw->priv; |
2062 | int err = 0; | 1953 | int err = 0; |
2063 | 1954 | ||
2064 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); | 1955 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
1956 | vif->type, vif->addr); | ||
2065 | 1957 | ||
2066 | mutex_lock(&priv->mutex); | 1958 | mutex_lock(&priv->mutex); |
2067 | 1959 | ||
@@ -2079,9 +1971,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2079 | priv->vif = vif; | 1971 | priv->vif = vif; |
2080 | priv->iw_mode = vif->type; | 1972 | priv->iw_mode = vif->type; |
2081 | 1973 | ||
2082 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); | ||
2083 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); | ||
2084 | |||
2085 | err = iwl_set_mode(priv, vif); | 1974 | err = iwl_set_mode(priv, vif); |
2086 | if (err) | 1975 | if (err) |
2087 | goto out_err; | 1976 | goto out_err; |
@@ -2115,6 +2004,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2115 | } | 2004 | } |
2116 | if (priv->vif == vif) { | 2005 | if (priv->vif == vif) { |
2117 | priv->vif = NULL; | 2006 | priv->vif = NULL; |
2007 | if (priv->scan_vif == vif) { | ||
2008 | ieee80211_scan_completed(priv->hw, true); | ||
2009 | priv->scan_vif = NULL; | ||
2010 | priv->scan_request = NULL; | ||
2011 | } | ||
2118 | memset(priv->bssid, 0, ETH_ALEN); | 2012 | memset(priv->bssid, 0, ETH_ALEN); |
2119 | } | 2013 | } |
2120 | mutex_unlock(&priv->mutex); | 2014 | mutex_unlock(&priv->mutex); |
@@ -2215,22 +2109,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2215 | 2109 | ||
2216 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); | 2110 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); |
2217 | spin_unlock_irqrestore(&priv->lock, flags); | 2111 | spin_unlock_irqrestore(&priv->lock, flags); |
2218 | if (iwl_is_associated(priv) && | 2112 | |
2219 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | ||
2220 | priv->cfg->ops->lib->set_channel_switch) { | ||
2221 | iwl_set_rate(priv); | ||
2222 | /* | ||
2223 | * at this point, staging_rxon has the | ||
2224 | * configuration for channel switch | ||
2225 | */ | ||
2226 | ret = priv->cfg->ops->lib->set_channel_switch(priv, | ||
2227 | ch); | ||
2228 | if (!ret) { | ||
2229 | iwl_print_rx_config_cmd(priv); | ||
2230 | goto out; | ||
2231 | } | ||
2232 | priv->switch_rxon.switch_in_progress = false; | ||
2233 | } | ||
2234 | set_ch_out: | 2113 | set_ch_out: |
2235 | /* The list of supported rates and rate mask can be different | 2114 | /* The list of supported rates and rate mask can be different |
2236 | * for each band; since the band may have changed, reset | 2115 | * for each band; since the band may have changed, reset |
@@ -2588,7 +2467,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
2588 | EXPORT_SYMBOL(iwl_update_stats); | 2467 | EXPORT_SYMBOL(iwl_update_stats); |
2589 | #endif | 2468 | #endif |
2590 | 2469 | ||
2591 | const static char *get_csr_string(int cmd) | 2470 | static const char *get_csr_string(int cmd) |
2592 | { | 2471 | { |
2593 | switch (cmd) { | 2472 | switch (cmd) { |
2594 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | 2473 | IWL_CMD(CSR_HW_IF_CONFIG_REG); |
@@ -2659,7 +2538,7 @@ void iwl_dump_csr(struct iwl_priv *priv) | |||
2659 | } | 2538 | } |
2660 | EXPORT_SYMBOL(iwl_dump_csr); | 2539 | EXPORT_SYMBOL(iwl_dump_csr); |
2661 | 2540 | ||
2662 | const static char *get_fh_string(int cmd) | 2541 | static const char *get_fh_string(int cmd) |
2663 | { | 2542 | { |
2664 | switch (cmd) { | 2543 | switch (cmd) { |
2665 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | 2544 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); |
@@ -2881,6 +2760,61 @@ void iwl_bg_monitor_recover(unsigned long data) | |||
2881 | } | 2760 | } |
2882 | EXPORT_SYMBOL(iwl_bg_monitor_recover); | 2761 | EXPORT_SYMBOL(iwl_bg_monitor_recover); |
2883 | 2762 | ||
2763 | |||
2764 | /* | ||
2765 | * extended beacon time format | ||
2766 | * time in usec will be changed into a 32-bit value in extended:internal format | ||
2767 | * the extended part is the beacon counts | ||
2768 | * the internal part is the time in usec within one beacon interval | ||
2769 | */ | ||
2770 | u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) | ||
2771 | { | ||
2772 | u32 quot; | ||
2773 | u32 rem; | ||
2774 | u32 interval = beacon_interval * TIME_UNIT; | ||
2775 | |||
2776 | if (!interval || !usec) | ||
2777 | return 0; | ||
2778 | |||
2779 | quot = (usec / interval) & | ||
2780 | (iwl_beacon_time_mask_high(priv, | ||
2781 | priv->hw_params.beacon_time_tsf_bits) >> | ||
2782 | priv->hw_params.beacon_time_tsf_bits); | ||
2783 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, | ||
2784 | priv->hw_params.beacon_time_tsf_bits); | ||
2785 | |||
2786 | return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; | ||
2787 | } | ||
2788 | EXPORT_SYMBOL(iwl_usecs_to_beacons); | ||
2789 | |||
2790 | /* base is usually what we get from ucode with each received frame, | ||
2791 | * the same as HW timer counter counting down | ||
2792 | */ | ||
2793 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
2794 | u32 addon, u32 beacon_interval) | ||
2795 | { | ||
2796 | u32 base_low = base & iwl_beacon_time_mask_low(priv, | ||
2797 | priv->hw_params.beacon_time_tsf_bits); | ||
2798 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, | ||
2799 | priv->hw_params.beacon_time_tsf_bits); | ||
2800 | u32 interval = beacon_interval * TIME_UNIT; | ||
2801 | u32 res = (base & iwl_beacon_time_mask_high(priv, | ||
2802 | priv->hw_params.beacon_time_tsf_bits)) + | ||
2803 | (addon & iwl_beacon_time_mask_high(priv, | ||
2804 | priv->hw_params.beacon_time_tsf_bits)); | ||
2805 | |||
2806 | if (base_low > addon_low) | ||
2807 | res += base_low - addon_low; | ||
2808 | else if (base_low < addon_low) { | ||
2809 | res += interval + base_low - addon_low; | ||
2810 | res += (1 << priv->hw_params.beacon_time_tsf_bits); | ||
2811 | } else | ||
2812 | res += (1 << priv->hw_params.beacon_time_tsf_bits); | ||
2813 | |||
2814 | return cpu_to_le32(res); | ||
2815 | } | ||
2816 | EXPORT_SYMBOL(iwl_add_beacon_time); | ||
2817 | |||
2884 | #ifdef CONFIG_PM | 2818 | #ifdef CONFIG_PM |
2885 | 2819 | ||
2886 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 2820 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 31775bd9c361..5e72d743d9ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -79,6 +79,8 @@ struct iwl_cmd; | |||
79 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ | 79 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ |
80 | .driver_data = (kernel_ulong_t)&(cfg) | 80 | .driver_data = (kernel_ulong_t)&(cfg) |
81 | 81 | ||
82 | #define TIME_UNIT 1024 | ||
83 | |||
82 | #define IWL_SKU_G 0x1 | 84 | #define IWL_SKU_G 0x1 |
83 | #define IWL_SKU_A 0x2 | 85 | #define IWL_SKU_A 0x2 |
84 | #define IWL_SKU_N 0x8 | 86 | #define IWL_SKU_N 0x8 |
@@ -173,7 +175,8 @@ struct iwl_lib_ops { | |||
173 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 175 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
174 | void (*dump_csr)(struct iwl_priv *priv); | 176 | void (*dump_csr)(struct iwl_priv *priv); |
175 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); | 177 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); |
176 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 178 | int (*set_channel_switch)(struct iwl_priv *priv, |
179 | struct ieee80211_channel_switch *ch_switch); | ||
177 | /* power management */ | 180 | /* power management */ |
178 | struct iwl_apm_ops apm_ops; | 181 | struct iwl_apm_ops apm_ops; |
179 | 182 | ||
@@ -325,7 +328,8 @@ struct iwl_cfg { | |||
325 | const bool ucode_tracing; | 328 | const bool ucode_tracing; |
326 | const bool sensitivity_calib_by_driver; | 329 | const bool sensitivity_calib_by_driver; |
327 | const bool chain_noise_calib_by_driver; | 330 | const bool chain_noise_calib_by_driver; |
328 | u8 scan_antennas[IEEE80211_NUM_BANDS]; | 331 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; |
332 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; | ||
329 | }; | 333 | }; |
330 | 334 | ||
331 | /*************************** | 335 | /*************************** |
@@ -343,6 +347,9 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv); | |||
343 | int iwl_full_rxon_required(struct iwl_priv *priv); | 347 | int iwl_full_rxon_required(struct iwl_priv *priv); |
344 | void iwl_set_rxon_chain(struct iwl_priv *priv); | 348 | void iwl_set_rxon_chain(struct iwl_priv *priv); |
345 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); | 349 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); |
350 | void iwl_set_flags_for_band(struct iwl_priv *priv, | ||
351 | enum ieee80211_band band, | ||
352 | struct ieee80211_vif *vif); | ||
346 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | 353 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, |
347 | enum ieee80211_band band); | 354 | enum ieee80211_band band); |
348 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); | 355 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); |
@@ -350,6 +357,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
350 | struct ieee80211_sta_ht_cap *sta_ht_inf); | 357 | struct ieee80211_sta_ht_cap *sta_ht_inf); |
351 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 358 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
352 | struct ieee80211_vif *vif); | 359 | struct ieee80211_vif *vif); |
360 | void iwl_set_rate(struct iwl_priv *priv); | ||
353 | int iwl_set_decrypted_flag(struct iwl_priv *priv, | 361 | int iwl_set_decrypted_flag(struct iwl_priv *priv, |
354 | struct ieee80211_hdr *hdr, | 362 | struct ieee80211_hdr *hdr, |
355 | u32 decrypt_res, | 363 | u32 decrypt_res, |
@@ -447,20 +455,11 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | |||
447 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 455 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
448 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 456 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
449 | /* Handlers */ | 457 | /* Handlers */ |
450 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
451 | struct iwl_rx_mem_buffer *rxb); | ||
452 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 458 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
453 | struct iwl_rx_mem_buffer *rxb); | 459 | struct iwl_rx_mem_buffer *rxb); |
454 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
455 | struct iwl_rx_packet *pkt); | ||
456 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
457 | struct iwl_rx_packet *pkt); | ||
458 | void iwl_recover_from_statistics(struct iwl_priv *priv, | 460 | void iwl_recover_from_statistics(struct iwl_priv *priv, |
459 | struct iwl_rx_packet *pkt); | 461 | struct iwl_rx_packet *pkt); |
460 | void iwl_rx_statistics(struct iwl_priv *priv, | 462 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); |
461 | struct iwl_rx_mem_buffer *rxb); | ||
462 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
463 | struct iwl_rx_mem_buffer *rxb); | ||
464 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 463 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
465 | 464 | ||
466 | /* TX helpers */ | 465 | /* TX helpers */ |
@@ -474,8 +473,6 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
474 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 473 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
475 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 474 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
476 | struct iwl_tx_queue *txq); | 475 | struct iwl_tx_queue *txq); |
477 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
478 | int sta_id, int tid, int freed); | ||
479 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 476 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
480 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 477 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
481 | int slots_num, u32 txq_id); | 478 | int slots_num, u32 txq_id); |
@@ -495,7 +492,7 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | |||
495 | 492 | ||
496 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); | 493 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); |
497 | 494 | ||
498 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); | 495 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); |
499 | 496 | ||
500 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) | 497 | static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) |
501 | { | 498 | { |
@@ -528,7 +525,7 @@ void iwl_bg_start_internal_scan(struct work_struct *work); | |||
528 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | 525 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); |
529 | int iwl_force_reset(struct iwl_priv *priv, int mode); | 526 | int iwl_force_reset(struct iwl_priv *priv, int mode); |
530 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 527 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
531 | const u8 *ie, int ie_len, int left); | 528 | const u8 *ta, const u8 *ie, int ie_len, int left); |
532 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 529 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
533 | u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 530 | u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
534 | enum ieee80211_band band, | 531 | enum ieee80211_band band, |
@@ -595,6 +592,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) | |||
595 | } | 592 | } |
596 | 593 | ||
597 | void iwl_bg_monitor_recover(unsigned long data); | 594 | void iwl_bg_monitor_recover(unsigned long data); |
595 | u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); | ||
596 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | ||
597 | u32 addon, u32 beacon_interval); | ||
598 | 598 | ||
599 | #ifdef CONFIG_PM | 599 | #ifdef CONFIG_PM |
600 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); | 600 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); |
@@ -693,7 +693,6 @@ extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | |||
693 | extern void iwl_send_bt_config(struct iwl_priv *priv); | 693 | extern void iwl_send_bt_config(struct iwl_priv *priv); |
694 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | 694 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
695 | u8 flags, bool clear); | 695 | u8 flags, bool clear); |
696 | extern int iwl_verify_ucode(struct iwl_priv *priv); | ||
697 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 696 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
698 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); | 697 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
699 | void iwl_apm_stop(struct iwl_priv *priv); | 698 | void iwl_apm_stop(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 9659c5d01df9..cee3d12eb383 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -106,27 +106,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
106 | .open = iwl_dbgfs_open_file_generic, \ | 106 | .open = iwl_dbgfs_open_file_generic, \ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
110 | { | ||
111 | int p = 0; | ||
112 | |||
113 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
114 | le32_to_cpu(priv->statistics.flag)); | ||
115 | if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) | ||
116 | p += scnprintf(buf + p, bufsz - p, | ||
117 | "\tStatistics have been cleared\n"); | ||
118 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
119 | (le32_to_cpu(priv->statistics.flag) & | ||
120 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
121 | ? "2.4 GHz" : "5.2 GHz"); | ||
122 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
123 | (le32_to_cpu(priv->statistics.flag) & | ||
124 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
125 | ? "enabled" : "disabled"); | ||
126 | return p; | ||
127 | } | ||
128 | EXPORT_SYMBOL(iwl_dbgfs_statistics_flag); | ||
129 | |||
130 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | 109 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, |
131 | char __user *user_buf, | 110 | char __user *user_buf, |
132 | size_t count, loff_t *ppos) { | 111 | size_t count, loff_t *ppos) { |
@@ -330,45 +309,35 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
330 | 309 | ||
331 | for (i = 0; i < max_sta; i++) { | 310 | for (i = 0; i < max_sta; i++) { |
332 | station = &priv->stations[i]; | 311 | station = &priv->stations[i]; |
333 | if (station->used) { | 312 | if (!station->used) |
334 | pos += scnprintf(buf + pos, bufsz - pos, | 313 | continue; |
335 | "station %d:\ngeneral data:\n", i+1); | 314 | pos += scnprintf(buf + pos, bufsz - pos, |
336 | pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", | 315 | "station %d - addr: %pM, flags: %#x\n", |
337 | station->sta.sta.sta_id); | 316 | i, station->sta.sta.addr, |
338 | pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", | 317 | station->sta.station_flags_msk); |
339 | station->sta.mode); | 318 | pos += scnprintf(buf + pos, bufsz - pos, |
340 | pos += scnprintf(buf + pos, bufsz - pos, | 319 | "TID\tseq_num\ttxq_id\tframes\ttfds\t"); |
341 | "flags: 0x%x\n", | 320 | pos += scnprintf(buf + pos, bufsz - pos, |
342 | station->sta.station_flags_msk); | 321 | "start_idx\tbitmap\t\t\trate_n_flags\n"); |
343 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); | ||
344 | pos += scnprintf(buf + pos, bufsz - pos, | ||
345 | "seq_num\t\ttxq_id"); | ||
346 | pos += scnprintf(buf + pos, bufsz - pos, | ||
347 | "\tframe_count\twait_for_ba\t"); | ||
348 | pos += scnprintf(buf + pos, bufsz - pos, | ||
349 | "start_idx\tbitmap0\t"); | ||
350 | pos += scnprintf(buf + pos, bufsz - pos, | ||
351 | "bitmap1\trate_n_flags"); | ||
352 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
353 | 322 | ||
354 | for (j = 0; j < MAX_TID_COUNT; j++) { | 323 | for (j = 0; j < MAX_TID_COUNT; j++) { |
355 | pos += scnprintf(buf + pos, bufsz - pos, | 324 | pos += scnprintf(buf + pos, bufsz - pos, |
356 | "[%d]:\t\t%u", j, | 325 | "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", |
357 | station->tid[j].seq_number); | 326 | j, station->tid[j].seq_number, |
358 | pos += scnprintf(buf + pos, bufsz - pos, | 327 | station->tid[j].agg.txq_id, |
359 | "\t%u\t\t%u\t\t%u\t\t", | 328 | station->tid[j].agg.frame_count, |
360 | station->tid[j].agg.txq_id, | 329 | station->tid[j].tfds_in_queue, |
361 | station->tid[j].agg.frame_count, | 330 | station->tid[j].agg.start_idx, |
362 | station->tid[j].agg.wait_for_ba); | 331 | station->tid[j].agg.bitmap, |
332 | station->tid[j].agg.rate_n_flags); | ||
333 | |||
334 | if (station->tid[j].agg.wait_for_ba) | ||
363 | pos += scnprintf(buf + pos, bufsz - pos, | 335 | pos += scnprintf(buf + pos, bufsz - pos, |
364 | "%u\t%llu\t%u", | 336 | " - waitforba"); |
365 | station->tid[j].agg.start_idx, | ||
366 | (unsigned long long)station->tid[j].agg.bitmap, | ||
367 | station->tid[j].agg.rate_n_flags); | ||
368 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
369 | } | ||
370 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 337 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
371 | } | 338 | } |
339 | |||
340 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
372 | } | 341 | } |
373 | 342 | ||
374 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 343 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
@@ -1049,8 +1018,13 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1049 | rxq->write); | 1018 | rxq->write); |
1050 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | 1019 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", |
1051 | rxq->free_count); | 1020 | rxq->free_count); |
1052 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | 1021 | if (rxq->rb_stts) { |
1022 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
1053 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | 1023 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); |
1024 | } else { | ||
1025 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1026 | "closed_rb_num: Not Allocated\n"); | ||
1027 | } | ||
1054 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1028 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1055 | } | 1029 | } |
1056 | 1030 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f3f3473c5c7e..1af845c0f0b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -48,25 +48,6 @@ | |||
48 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
49 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
50 | 50 | ||
51 | /* configuration for the iwl4965 */ | ||
52 | extern struct iwl_cfg iwl4965_agn_cfg; | ||
53 | extern struct iwl_cfg iwl5300_agn_cfg; | ||
54 | extern struct iwl_cfg iwl5100_agn_cfg; | ||
55 | extern struct iwl_cfg iwl5350_agn_cfg; | ||
56 | extern struct iwl_cfg iwl5100_bgn_cfg; | ||
57 | extern struct iwl_cfg iwl5100_abg_cfg; | ||
58 | extern struct iwl_cfg iwl5150_agn_cfg; | ||
59 | extern struct iwl_cfg iwl5150_abg_cfg; | ||
60 | extern struct iwl_cfg iwl6000g2a_2agn_cfg; | ||
61 | extern struct iwl_cfg iwl6000i_2agn_cfg; | ||
62 | extern struct iwl_cfg iwl6000i_2abg_cfg; | ||
63 | extern struct iwl_cfg iwl6000i_2bg_cfg; | ||
64 | extern struct iwl_cfg iwl6000_3agn_cfg; | ||
65 | extern struct iwl_cfg iwl6050_2agn_cfg; | ||
66 | extern struct iwl_cfg iwl6050_2abg_cfg; | ||
67 | extern struct iwl_cfg iwl1000_bgn_cfg; | ||
68 | extern struct iwl_cfg iwl1000_bg_cfg; | ||
69 | |||
70 | struct iwl_tx_queue; | 51 | struct iwl_tx_queue; |
71 | 52 | ||
72 | /* CT-KILL constants */ | 53 | /* CT-KILL constants */ |
@@ -133,8 +114,8 @@ struct iwl_cmd_meta { | |||
133 | * structure is stored at the end of the shared queue memory. */ | 114 | * structure is stored at the end of the shared queue memory. */ |
134 | u32 flags; | 115 | u32 flags; |
135 | 116 | ||
136 | DECLARE_PCI_UNMAP_ADDR(mapping) | 117 | DEFINE_DMA_UNMAP_ADDR(mapping); |
137 | DECLARE_PCI_UNMAP_LEN(len) | 118 | DEFINE_DMA_UNMAP_LEN(len); |
138 | }; | 119 | }; |
139 | 120 | ||
140 | /* | 121 | /* |
@@ -161,7 +142,7 @@ struct iwl_queue { | |||
161 | 142 | ||
162 | /* One for each TFD */ | 143 | /* One for each TFD */ |
163 | struct iwl_tx_info { | 144 | struct iwl_tx_info { |
164 | struct sk_buff *skb[IWL_NUM_OF_TBS - 1]; | 145 | struct sk_buff *skb; |
165 | }; | 146 | }; |
166 | 147 | ||
167 | /** | 148 | /** |
@@ -367,7 +348,7 @@ struct iwl_host_cmd { | |||
367 | /** | 348 | /** |
368 | * struct iwl_rx_queue - Rx queue | 349 | * struct iwl_rx_queue - Rx queue |
369 | * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) | 350 | * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) |
370 | * @dma_addr: bus address of buffer of receive buffer descriptors (rbd) | 351 | * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) |
371 | * @read: Shared index to newest available Rx buffer | 352 | * @read: Shared index to newest available Rx buffer |
372 | * @write: Shared index to oldest written Rx packet | 353 | * @write: Shared index to oldest written Rx packet |
373 | * @free_count: Number of pre-allocated buffers in rx_free | 354 | * @free_count: Number of pre-allocated buffers in rx_free |
@@ -381,7 +362,7 @@ struct iwl_host_cmd { | |||
381 | */ | 362 | */ |
382 | struct iwl_rx_queue { | 363 | struct iwl_rx_queue { |
383 | __le32 *bd; | 364 | __le32 *bd; |
384 | dma_addr_t dma_addr; | 365 | dma_addr_t bd_dma; |
385 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; | 366 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; |
386 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; | 367 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; |
387 | u32 read; | 368 | u32 read; |
@@ -433,7 +414,7 @@ struct iwl_ht_agg { | |||
433 | 414 | ||
434 | 415 | ||
435 | struct iwl_tid_data { | 416 | struct iwl_tid_data { |
436 | u16 seq_number; | 417 | u16 seq_number; /* agn only */ |
437 | u16 tfds_in_queue; | 418 | u16 tfds_in_queue; |
438 | struct iwl_ht_agg agg; | 419 | struct iwl_ht_agg agg; |
439 | }; | 420 | }; |
@@ -583,6 +564,12 @@ enum iwl_ucode_tlv_type { | |||
583 | IWL_UCODE_TLV_INIT_DATA = 4, | 564 | IWL_UCODE_TLV_INIT_DATA = 4, |
584 | IWL_UCODE_TLV_BOOT = 5, | 565 | IWL_UCODE_TLV_BOOT = 5, |
585 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ | 566 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ |
567 | IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, | ||
568 | IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, | ||
569 | IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, | ||
570 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, | ||
571 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, | ||
572 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, | ||
586 | }; | 573 | }; |
587 | 574 | ||
588 | struct iwl_ucode_tlv { | 575 | struct iwl_ucode_tlv { |
@@ -675,6 +662,7 @@ struct iwl_sensitivity_ranges { | |||
675 | * @sw_crypto: 0 for hw, 1 for sw | 662 | * @sw_crypto: 0 for hw, 1 for sw |
676 | * @max_xxx_size: for ucode uses | 663 | * @max_xxx_size: for ucode uses |
677 | * @ct_kill_threshold: temperature threshold | 664 | * @ct_kill_threshold: temperature threshold |
665 | * @beacon_time_tsf_bits: number of valid tsf bits for beacon time | ||
678 | * @calib_init_cfg: setup initial calibrations for the hw | 666 | * @calib_init_cfg: setup initial calibrations for the hw |
679 | * @struct iwl_sensitivity_ranges: range of sensitivity values | 667 | * @struct iwl_sensitivity_ranges: range of sensitivity values |
680 | */ | 668 | */ |
@@ -701,6 +689,7 @@ struct iwl_hw_params { | |||
701 | u32 ct_kill_threshold; /* value in hw-dependent units */ | 689 | u32 ct_kill_threshold; /* value in hw-dependent units */ |
702 | u32 ct_kill_exit_threshold; /* value in hw-dependent units */ | 690 | u32 ct_kill_exit_threshold; /* value in hw-dependent units */ |
703 | /* for 1000, 6000 series and up */ | 691 | /* for 1000, 6000 series and up */ |
692 | u16 beacon_time_tsf_bits; | ||
704 | u32 calib_init_cfg; | 693 | u32 calib_init_cfg; |
705 | const struct iwl_sensitivity_ranges *sens; | 694 | const struct iwl_sensitivity_ranges *sens; |
706 | }; | 695 | }; |
@@ -1075,6 +1064,20 @@ struct iwl_force_reset { | |||
1075 | unsigned long last_force_reset_jiffies; | 1064 | unsigned long last_force_reset_jiffies; |
1076 | }; | 1065 | }; |
1077 | 1066 | ||
1067 | /* extend beacon time format bit shifting */ | ||
1068 | /* | ||
1069 | * for _3945 devices | ||
1070 | * bits 31:24 - extended | ||
1071 | * bits 23:0 - interval | ||
1072 | */ | ||
1073 | #define IWL3945_EXT_BEACON_TIME_POS 24 | ||
1074 | /* | ||
1075 | * for _agn devices | ||
1076 | * bits 31:22 - extended | ||
1077 | * bits 21:0 - interval | ||
1078 | */ | ||
1079 | #define IWLAGN_EXT_BEACON_TIME_POS 22 | ||
1080 | |||
1078 | struct iwl_priv { | 1081 | struct iwl_priv { |
1079 | 1082 | ||
1080 | /* ieee device used by generic ieee processing code */ | 1083 | /* ieee device used by generic ieee processing code */ |
@@ -1109,7 +1112,7 @@ struct iwl_priv { | |||
1109 | /* force reset */ | 1112 | /* force reset */ |
1110 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | 1113 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; |
1111 | 1114 | ||
1112 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. | 1115 | /* we allocate array of iwl_channel_info for NIC's valid channels. |
1113 | * Access via channel # using indirect index array */ | 1116 | * Access via channel # using indirect index array */ |
1114 | struct iwl_channel_info *channel_info; /* channel info array */ | 1117 | struct iwl_channel_info *channel_info; /* channel info array */ |
1115 | u8 channel_count; /* # of channels */ | 1118 | u8 channel_count; /* # of channels */ |
@@ -1127,6 +1130,7 @@ struct iwl_priv { | |||
1127 | void *scan_cmd; | 1130 | void *scan_cmd; |
1128 | enum ieee80211_band scan_band; | 1131 | enum ieee80211_band scan_band; |
1129 | struct cfg80211_scan_request *scan_request; | 1132 | struct cfg80211_scan_request *scan_request; |
1133 | struct ieee80211_vif *scan_vif; | ||
1130 | bool is_internal_short_scan; | 1134 | bool is_internal_short_scan; |
1131 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; | 1135 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; |
1132 | u8 mgmt_tx_ant; | 1136 | u8 mgmt_tx_ant; |
@@ -1174,7 +1178,7 @@ struct iwl_priv { | |||
1174 | struct iwl_switch_rxon switch_rxon; | 1178 | struct iwl_switch_rxon switch_rxon; |
1175 | 1179 | ||
1176 | /* 1st responses from initialize and runtime uCode images. | 1180 | /* 1st responses from initialize and runtime uCode images. |
1177 | * 4965's initialize alive response contains some calibration data. */ | 1181 | * _agn's initialize alive response contains some calibration data. */ |
1178 | struct iwl_init_alive_resp card_alive_init; | 1182 | struct iwl_init_alive_resp card_alive_init; |
1179 | struct iwl_alive_resp card_alive; | 1183 | struct iwl_alive_resp card_alive; |
1180 | 1184 | ||
@@ -1220,18 +1224,12 @@ struct iwl_priv { | |||
1220 | struct iwl_power_mgr power_data; | 1224 | struct iwl_power_mgr power_data; |
1221 | struct iwl_tt_mgmt thermal_throttle; | 1225 | struct iwl_tt_mgmt thermal_throttle; |
1222 | 1226 | ||
1223 | struct iwl_notif_statistics statistics; | ||
1224 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1225 | struct iwl_notif_statistics accum_statistics; | ||
1226 | struct iwl_notif_statistics delta_statistics; | ||
1227 | struct iwl_notif_statistics max_delta; | ||
1228 | #endif | ||
1229 | |||
1230 | /* context information */ | 1227 | /* context information */ |
1231 | u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ | 1228 | u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ |
1232 | u8 mac_addr[ETH_ALEN]; | ||
1233 | 1229 | ||
1234 | /*station table variables */ | 1230 | /* station table variables */ |
1231 | |||
1232 | /* Note: if lock and sta_lock are needed, lock must be acquired first */ | ||
1235 | spinlock_t sta_lock; | 1233 | spinlock_t sta_lock; |
1236 | int num_stations; | 1234 | int num_stations; |
1237 | struct iwl_station_entry stations[IWL_STATION_COUNT]; | 1235 | struct iwl_station_entry stations[IWL_STATION_COUNT]; |
@@ -1273,7 +1271,7 @@ struct iwl_priv { | |||
1273 | struct delayed_work rfkill_poll; | 1271 | struct delayed_work rfkill_poll; |
1274 | 1272 | ||
1275 | struct iwl3945_notif_statistics statistics; | 1273 | struct iwl3945_notif_statistics statistics; |
1276 | #ifdef CONFIG_IWLWIFI_DEBUG | 1274 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1277 | struct iwl3945_notif_statistics accum_statistics; | 1275 | struct iwl3945_notif_statistics accum_statistics; |
1278 | struct iwl3945_notif_statistics delta_statistics; | 1276 | struct iwl3945_notif_statistics delta_statistics; |
1279 | struct iwl3945_notif_statistics max_delta; | 1277 | struct iwl3945_notif_statistics max_delta; |
@@ -1315,6 +1313,16 @@ struct iwl_priv { | |||
1315 | bool last_phy_res_valid; | 1313 | bool last_phy_res_valid; |
1316 | 1314 | ||
1317 | struct completion firmware_loading_complete; | 1315 | struct completion firmware_loading_complete; |
1316 | |||
1317 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
1318 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
1319 | |||
1320 | struct iwl_notif_statistics statistics; | ||
1321 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1322 | struct iwl_notif_statistics accum_statistics; | ||
1323 | struct iwl_notif_statistics delta_statistics; | ||
1324 | struct iwl_notif_statistics max_delta; | ||
1325 | #endif | ||
1318 | } _agn; | 1326 | } _agn; |
1319 | #endif | 1327 | #endif |
1320 | }; | 1328 | }; |
@@ -1353,9 +1361,7 @@ struct iwl_priv { | |||
1353 | /* debugging info */ | 1361 | /* debugging info */ |
1354 | u32 debug_level; /* per device debugging will override global | 1362 | u32 debug_level; /* per device debugging will override global |
1355 | iwl_debug_level if set */ | 1363 | iwl_debug_level if set */ |
1356 | u32 framecnt_to_us; | 1364 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
1357 | atomic_t restrict_refcnt; | ||
1358 | bool disable_ht40; | ||
1359 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1365 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1360 | /* debugfs */ | 1366 | /* debugfs */ |
1361 | u16 tx_traffic_idx; | 1367 | u16 tx_traffic_idx; |
@@ -1364,8 +1370,8 @@ struct iwl_priv { | |||
1364 | u8 *rx_traffic; | 1370 | u8 *rx_traffic; |
1365 | struct dentry *debugfs_dir; | 1371 | struct dentry *debugfs_dir; |
1366 | u32 dbgfs_sram_offset, dbgfs_sram_len; | 1372 | u32 dbgfs_sram_offset, dbgfs_sram_len; |
1373 | bool disable_ht40; | ||
1367 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 1374 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
1368 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
1369 | 1375 | ||
1370 | struct work_struct txpower_work; | 1376 | struct work_struct txpower_work; |
1371 | u32 disable_sens_cal; | 1377 | u32 disable_sens_cal; |
@@ -1419,9 +1425,9 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv) | |||
1419 | static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, | 1425 | static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, |
1420 | int txq_id, int idx) | 1426 | int txq_id, int idx) |
1421 | { | 1427 | { |
1422 | if (priv->txq[txq_id].txb[idx].skb[0]) | 1428 | if (priv->txq[txq_id].txb[idx].skb) |
1423 | return (struct ieee80211_hdr *)priv->txq[txq_id]. | 1429 | return (struct ieee80211_hdr *)priv->txq[txq_id]. |
1424 | txb[idx].skb[0]->data; | 1430 | txb[idx].skb->data; |
1425 | return NULL; | 1431 | return NULL; |
1426 | } | 1432 | } |
1427 | 1433 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 3ff6b9d25a10..621abe3c5afc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -92,6 +92,11 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
92 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, | 92 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, |
93 | struct fw_desc *desc) | 93 | struct fw_desc *desc) |
94 | { | 94 | { |
95 | if (!desc->len) { | ||
96 | desc->v_addr = NULL; | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
95 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, | 100 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, |
96 | &desc->p_addr, GFP_KERNEL); | 101 | &desc->p_addr, GFP_KERNEL); |
97 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | 102 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; |
@@ -170,4 +175,26 @@ static inline void iwl_enable_interrupts(struct iwl_priv *priv) | |||
170 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); | 175 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); |
171 | } | 176 | } |
172 | 177 | ||
178 | /** | ||
179 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time | ||
180 | * @priv -- pointer to iwl_priv data structure | ||
181 | * @tsf_bits -- number of bits need to shift for masking) | ||
182 | */ | ||
183 | static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, | ||
184 | u16 tsf_bits) | ||
185 | { | ||
186 | return (1 << tsf_bits) - 1; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time | ||
191 | * @priv -- pointer to iwl_priv data structure | ||
192 | * @tsf_bits -- number of bits need to shift for masking) | ||
193 | */ | ||
194 | static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, | ||
195 | u16 tsf_bits) | ||
196 | { | ||
197 | return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; | ||
198 | } | ||
199 | |||
173 | #endif /* __iwl_helpers_h__ */ | 200 | #endif /* __iwl_helpers_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0a5d7cf25196..b437f317b979 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -175,7 +175,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
175 | INIT_LIST_HEAD(&rxq->rx_used); | 175 | INIT_LIST_HEAD(&rxq->rx_used); |
176 | 176 | ||
177 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 177 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
178 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, | 178 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, |
179 | GFP_KERNEL); | 179 | GFP_KERNEL); |
180 | if (!rxq->bd) | 180 | if (!rxq->bd) |
181 | goto err_bd; | 181 | goto err_bd; |
@@ -199,32 +199,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
199 | 199 | ||
200 | err_rb: | 200 | err_rb: |
201 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 201 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
202 | rxq->dma_addr); | 202 | rxq->bd_dma); |
203 | err_bd: | 203 | err_bd: |
204 | return -ENOMEM; | 204 | return -ENOMEM; |
205 | } | 205 | } |
206 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | 206 | EXPORT_SYMBOL(iwl_rx_queue_alloc); |
207 | 207 | ||
208 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | ||
209 | struct iwl_rx_mem_buffer *rxb) | ||
210 | |||
211 | { | ||
212 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
213 | struct iwl_missed_beacon_notif *missed_beacon; | ||
214 | |||
215 | missed_beacon = &pkt->u.missed_beacon; | ||
216 | if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) > | ||
217 | priv->missed_beacon_threshold) { | ||
218 | IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", | ||
219 | le32_to_cpu(missed_beacon->consecutive_missed_beacons), | ||
220 | le32_to_cpu(missed_beacon->total_missed_becons), | ||
221 | le32_to_cpu(missed_beacon->num_recvd_beacons), | ||
222 | le32_to_cpu(missed_beacon->num_expected_beacons)); | ||
223 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
224 | iwl_init_sensitivity(priv); | ||
225 | } | ||
226 | } | ||
227 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); | ||
228 | 208 | ||
229 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 209 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
230 | struct iwl_rx_mem_buffer *rxb) | 210 | struct iwl_rx_mem_buffer *rxb) |
@@ -243,161 +223,6 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | |||
243 | } | 223 | } |
244 | EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); | 224 | EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); |
245 | 225 | ||
246 | |||
247 | |||
248 | /* Calculate noise level, based on measurements during network silence just | ||
249 | * before arriving beacon. This measurement can be done only if we know | ||
250 | * exactly when to expect beacons, therefore only when we're associated. */ | ||
251 | static void iwl_rx_calc_noise(struct iwl_priv *priv) | ||
252 | { | ||
253 | struct statistics_rx_non_phy *rx_info | ||
254 | = &(priv->statistics.rx.general); | ||
255 | int num_active_rx = 0; | ||
256 | int total_silence = 0; | ||
257 | int bcn_silence_a = | ||
258 | le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; | ||
259 | int bcn_silence_b = | ||
260 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | ||
261 | int bcn_silence_c = | ||
262 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | ||
263 | int last_rx_noise; | ||
264 | |||
265 | if (bcn_silence_a) { | ||
266 | total_silence += bcn_silence_a; | ||
267 | num_active_rx++; | ||
268 | } | ||
269 | if (bcn_silence_b) { | ||
270 | total_silence += bcn_silence_b; | ||
271 | num_active_rx++; | ||
272 | } | ||
273 | if (bcn_silence_c) { | ||
274 | total_silence += bcn_silence_c; | ||
275 | num_active_rx++; | ||
276 | } | ||
277 | |||
278 | /* Average among active antennas */ | ||
279 | if (num_active_rx) | ||
280 | last_rx_noise = (total_silence / num_active_rx) - 107; | ||
281 | else | ||
282 | last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
283 | |||
284 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", | ||
285 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | ||
286 | last_rx_noise); | ||
287 | } | ||
288 | |||
289 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
290 | /* | ||
291 | * based on the assumption of all statistics counter are in DWORD | ||
292 | * FIXME: This function is for debugging, do not deal with | ||
293 | * the case of counters roll-over. | ||
294 | */ | ||
295 | static void iwl_accumulative_statistics(struct iwl_priv *priv, | ||
296 | __le32 *stats) | ||
297 | { | ||
298 | int i; | ||
299 | __le32 *prev_stats; | ||
300 | u32 *accum_stats; | ||
301 | u32 *delta, *max_delta; | ||
302 | |||
303 | prev_stats = (__le32 *)&priv->statistics; | ||
304 | accum_stats = (u32 *)&priv->accum_statistics; | ||
305 | delta = (u32 *)&priv->delta_statistics; | ||
306 | max_delta = (u32 *)&priv->max_delta; | ||
307 | |||
308 | for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); | ||
309 | i += sizeof(__le32), stats++, prev_stats++, delta++, | ||
310 | max_delta++, accum_stats++) { | ||
311 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { | ||
312 | *delta = (le32_to_cpu(*stats) - | ||
313 | le32_to_cpu(*prev_stats)); | ||
314 | *accum_stats += *delta; | ||
315 | if (*delta > *max_delta) | ||
316 | *max_delta = *delta; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | /* reset accumulative statistics for "no-counter" type statistics */ | ||
321 | priv->accum_statistics.general.temperature = | ||
322 | priv->statistics.general.temperature; | ||
323 | priv->accum_statistics.general.temperature_m = | ||
324 | priv->statistics.general.temperature_m; | ||
325 | priv->accum_statistics.general.ttl_timestamp = | ||
326 | priv->statistics.general.ttl_timestamp; | ||
327 | priv->accum_statistics.tx.tx_power.ant_a = | ||
328 | priv->statistics.tx.tx_power.ant_a; | ||
329 | priv->accum_statistics.tx.tx_power.ant_b = | ||
330 | priv->statistics.tx.tx_power.ant_b; | ||
331 | priv->accum_statistics.tx.tx_power.ant_c = | ||
332 | priv->statistics.tx.tx_power.ant_c; | ||
333 | } | ||
334 | #endif | ||
335 | |||
336 | #define REG_RECALIB_PERIOD (60) | ||
337 | |||
338 | /** | ||
339 | * iwl_good_plcp_health - checks for plcp error. | ||
340 | * | ||
341 | * When the plcp error is exceeding the thresholds, reset the radio | ||
342 | * to improve the throughput. | ||
343 | */ | ||
344 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
345 | struct iwl_rx_packet *pkt) | ||
346 | { | ||
347 | bool rc = true; | ||
348 | int combined_plcp_delta; | ||
349 | unsigned int plcp_msec; | ||
350 | unsigned long plcp_received_jiffies; | ||
351 | |||
352 | /* | ||
353 | * check for plcp_err and trigger radio reset if it exceeds | ||
354 | * the plcp error threshold plcp_delta. | ||
355 | */ | ||
356 | plcp_received_jiffies = jiffies; | ||
357 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
358 | (long) priv->plcp_jiffies); | ||
359 | priv->plcp_jiffies = plcp_received_jiffies; | ||
360 | /* | ||
361 | * check to make sure plcp_msec is not 0 to prevent division | ||
362 | * by zero. | ||
363 | */ | ||
364 | if (plcp_msec) { | ||
365 | combined_plcp_delta = | ||
366 | (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - | ||
367 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) + | ||
368 | (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - | ||
369 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); | ||
370 | |||
371 | if ((combined_plcp_delta > 0) && | ||
372 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
373 | priv->cfg->plcp_delta_threshold) { | ||
374 | /* | ||
375 | * if plcp_err exceed the threshold, | ||
376 | * the following data is printed in csv format: | ||
377 | * Text: plcp_err exceeded %d, | ||
378 | * Received ofdm.plcp_err, | ||
379 | * Current ofdm.plcp_err, | ||
380 | * Received ofdm_ht.plcp_err, | ||
381 | * Current ofdm_ht.plcp_err, | ||
382 | * combined_plcp_delta, | ||
383 | * plcp_msec | ||
384 | */ | ||
385 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | ||
386 | "%u, %u, %u, %u, %d, %u mSecs\n", | ||
387 | priv->cfg->plcp_delta_threshold, | ||
388 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | ||
389 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), | ||
390 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | ||
391 | le32_to_cpu( | ||
392 | priv->statistics.rx.ofdm_ht.plcp_err), | ||
393 | combined_plcp_delta, plcp_msec); | ||
394 | rc = false; | ||
395 | } | ||
396 | } | ||
397 | return rc; | ||
398 | } | ||
399 | EXPORT_SYMBOL(iwl_good_plcp_health); | ||
400 | |||
401 | void iwl_recover_from_statistics(struct iwl_priv *priv, | 226 | void iwl_recover_from_statistics(struct iwl_priv *priv, |
402 | struct iwl_rx_packet *pkt) | 227 | struct iwl_rx_packet *pkt) |
403 | { | 228 | { |
@@ -431,69 +256,6 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, | |||
431 | } | 256 | } |
432 | EXPORT_SYMBOL(iwl_recover_from_statistics); | 257 | EXPORT_SYMBOL(iwl_recover_from_statistics); |
433 | 258 | ||
434 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
435 | struct iwl_rx_mem_buffer *rxb) | ||
436 | { | ||
437 | int change; | ||
438 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
439 | |||
440 | |||
441 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
442 | (int)sizeof(priv->statistics), | ||
443 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
444 | |||
445 | change = ((priv->statistics.general.temperature != | ||
446 | pkt->u.stats.general.temperature) || | ||
447 | ((priv->statistics.flag & | ||
448 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | ||
449 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | ||
450 | |||
451 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
452 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
453 | #endif | ||
454 | iwl_recover_from_statistics(priv, pkt); | ||
455 | |||
456 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | ||
457 | |||
458 | set_bit(STATUS_STATISTICS, &priv->status); | ||
459 | |||
460 | /* Reschedule the statistics timer to occur in | ||
461 | * REG_RECALIB_PERIOD seconds to ensure we get a | ||
462 | * thermal update even if the uCode doesn't give | ||
463 | * us one */ | ||
464 | mod_timer(&priv->statistics_periodic, jiffies + | ||
465 | msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); | ||
466 | |||
467 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | ||
468 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { | ||
469 | iwl_rx_calc_noise(priv); | ||
470 | queue_work(priv->workqueue, &priv->run_time_calib_work); | ||
471 | } | ||
472 | if (priv->cfg->ops->lib->temp_ops.temperature && change) | ||
473 | priv->cfg->ops->lib->temp_ops.temperature(priv); | ||
474 | } | ||
475 | EXPORT_SYMBOL(iwl_rx_statistics); | ||
476 | |||
477 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
478 | struct iwl_rx_mem_buffer *rxb) | ||
479 | { | ||
480 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
481 | |||
482 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { | ||
483 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
484 | memset(&priv->accum_statistics, 0, | ||
485 | sizeof(struct iwl_notif_statistics)); | ||
486 | memset(&priv->delta_statistics, 0, | ||
487 | sizeof(struct iwl_notif_statistics)); | ||
488 | memset(&priv->max_delta, 0, | ||
489 | sizeof(struct iwl_notif_statistics)); | ||
490 | #endif | ||
491 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | ||
492 | } | ||
493 | iwl_rx_statistics(priv, rxb); | ||
494 | } | ||
495 | EXPORT_SYMBOL(iwl_reply_statistics); | ||
496 | |||
497 | /* | 259 | /* |
498 | * returns non-zero if packet should be dropped | 260 | * returns non-zero if packet should be dropped |
499 | */ | 261 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 386c5f96eff8..798f93e0ff50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -333,7 +333,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
333 | goto out_unlock; | 333 | goto out_unlock; |
334 | } | 334 | } |
335 | 335 | ||
336 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 336 | if (test_bit(STATUS_SCANNING, &priv->status) && |
337 | !priv->is_internal_short_scan) { | ||
337 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 338 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
338 | ret = -EAGAIN; | 339 | ret = -EAGAIN; |
339 | goto out_unlock; | 340 | goto out_unlock; |
@@ -348,8 +349,16 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
348 | /* mac80211 will only ask for one band at a time */ | 349 | /* mac80211 will only ask for one band at a time */ |
349 | priv->scan_band = req->channels[0]->band; | 350 | priv->scan_band = req->channels[0]->band; |
350 | priv->scan_request = req; | 351 | priv->scan_request = req; |
352 | priv->scan_vif = vif; | ||
351 | 353 | ||
352 | ret = iwl_scan_initiate(priv, vif); | 354 | /* |
355 | * If an internal scan is in progress, just set | ||
356 | * up the scan_request as per above. | ||
357 | */ | ||
358 | if (priv->is_internal_short_scan) | ||
359 | ret = 0; | ||
360 | else | ||
361 | ret = iwl_scan_initiate(priv, vif); | ||
353 | 362 | ||
354 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 363 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
355 | 364 | ||
@@ -438,7 +447,7 @@ EXPORT_SYMBOL(iwl_bg_scan_check); | |||
438 | */ | 447 | */ |
439 | 448 | ||
440 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 449 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
441 | const u8 *ies, int ie_len, int left) | 450 | const u8 *ta, const u8 *ies, int ie_len, int left) |
442 | { | 451 | { |
443 | int len = 0; | 452 | int len = 0; |
444 | u8 *pos = NULL; | 453 | u8 *pos = NULL; |
@@ -451,7 +460,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
451 | 460 | ||
452 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 461 | frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); |
453 | memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); | 462 | memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); |
454 | memcpy(frame->sa, priv->mac_addr, ETH_ALEN); | 463 | memcpy(frame->sa, ta, ETH_ALEN); |
455 | memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); | 464 | memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); |
456 | frame->seq_ctrl = 0; | 465 | frame->seq_ctrl = 0; |
457 | 466 | ||
@@ -514,7 +523,21 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
514 | priv->is_internal_short_scan = false; | 523 | priv->is_internal_short_scan = false; |
515 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 524 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); |
516 | internal = true; | 525 | internal = true; |
526 | } else { | ||
527 | priv->scan_request = NULL; | ||
528 | priv->scan_vif = NULL; | ||
517 | } | 529 | } |
530 | |||
531 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
532 | goto out; | ||
533 | |||
534 | if (internal && priv->scan_request) | ||
535 | iwl_scan_initiate(priv, priv->scan_vif); | ||
536 | |||
537 | /* Since setting the TXPOWER may have been deferred while | ||
538 | * performing the scan, fire one off */ | ||
539 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
540 | out: | ||
518 | mutex_unlock(&priv->mutex); | 541 | mutex_unlock(&priv->mutex); |
519 | 542 | ||
520 | /* | 543 | /* |
@@ -524,15 +547,6 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
524 | */ | 547 | */ |
525 | if (!internal) | 548 | if (!internal) |
526 | ieee80211_scan_completed(priv->hw, false); | 549 | ieee80211_scan_completed(priv->hw, false); |
527 | |||
528 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
529 | return; | ||
530 | |||
531 | /* Since setting the TXPOWER may have been deferred while | ||
532 | * performing the scan, fire one off */ | ||
533 | mutex_lock(&priv->mutex); | ||
534 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
535 | mutex_unlock(&priv->mutex); | ||
536 | } | 550 | } |
537 | EXPORT_SYMBOL(iwl_bg_scan_completed); | 551 | EXPORT_SYMBOL(iwl_bg_scan_completed); |
538 | 552 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c27c13fbb1ae..6a9cd08bd449 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/lockdep.h> | ||
33 | 34 | ||
34 | #include "iwl-dev.h" | 35 | #include "iwl-dev.h" |
35 | #include "iwl-core.h" | 36 | #include "iwl-core.h" |
@@ -54,18 +55,19 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | |||
54 | } | 55 | } |
55 | } | 56 | } |
56 | 57 | ||
57 | static void iwl_process_add_sta_resp(struct iwl_priv *priv, | 58 | static int iwl_process_add_sta_resp(struct iwl_priv *priv, |
58 | struct iwl_addsta_cmd *addsta, | 59 | struct iwl_addsta_cmd *addsta, |
59 | struct iwl_rx_packet *pkt, | 60 | struct iwl_rx_packet *pkt, |
60 | bool sync) | 61 | bool sync) |
61 | { | 62 | { |
62 | u8 sta_id = addsta->sta.sta_id; | 63 | u8 sta_id = addsta->sta.sta_id; |
63 | unsigned long flags; | 64 | unsigned long flags; |
65 | int ret = -EIO; | ||
64 | 66 | ||
65 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | 67 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
66 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | 68 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", |
67 | pkt->hdr.flags); | 69 | pkt->hdr.flags); |
68 | return; | 70 | return ret; |
69 | } | 71 | } |
70 | 72 | ||
71 | IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", | 73 | IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", |
@@ -77,6 +79,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
77 | case ADD_STA_SUCCESS_MSK: | 79 | case ADD_STA_SUCCESS_MSK: |
78 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | 80 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); |
79 | iwl_sta_ucode_activate(priv, sta_id); | 81 | iwl_sta_ucode_activate(priv, sta_id); |
82 | ret = 0; | ||
80 | break; | 83 | break; |
81 | case ADD_STA_NO_ROOM_IN_TABLE: | 84 | case ADD_STA_NO_ROOM_IN_TABLE: |
82 | IWL_ERR(priv, "Adding station %d failed, no room in table.\n", | 85 | IWL_ERR(priv, "Adding station %d failed, no room in table.\n", |
@@ -114,6 +117,8 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
114 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | 117 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", |
115 | addsta->sta.addr); | 118 | addsta->sta.addr); |
116 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 119 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
120 | |||
121 | return ret; | ||
117 | } | 122 | } |
118 | 123 | ||
119 | static void iwl_add_sta_callback(struct iwl_priv *priv, | 124 | static void iwl_add_sta_callback(struct iwl_priv *priv, |
@@ -145,8 +150,10 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
145 | 150 | ||
146 | if (flags & CMD_ASYNC) | 151 | if (flags & CMD_ASYNC) |
147 | cmd.callback = iwl_add_sta_callback; | 152 | cmd.callback = iwl_add_sta_callback; |
148 | else | 153 | else { |
149 | cmd.flags |= CMD_WANT_SKB; | 154 | cmd.flags |= CMD_WANT_SKB; |
155 | might_sleep(); | ||
156 | } | ||
150 | 157 | ||
151 | cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); | 158 | cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); |
152 | ret = iwl_send_cmd(priv, &cmd); | 159 | ret = iwl_send_cmd(priv, &cmd); |
@@ -156,7 +163,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
156 | 163 | ||
157 | if (ret == 0) { | 164 | if (ret == 0) { |
158 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | 165 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
159 | iwl_process_add_sta_resp(priv, sta, pkt, true); | 166 | ret = iwl_process_add_sta_resp(priv, sta, pkt, true); |
160 | } | 167 | } |
161 | iwl_free_pages(priv, cmd.reply_page); | 168 | iwl_free_pages(priv, cmd.reply_page); |
162 | 169 | ||
@@ -311,10 +318,10 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | |||
311 | struct ieee80211_sta_ht_cap *ht_info, | 318 | struct ieee80211_sta_ht_cap *ht_info, |
312 | u8 *sta_id_r) | 319 | u8 *sta_id_r) |
313 | { | 320 | { |
314 | struct iwl_station_entry *station; | ||
315 | unsigned long flags_spin; | 321 | unsigned long flags_spin; |
316 | int ret = 0; | 322 | int ret = 0; |
317 | u8 sta_id; | 323 | u8 sta_id; |
324 | struct iwl_addsta_cmd sta_cmd; | ||
318 | 325 | ||
319 | *sta_id_r = 0; | 326 | *sta_id_r = 0; |
320 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 327 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
@@ -347,14 +354,15 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | |||
347 | } | 354 | } |
348 | 355 | ||
349 | priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; | 356 | priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; |
350 | station = &priv->stations[sta_id]; | 357 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
351 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 358 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
352 | 359 | ||
353 | /* Add station to device's station table */ | 360 | /* Add station to device's station table */ |
354 | ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); | 361 | ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
355 | if (ret) { | 362 | if (ret) { |
356 | IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr); | ||
357 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 363 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
364 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
365 | priv->stations[sta_id].sta.sta.addr); | ||
358 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | 366 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; |
359 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | 367 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; |
360 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 368 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
@@ -488,7 +496,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) | |||
488 | } | 496 | } |
489 | 497 | ||
490 | static int iwl_send_remove_station(struct iwl_priv *priv, | 498 | static int iwl_send_remove_station(struct iwl_priv *priv, |
491 | struct iwl_station_entry *station) | 499 | const u8 *addr, int sta_id) |
492 | { | 500 | { |
493 | struct iwl_rx_packet *pkt; | 501 | struct iwl_rx_packet *pkt; |
494 | int ret; | 502 | int ret; |
@@ -505,7 +513,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
505 | 513 | ||
506 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); | 514 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); |
507 | rm_sta_cmd.num_sta = 1; | 515 | rm_sta_cmd.num_sta = 1; |
508 | memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); | 516 | memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN); |
509 | 517 | ||
510 | cmd.flags |= CMD_WANT_SKB; | 518 | cmd.flags |= CMD_WANT_SKB; |
511 | 519 | ||
@@ -525,7 +533,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
525 | switch (pkt->u.rem_sta.status) { | 533 | switch (pkt->u.rem_sta.status) { |
526 | case REM_STA_SUCCESS_MSK: | 534 | case REM_STA_SUCCESS_MSK: |
527 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 535 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
528 | iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); | 536 | iwl_sta_ucode_deactivate(priv, sta_id); |
529 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 537 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
530 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 538 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
531 | break; | 539 | break; |
@@ -546,7 +554,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
546 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | 554 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, |
547 | const u8 *addr) | 555 | const u8 *addr) |
548 | { | 556 | { |
549 | struct iwl_station_entry *station; | ||
550 | unsigned long flags; | 557 | unsigned long flags; |
551 | 558 | ||
552 | if (!iwl_is_ready(priv)) { | 559 | if (!iwl_is_ready(priv)) { |
@@ -592,10 +599,9 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | |||
592 | 599 | ||
593 | BUG_ON(priv->num_stations < 0); | 600 | BUG_ON(priv->num_stations < 0); |
594 | 601 | ||
595 | station = &priv->stations[sta_id]; | ||
596 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 602 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
597 | 603 | ||
598 | return iwl_send_remove_station(priv, station); | 604 | return iwl_send_remove_station(priv, addr, sta_id); |
599 | out_err: | 605 | out_err: |
600 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 606 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
601 | return -EINVAL; | 607 | return -EINVAL; |
@@ -643,11 +649,13 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations); | |||
643 | */ | 649 | */ |
644 | void iwl_restore_stations(struct iwl_priv *priv) | 650 | void iwl_restore_stations(struct iwl_priv *priv) |
645 | { | 651 | { |
646 | struct iwl_station_entry *station; | 652 | struct iwl_addsta_cmd sta_cmd; |
653 | struct iwl_link_quality_cmd lq; | ||
647 | unsigned long flags_spin; | 654 | unsigned long flags_spin; |
648 | int i; | 655 | int i; |
649 | bool found = false; | 656 | bool found = false; |
650 | int ret; | 657 | int ret; |
658 | bool send_lq; | ||
651 | 659 | ||
652 | if (!iwl_is_ready(priv)) { | 660 | if (!iwl_is_ready(priv)) { |
653 | IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); | 661 | IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); |
@@ -669,13 +677,20 @@ void iwl_restore_stations(struct iwl_priv *priv) | |||
669 | 677 | ||
670 | for (i = 0; i < priv->hw_params.max_stations; i++) { | 678 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
671 | if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { | 679 | if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { |
680 | memcpy(&sta_cmd, &priv->stations[i].sta, | ||
681 | sizeof(struct iwl_addsta_cmd)); | ||
682 | send_lq = false; | ||
683 | if (priv->stations[i].lq) { | ||
684 | memcpy(&lq, priv->stations[i].lq, | ||
685 | sizeof(struct iwl_link_quality_cmd)); | ||
686 | send_lq = true; | ||
687 | } | ||
672 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 688 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
673 | station = &priv->stations[i]; | 689 | ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
674 | ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC); | ||
675 | if (ret) { | 690 | if (ret) { |
676 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
677 | station->sta.sta.addr); | ||
678 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 691 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
692 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
693 | priv->stations[i].sta.sta.addr); | ||
679 | priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; | 694 | priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; |
680 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | 695 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; |
681 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 696 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
@@ -684,8 +699,8 @@ void iwl_restore_stations(struct iwl_priv *priv) | |||
684 | * Rate scaling has already been initialized, send | 699 | * Rate scaling has already been initialized, send |
685 | * current LQ command | 700 | * current LQ command |
686 | */ | 701 | */ |
687 | if (station->lq) | 702 | if (send_lq) |
688 | iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); | 703 | iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true); |
689 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 704 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
690 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | 705 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; |
691 | } | 706 | } |
@@ -823,7 +838,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
823 | { | 838 | { |
824 | unsigned long flags; | 839 | unsigned long flags; |
825 | __le16 key_flags = 0; | 840 | __le16 key_flags = 0; |
826 | int ret; | 841 | struct iwl_addsta_cmd sta_cmd; |
842 | |||
843 | lockdep_assert_held(&priv->mutex); | ||
827 | 844 | ||
828 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | 845 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; |
829 | 846 | ||
@@ -863,11 +880,10 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
863 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 880 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
864 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 881 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
865 | 882 | ||
866 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 883 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
867 | |||
868 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 884 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
869 | 885 | ||
870 | return ret; | 886 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
871 | } | 887 | } |
872 | 888 | ||
873 | static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | 889 | static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, |
@@ -876,7 +892,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
876 | { | 892 | { |
877 | unsigned long flags; | 893 | unsigned long flags; |
878 | __le16 key_flags = 0; | 894 | __le16 key_flags = 0; |
879 | int ret; | 895 | struct iwl_addsta_cmd sta_cmd; |
896 | |||
897 | lockdep_assert_held(&priv->mutex); | ||
880 | 898 | ||
881 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); | 899 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); |
882 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 900 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
@@ -911,11 +929,10 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
911 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 929 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
912 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 930 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
913 | 931 | ||
914 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 932 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
915 | |||
916 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 933 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
917 | 934 | ||
918 | return ret; | 935 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
919 | } | 936 | } |
920 | 937 | ||
921 | static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | 938 | static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, |
@@ -972,24 +989,16 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
972 | unsigned long flags; | 989 | unsigned long flags; |
973 | int i; | 990 | int i; |
974 | 991 | ||
975 | if (sta) { | ||
976 | sta_id = iwl_sta_id(sta); | ||
977 | |||
978 | if (sta_id == IWL_INVALID_STATION) { | ||
979 | IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", | ||
980 | sta->addr); | ||
981 | return; | ||
982 | } | ||
983 | } else | ||
984 | sta_id = priv->hw_params.bcast_sta_id; | ||
985 | |||
986 | |||
987 | if (iwl_scan_cancel(priv)) { | 992 | if (iwl_scan_cancel(priv)) { |
988 | /* cancel scan failed, just live w/ bad key and rely | 993 | /* cancel scan failed, just live w/ bad key and rely |
989 | briefly on SW decryption */ | 994 | briefly on SW decryption */ |
990 | return; | 995 | return; |
991 | } | 996 | } |
992 | 997 | ||
998 | sta_id = iwl_sta_id_or_broadcast(priv, sta); | ||
999 | if (sta_id == IWL_INVALID_STATION) | ||
1000 | return; | ||
1001 | |||
993 | spin_lock_irqsave(&priv->sta_lock, flags); | 1002 | spin_lock_irqsave(&priv->sta_lock, flags); |
994 | 1003 | ||
995 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; | 1004 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; |
@@ -1013,9 +1022,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
1013 | u8 sta_id) | 1022 | u8 sta_id) |
1014 | { | 1023 | { |
1015 | unsigned long flags; | 1024 | unsigned long flags; |
1016 | int ret = 0; | ||
1017 | u16 key_flags; | 1025 | u16 key_flags; |
1018 | u8 keyidx; | 1026 | u8 keyidx; |
1027 | struct iwl_addsta_cmd sta_cmd; | ||
1028 | |||
1029 | lockdep_assert_held(&priv->mutex); | ||
1019 | 1030 | ||
1020 | priv->key_mapping_key--; | 1031 | priv->key_mapping_key--; |
1021 | 1032 | ||
@@ -1062,9 +1073,10 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
1062 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1073 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1063 | return 0; | 1074 | return 0; |
1064 | } | 1075 | } |
1065 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1076 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
1066 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1077 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1067 | return ret; | 1078 | |
1079 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | ||
1068 | } | 1080 | } |
1069 | EXPORT_SYMBOL(iwl_remove_dynamic_key); | 1081 | EXPORT_SYMBOL(iwl_remove_dynamic_key); |
1070 | 1082 | ||
@@ -1073,6 +1085,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, | |||
1073 | { | 1085 | { |
1074 | int ret; | 1086 | int ret; |
1075 | 1087 | ||
1088 | lockdep_assert_held(&priv->mutex); | ||
1089 | |||
1076 | priv->key_mapping_key++; | 1090 | priv->key_mapping_key++; |
1077 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 1091 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
1078 | 1092 | ||
@@ -1268,18 +1282,22 @@ EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); | |||
1268 | /** | 1282 | /** |
1269 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table | 1283 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table |
1270 | */ | 1284 | */ |
1271 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) | 1285 | int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) |
1272 | { | 1286 | { |
1273 | unsigned long flags; | 1287 | unsigned long flags; |
1288 | struct iwl_addsta_cmd sta_cmd; | ||
1289 | |||
1290 | lockdep_assert_held(&priv->mutex); | ||
1274 | 1291 | ||
1275 | /* Remove "disable" flag, to enable Tx for this TID */ | 1292 | /* Remove "disable" flag, to enable Tx for this TID */ |
1276 | spin_lock_irqsave(&priv->sta_lock, flags); | 1293 | spin_lock_irqsave(&priv->sta_lock, flags); |
1277 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; | 1294 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; |
1278 | priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); | 1295 | priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); |
1279 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1296 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1297 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | ||
1280 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1298 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1281 | 1299 | ||
1282 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1300 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
1283 | } | 1301 | } |
1284 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); | 1302 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); |
1285 | 1303 | ||
@@ -1288,6 +1306,9 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
1288 | { | 1306 | { |
1289 | unsigned long flags; | 1307 | unsigned long flags; |
1290 | int sta_id; | 1308 | int sta_id; |
1309 | struct iwl_addsta_cmd sta_cmd; | ||
1310 | |||
1311 | lockdep_assert_held(&priv->mutex); | ||
1291 | 1312 | ||
1292 | sta_id = iwl_sta_id(sta); | 1313 | sta_id = iwl_sta_id(sta); |
1293 | if (sta_id == IWL_INVALID_STATION) | 1314 | if (sta_id == IWL_INVALID_STATION) |
@@ -1299,10 +1320,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
1299 | priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; | 1320 | priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; |
1300 | priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); | 1321 | priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); |
1301 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1322 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1323 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | ||
1302 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1324 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1303 | 1325 | ||
1304 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | 1326 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
1305 | CMD_ASYNC); | ||
1306 | } | 1327 | } |
1307 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); | 1328 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); |
1308 | 1329 | ||
@@ -1311,6 +1332,9 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
1311 | { | 1332 | { |
1312 | unsigned long flags; | 1333 | unsigned long flags; |
1313 | int sta_id; | 1334 | int sta_id; |
1335 | struct iwl_addsta_cmd sta_cmd; | ||
1336 | |||
1337 | lockdep_assert_held(&priv->mutex); | ||
1314 | 1338 | ||
1315 | sta_id = iwl_sta_id(sta); | 1339 | sta_id = iwl_sta_id(sta); |
1316 | if (sta_id == IWL_INVALID_STATION) { | 1340 | if (sta_id == IWL_INVALID_STATION) { |
@@ -1323,10 +1347,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
1323 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; | 1347 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; |
1324 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; | 1348 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; |
1325 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1349 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1350 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | ||
1326 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1351 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1327 | 1352 | ||
1328 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | 1353 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
1329 | CMD_ASYNC); | ||
1330 | } | 1354 | } |
1331 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | 1355 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); |
1332 | 1356 | ||
@@ -1340,9 +1364,9 @@ void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1340 | priv->stations[sta_id].sta.sta.modify_mask = 0; | 1364 | priv->stations[sta_id].sta.sta.modify_mask = 0; |
1341 | priv->stations[sta_id].sta.sleep_tx_count = 0; | 1365 | priv->stations[sta_id].sta.sleep_tx_count = 0; |
1342 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1366 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1367 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1343 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1368 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1344 | 1369 | ||
1345 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1346 | } | 1370 | } |
1347 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); | 1371 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); |
1348 | 1372 | ||
@@ -1357,9 +1381,9 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1357 | STA_MODIFY_SLEEP_TX_COUNT_MSK; | 1381 | STA_MODIFY_SLEEP_TX_COUNT_MSK; |
1358 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); | 1382 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); |
1359 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1383 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1384 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1360 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1385 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1361 | 1386 | ||
1362 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1363 | } | 1387 | } |
1364 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | 1388 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); |
1365 | 1389 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index c2a453a1a991..619bb99d85cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -73,7 +73,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | |||
73 | const u8 *addr); | 73 | const u8 *addr); |
74 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 74 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
75 | struct ieee80211_sta *sta); | 75 | struct ieee80211_sta *sta); |
76 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); | 76 | int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); |
77 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, | 77 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, |
78 | int tid, u16 ssn); | 78 | int tid, u16 ssn); |
79 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | 79 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, |
@@ -107,4 +107,33 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) | |||
107 | 107 | ||
108 | return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; | 108 | return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; |
109 | } | 109 | } |
110 | |||
111 | /** | ||
112 | * iwl_sta_id_or_broadcast - return sta_id or broadcast sta | ||
113 | * @priv: iwl priv | ||
114 | * @sta: mac80211 station | ||
115 | * | ||
116 | * In certain circumstances mac80211 passes a station pointer | ||
117 | * that may be %NULL, for example during TX or key setup. In | ||
118 | * that case, we need to use the broadcast station, so this | ||
119 | * inline wraps that pattern. | ||
120 | */ | ||
121 | static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv, | ||
122 | struct ieee80211_sta *sta) | ||
123 | { | ||
124 | int sta_id; | ||
125 | |||
126 | if (!sta) | ||
127 | return priv->hw_params.bcast_sta_id; | ||
128 | |||
129 | sta_id = iwl_sta_id(sta); | ||
130 | |||
131 | /* | ||
132 | * mac80211 should not be passing a partially | ||
133 | * initialised station! | ||
134 | */ | ||
135 | WARN_ON(sta_id == IWL_INVALID_STATION); | ||
136 | |||
137 | return sta_id; | ||
138 | } | ||
110 | #endif /* __iwl_sta_h__ */ | 139 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1ece2ea09773..a81989c06983 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -77,21 +77,6 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
77 | } | 77 | } |
78 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | 78 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); |
79 | 79 | ||
80 | |||
81 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
82 | int sta_id, int tid, int freed) | ||
83 | { | ||
84 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | ||
85 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
86 | else { | ||
87 | IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", | ||
88 | priv->stations[sta_id].tid[tid].tfds_in_queue, | ||
89 | freed); | ||
90 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | ||
91 | } | ||
92 | } | ||
93 | EXPORT_SYMBOL(iwl_free_tfds_in_queue); | ||
94 | |||
95 | /** | 80 | /** |
96 | * iwl_tx_queue_free - Deallocate DMA queue. | 81 | * iwl_tx_queue_free - Deallocate DMA queue. |
97 | * @txq: Transmit queue to deallocate. | 82 | * @txq: Transmit queue to deallocate. |
@@ -169,15 +154,15 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
169 | } | 154 | } |
170 | 155 | ||
171 | pci_unmap_single(priv->pci_dev, | 156 | pci_unmap_single(priv->pci_dev, |
172 | pci_unmap_addr(&txq->meta[i], mapping), | 157 | dma_unmap_addr(&txq->meta[i], mapping), |
173 | pci_unmap_len(&txq->meta[i], len), | 158 | dma_unmap_len(&txq->meta[i], len), |
174 | PCI_DMA_BIDIRECTIONAL); | 159 | PCI_DMA_BIDIRECTIONAL); |
175 | } | 160 | } |
176 | if (huge) { | 161 | if (huge) { |
177 | i = q->n_window; | 162 | i = q->n_window; |
178 | pci_unmap_single(priv->pci_dev, | 163 | pci_unmap_single(priv->pci_dev, |
179 | pci_unmap_addr(&txq->meta[i], mapping), | 164 | dma_unmap_addr(&txq->meta[i], mapping), |
180 | pci_unmap_len(&txq->meta[i], len), | 165 | dma_unmap_len(&txq->meta[i], len), |
181 | PCI_DMA_BIDIRECTIONAL); | 166 | PCI_DMA_BIDIRECTIONAL); |
182 | } | 167 | } |
183 | 168 | ||
@@ -287,7 +272,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
287 | /* Driver private data, only for Tx (not command) queues, | 272 | /* Driver private data, only for Tx (not command) queues, |
288 | * not shared with device. */ | 273 | * not shared with device. */ |
289 | if (id != IWL_CMD_QUEUE_NUM) { | 274 | if (id != IWL_CMD_QUEUE_NUM) { |
290 | txq->txb = kmalloc(sizeof(txq->txb[0]) * | 275 | txq->txb = kzalloc(sizeof(txq->txb[0]) * |
291 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | 276 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); |
292 | if (!txq->txb) { | 277 | if (!txq->txb) { |
293 | IWL_ERR(priv, "kmalloc for auxiliary BD " | 278 | IWL_ERR(priv, "kmalloc for auxiliary BD " |
@@ -531,8 +516,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
531 | 516 | ||
532 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, | 517 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, |
533 | fix_size, PCI_DMA_BIDIRECTIONAL); | 518 | fix_size, PCI_DMA_BIDIRECTIONAL); |
534 | pci_unmap_addr_set(out_meta, mapping, phys_addr); | 519 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
535 | pci_unmap_len_set(out_meta, len, fix_size); | 520 | dma_unmap_len_set(out_meta, len, fix_size); |
536 | 521 | ||
537 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | 522 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); |
538 | 523 | ||
@@ -626,8 +611,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
626 | meta = &txq->meta[cmd_index]; | 611 | meta = &txq->meta[cmd_index]; |
627 | 612 | ||
628 | pci_unmap_single(priv->pci_dev, | 613 | pci_unmap_single(priv->pci_dev, |
629 | pci_unmap_addr(meta, mapping), | 614 | dma_unmap_addr(meta, mapping), |
630 | pci_unmap_len(meta, len), | 615 | dma_unmap_len(meta, len), |
631 | PCI_DMA_BIDIRECTIONAL); | 616 | PCI_DMA_BIDIRECTIONAL); |
632 | 617 | ||
633 | /* Input error checking is done when commands are added to queue. */ | 618 | /* Input error checking is done when commands are added to queue. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a27872de4106..8eb347106902 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -197,6 +197,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
197 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | 197 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) |
198 | { | 198 | { |
199 | unsigned long flags; | 199 | unsigned long flags; |
200 | struct iwl_addsta_cmd sta_cmd; | ||
200 | 201 | ||
201 | spin_lock_irqsave(&priv->sta_lock, flags); | 202 | spin_lock_irqsave(&priv->sta_lock, flags); |
202 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); | 203 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); |
@@ -205,11 +206,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | |||
205 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; | 206 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; |
206 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 207 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
207 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 208 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
209 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | ||
208 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 210 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
209 | 211 | ||
210 | IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); | 212 | IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); |
211 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); | 213 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); |
212 | return 0; | ||
213 | } | 214 | } |
214 | 215 | ||
215 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, | 216 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, |
@@ -474,10 +475,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
474 | u8 unicast; | 475 | u8 unicast; |
475 | u8 sta_id; | 476 | u8 sta_id; |
476 | u8 tid = 0; | 477 | u8 tid = 0; |
477 | u16 seq_number = 0; | ||
478 | __le16 fc; | 478 | __le16 fc; |
479 | u8 wait_write_ptr = 0; | 479 | u8 wait_write_ptr = 0; |
480 | u8 *qc = NULL; | ||
481 | unsigned long flags; | 480 | unsigned long flags; |
482 | 481 | ||
483 | spin_lock_irqsave(&priv->lock, flags); | 482 | spin_lock_irqsave(&priv->lock, flags); |
@@ -510,10 +509,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
510 | hdr_len = ieee80211_hdrlen(fc); | 509 | hdr_len = ieee80211_hdrlen(fc); |
511 | 510 | ||
512 | /* Find index into station table for destination station */ | 511 | /* Find index into station table for destination station */ |
513 | if (!info->control.sta) | 512 | sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); |
514 | sta_id = priv->hw_params.bcast_sta_id; | ||
515 | else | ||
516 | sta_id = iwl_sta_id(info->control.sta); | ||
517 | if (sta_id == IWL_INVALID_STATION) { | 513 | if (sta_id == IWL_INVALID_STATION) { |
518 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 514 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
519 | hdr->addr1); | 515 | hdr->addr1); |
@@ -523,16 +519,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
523 | IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); | 519 | IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); |
524 | 520 | ||
525 | if (ieee80211_is_data_qos(fc)) { | 521 | if (ieee80211_is_data_qos(fc)) { |
526 | qc = ieee80211_get_qos_ctl(hdr); | 522 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
527 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 523 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
528 | if (unlikely(tid >= MAX_TID_COUNT)) | 524 | if (unlikely(tid >= MAX_TID_COUNT)) |
529 | goto drop; | 525 | goto drop; |
530 | seq_number = priv->stations[sta_id].tid[tid].seq_number & | ||
531 | IEEE80211_SCTL_SEQ; | ||
532 | hdr->seq_ctrl = cpu_to_le16(seq_number) | | ||
533 | (hdr->seq_ctrl & | ||
534 | cpu_to_le16(IEEE80211_SCTL_FRAG)); | ||
535 | seq_number += 0x10; | ||
536 | } | 526 | } |
537 | 527 | ||
538 | /* Descriptor for chosen Tx queue */ | 528 | /* Descriptor for chosen Tx queue */ |
@@ -548,7 +538,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
548 | 538 | ||
549 | /* Set up driver data for this TFD */ | 539 | /* Set up driver data for this TFD */ |
550 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 540 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
551 | txq->txb[q->write_ptr].skb[0] = skb; | 541 | txq->txb[q->write_ptr].skb = skb; |
552 | 542 | ||
553 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | 543 | /* Init first empty entry in queue's array of Tx/cmd buffers */ |
554 | out_cmd = txq->cmd[idx]; | 544 | out_cmd = txq->cmd[idx]; |
@@ -591,8 +581,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
591 | 581 | ||
592 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 582 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
593 | txq->need_update = 1; | 583 | txq->need_update = 1; |
594 | if (qc) | ||
595 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
596 | } else { | 584 | } else { |
597 | wait_write_ptr = 1; | 585 | wait_write_ptr = 1; |
598 | txq->need_update = 0; | 586 | txq->need_update = 0; |
@@ -631,8 +619,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
631 | len, PCI_DMA_TODEVICE); | 619 | len, PCI_DMA_TODEVICE); |
632 | /* we do not map meta data ... so we can safely access address to | 620 | /* we do not map meta data ... so we can safely access address to |
633 | * provide to unmap command*/ | 621 | * provide to unmap command*/ |
634 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | 622 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
635 | pci_unmap_len_set(out_meta, len, len); | 623 | dma_unmap_len_set(out_meta, len, len); |
636 | 624 | ||
637 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 625 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
638 | * first entry */ | 626 | * first entry */ |
@@ -677,55 +665,6 @@ drop: | |||
677 | return -1; | 665 | return -1; |
678 | } | 666 | } |
679 | 667 | ||
680 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | ||
681 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | ||
682 | #define TIME_UNIT 1024 | ||
683 | |||
684 | /* | ||
685 | * extended beacon time format | ||
686 | * time in usec will be changed into a 32-bit value in 8:24 format | ||
687 | * the high 1 byte is the beacon counts | ||
688 | * the lower 3 bytes is the time in usec within one beacon interval | ||
689 | */ | ||
690 | |||
691 | static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval) | ||
692 | { | ||
693 | u32 quot; | ||
694 | u32 rem; | ||
695 | u32 interval = beacon_interval * 1024; | ||
696 | |||
697 | if (!interval || !usec) | ||
698 | return 0; | ||
699 | |||
700 | quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); | ||
701 | rem = (usec % interval) & BEACON_TIME_MASK_LOW; | ||
702 | |||
703 | return (quot << 24) + rem; | ||
704 | } | ||
705 | |||
706 | /* base is usually what we get from ucode with each received frame, | ||
707 | * the same as HW timer counter counting down | ||
708 | */ | ||
709 | |||
710 | static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) | ||
711 | { | ||
712 | u32 base_low = base & BEACON_TIME_MASK_LOW; | ||
713 | u32 addon_low = addon & BEACON_TIME_MASK_LOW; | ||
714 | u32 interval = beacon_interval * TIME_UNIT; | ||
715 | u32 res = (base & BEACON_TIME_MASK_HIGH) + | ||
716 | (addon & BEACON_TIME_MASK_HIGH); | ||
717 | |||
718 | if (base_low > addon_low) | ||
719 | res += base_low - addon_low; | ||
720 | else if (base_low < addon_low) { | ||
721 | res += interval + base_low - addon_low; | ||
722 | res += (1 << 24); | ||
723 | } else | ||
724 | res += (1 << 24); | ||
725 | |||
726 | return cpu_to_le32(res); | ||
727 | } | ||
728 | |||
729 | static int iwl3945_get_measurement(struct iwl_priv *priv, | 668 | static int iwl3945_get_measurement(struct iwl_priv *priv, |
730 | struct ieee80211_measurement_params *params, | 669 | struct ieee80211_measurement_params *params, |
731 | u8 type) | 670 | u8 type) |
@@ -743,8 +682,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
743 | int duration = le16_to_cpu(params->duration); | 682 | int duration = le16_to_cpu(params->duration); |
744 | 683 | ||
745 | if (iwl_is_associated(priv)) | 684 | if (iwl_is_associated(priv)) |
746 | add_time = | 685 | add_time = iwl_usecs_to_beacons(priv, |
747 | iwl3945_usecs_to_beacons( | ||
748 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, | 686 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, |
749 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 687 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
750 | 688 | ||
@@ -759,8 +697,8 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
759 | 697 | ||
760 | if (iwl_is_associated(priv)) | 698 | if (iwl_is_associated(priv)) |
761 | spectrum.start_time = | 699 | spectrum.start_time = |
762 | iwl3945_add_beacon_time(priv->_3945.last_beacon_time, | 700 | iwl_add_beacon_time(priv, |
763 | add_time, | 701 | priv->_3945.last_beacon_time, add_time, |
764 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 702 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
765 | else | 703 | else |
766 | spectrum.start_time = 0; | 704 | spectrum.start_time = 0; |
@@ -1233,7 +1171,7 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx | |||
1233 | } | 1171 | } |
1234 | 1172 | ||
1235 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 1173 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
1236 | rxq->dma_addr); | 1174 | rxq->bd_dma); |
1237 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | 1175 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
1238 | rxq->rb_stts, rxq->rb_stts_dma); | 1176 | rxq->rb_stts, rxq->rb_stts_dma); |
1239 | rxq->bd = NULL; | 1177 | rxq->bd = NULL; |
@@ -1314,6 +1252,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1314 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); | 1252 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); |
1315 | 1253 | ||
1316 | while (i != r) { | 1254 | while (i != r) { |
1255 | int len; | ||
1256 | |||
1317 | rxb = rxq->queue[i]; | 1257 | rxb = rxq->queue[i]; |
1318 | 1258 | ||
1319 | /* If an RXB doesn't have a Rx queue slot associated with it, | 1259 | /* If an RXB doesn't have a Rx queue slot associated with it, |
@@ -1328,8 +1268,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1328 | PCI_DMA_FROMDEVICE); | 1268 | PCI_DMA_FROMDEVICE); |
1329 | pkt = rxb_addr(rxb); | 1269 | pkt = rxb_addr(rxb); |
1330 | 1270 | ||
1331 | trace_iwlwifi_dev_rx(priv, pkt, | 1271 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
1332 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 1272 | len += sizeof(u32); /* account for status word */ |
1273 | trace_iwlwifi_dev_rx(priv, pkt, len); | ||
1333 | 1274 | ||
1334 | /* Reclaim a command buffer only if this packet is a response | 1275 | /* Reclaim a command buffer only if this packet is a response |
1335 | * to a (driver-originated) command. | 1276 | * to a (driver-originated) command. |
@@ -1483,7 +1424,7 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1483 | iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); | 1424 | iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); |
1484 | 1425 | ||
1485 | IWL_ERR(priv, | 1426 | IWL_ERR(priv, |
1486 | "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", | 1427 | "%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", |
1487 | desc_lookup(desc), desc, time, blink1, blink2, | 1428 | desc_lookup(desc), desc, time, blink1, blink2, |
1488 | ilink1, ilink2, data1); | 1429 | ilink1, ilink2, data1); |
1489 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0, | 1430 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0, |
@@ -3022,14 +2963,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3022 | scan->tx_cmd.len = cpu_to_le16( | 2963 | scan->tx_cmd.len = cpu_to_le16( |
3023 | iwl_fill_probe_req(priv, | 2964 | iwl_fill_probe_req(priv, |
3024 | (struct ieee80211_mgmt *)scan->data, | 2965 | (struct ieee80211_mgmt *)scan->data, |
2966 | vif->addr, | ||
3025 | priv->scan_request->ie, | 2967 | priv->scan_request->ie, |
3026 | priv->scan_request->ie_len, | 2968 | priv->scan_request->ie_len, |
3027 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | 2969 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); |
3028 | } else { | 2970 | } else { |
2971 | /* use bcast addr, will not be transmitted but must be valid */ | ||
3029 | scan->tx_cmd.len = cpu_to_le16( | 2972 | scan->tx_cmd.len = cpu_to_le16( |
3030 | iwl_fill_probe_req(priv, | 2973 | iwl_fill_probe_req(priv, |
3031 | (struct ieee80211_mgmt *)scan->data, | 2974 | (struct ieee80211_mgmt *)scan->data, |
3032 | NULL, 0, | 2975 | iwl_bcast_addr, NULL, 0, |
3033 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | 2976 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); |
3034 | } | 2977 | } |
3035 | /* select Rx antennas */ | 2978 | /* select Rx antennas */ |
@@ -3158,19 +3101,16 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3158 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3101 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
3159 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | 3102 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
3160 | 3103 | ||
3161 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3104 | if (vif->bss_conf.use_short_preamble) |
3162 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3105 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
3163 | else | 3106 | else |
3164 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3107 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3165 | 3108 | ||
3166 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3109 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3167 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3110 | if (vif->bss_conf.use_short_slot) |
3168 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3111 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
3169 | else | 3112 | else |
3170 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3113 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
3171 | |||
3172 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3173 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
3174 | } | 3114 | } |
3175 | 3115 | ||
3176 | iwlcore_commit_rxon(priv); | 3116 | iwlcore_commit_rxon(priv); |
@@ -3334,8 +3274,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3334 | 3274 | ||
3335 | priv->staging_rxon.assoc_id = 0; | 3275 | priv->staging_rxon.assoc_id = 0; |
3336 | 3276 | ||
3337 | if (vif->bss_conf.assoc_capability & | 3277 | if (vif->bss_conf.use_short_preamble) |
3338 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
3339 | priv->staging_rxon.flags |= | 3278 | priv->staging_rxon.flags |= |
3340 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3279 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3341 | else | 3280 | else |
@@ -3343,17 +3282,12 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3343 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3282 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3344 | 3283 | ||
3345 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3284 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3346 | if (vif->bss_conf.assoc_capability & | 3285 | if (vif->bss_conf.use_short_slot) |
3347 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
3348 | priv->staging_rxon.flags |= | 3286 | priv->staging_rxon.flags |= |
3349 | RXON_FLG_SHORT_SLOT_MSK; | 3287 | RXON_FLG_SHORT_SLOT_MSK; |
3350 | else | 3288 | else |
3351 | priv->staging_rxon.flags &= | 3289 | priv->staging_rxon.flags &= |
3352 | ~RXON_FLG_SHORT_SLOT_MSK; | 3290 | ~RXON_FLG_SHORT_SLOT_MSK; |
3353 | |||
3354 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3355 | priv->staging_rxon.flags &= | ||
3356 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
3357 | } | 3291 | } |
3358 | /* restore RXON assoc */ | 3292 | /* restore RXON assoc */ |
3359 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3293 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
@@ -3386,17 +3320,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3386 | static_key = !iwl_is_associated(priv); | 3320 | static_key = !iwl_is_associated(priv); |
3387 | 3321 | ||
3388 | if (!static_key) { | 3322 | if (!static_key) { |
3389 | if (!sta) { | 3323 | sta_id = iwl_sta_id_or_broadcast(priv, sta); |
3390 | sta_id = priv->hw_params.bcast_sta_id; | 3324 | if (sta_id == IWL_INVALID_STATION) |
3391 | } else { | 3325 | return -EINVAL; |
3392 | sta_id = iwl_sta_id(sta); | ||
3393 | if (sta_id == IWL_INVALID_STATION) { | ||
3394 | IWL_DEBUG_MAC80211(priv, | ||
3395 | "leave - %pM not in station map.\n", | ||
3396 | sta->addr); | ||
3397 | return -EINVAL; | ||
3398 | } | ||
3399 | } | ||
3400 | } | 3326 | } |
3401 | 3327 | ||
3402 | mutex_lock(&priv->mutex); | 3328 | mutex_lock(&priv->mutex); |
@@ -4028,9 +3954,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4028 | priv->pci_dev = pdev; | 3954 | priv->pci_dev = pdev; |
4029 | priv->inta_mask = CSR_INI_SET_MASK; | 3955 | priv->inta_mask = CSR_INI_SET_MASK; |
4030 | 3956 | ||
4031 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
4032 | atomic_set(&priv->restrict_refcnt, 0); | ||
4033 | #endif | ||
4034 | if (iwl_alloc_traffic_mem(priv)) | 3957 | if (iwl_alloc_traffic_mem(priv)) |
4035 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 3958 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
4036 | 3959 | ||
@@ -4099,9 +4022,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4099 | } | 4022 | } |
4100 | /* MAC Address location in EEPROM same for 3945/4965 */ | 4023 | /* MAC Address location in EEPROM same for 3945/4965 */ |
4101 | eeprom = (struct iwl3945_eeprom *)priv->eeprom; | 4024 | eeprom = (struct iwl3945_eeprom *)priv->eeprom; |
4102 | memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN); | 4025 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address); |
4103 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); | 4026 | SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address); |
4104 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | ||
4105 | 4027 | ||
4106 | /*********************** | 4028 | /*********************** |
4107 | * 5. Setup HW Constants | 4029 | * 5. Setup HW Constants |
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 902e95f70f6e..60619678f4ec 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -670,20 +670,24 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, | |||
670 | } | 670 | } |
671 | 671 | ||
672 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, | 672 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, |
673 | enum tx_power_setting type, int dbm) | 673 | enum nl80211_tx_power_setting type, int mbm) |
674 | { | 674 | { |
675 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | 675 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); |
676 | int ret; | 676 | int ret; |
677 | 677 | ||
678 | switch (type) { | 678 | switch (type) { |
679 | case TX_POWER_AUTOMATIC: | 679 | case NL80211_TX_POWER_AUTOMATIC: |
680 | return 0; | 680 | return 0; |
681 | case TX_POWER_FIXED: | 681 | case NL80211_TX_POWER_FIXED: |
682 | if (mbm < 0 || (mbm % 100)) | ||
683 | return -EOPNOTSUPP; | ||
684 | |||
682 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 685 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) |
683 | return 0; | 686 | return 0; |
684 | 687 | ||
685 | ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, | 688 | ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, |
686 | CFG_TX_PWR_LIMIT_USR, dbm * 2); | 689 | CFG_TX_PWR_LIMIT_USR, |
690 | MBM_TO_DBM(mbm) * 2); | ||
687 | if (ret < 0) | 691 | if (ret < 0) |
688 | return ret; | 692 | return ret; |
689 | 693 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index 9531b18cf72a..907ac890997c 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c | |||
@@ -54,7 +54,7 @@ | |||
54 | * LMAC. If you look at LMAC commands you'll se that they | 54 | * LMAC. If you look at LMAC commands you'll se that they |
55 | * are actually regular iwlwifi target commands encapsulated | 55 | * are actually regular iwlwifi target commands encapsulated |
56 | * into a special UMAC command called UMAC passthrough. | 56 | * into a special UMAC command called UMAC passthrough. |
57 | * This is due to the fact the the host talks exclusively | 57 | * This is due to the fact the host talks exclusively |
58 | * to the UMAC and so there needs to be a special UMAC | 58 | * to the UMAC and so there needs to be a special UMAC |
59 | * command for talking to the LMAC. | 59 | * command for talking to the LMAC. |
60 | * This is how a wifi command is layed out: | 60 | * This is how a wifi command is layed out: |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index e1184deca559..c02fcedea9fa 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -321,14 +321,14 @@ iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket) | |||
321 | return ERR_PTR(-ENOMEM); | 321 | return ERR_PTR(-ENOMEM); |
322 | } | 322 | } |
323 | 323 | ||
324 | ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL); | 324 | ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket), |
325 | GFP_KERNEL); | ||
325 | if (!ticket_node->ticket) { | 326 | if (!ticket_node->ticket) { |
326 | IWM_ERR(iwm, "Couldn't allocate RX ticket\n"); | 327 | IWM_ERR(iwm, "Couldn't allocate RX ticket\n"); |
327 | kfree(ticket_node); | 328 | kfree(ticket_node); |
328 | return ERR_PTR(-ENOMEM); | 329 | return ERR_PTR(-ENOMEM); |
329 | } | 330 | } |
330 | 331 | ||
331 | memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket)); | ||
332 | INIT_LIST_HEAD(&ticket_node->node); | 332 | INIT_LIST_HEAD(&ticket_node->node); |
333 | 333 | ||
334 | return ticket_node; | 334 | return ticket_node; |
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 45e870e33117..f7d01bfa2e4a 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | libertas-y += assoc.o | ||
2 | libertas-y += cfg.o | 1 | libertas-y += cfg.o |
3 | libertas-y += cmd.o | 2 | libertas-y += cmd.o |
4 | libertas-y += cmdresp.o | 3 | libertas-y += cmdresp.o |
@@ -6,9 +5,7 @@ libertas-y += debugfs.o | |||
6 | libertas-y += ethtool.o | 5 | libertas-y += ethtool.o |
7 | libertas-y += main.o | 6 | libertas-y += main.o |
8 | libertas-y += rx.o | 7 | libertas-y += rx.o |
9 | libertas-y += scan.o | ||
10 | libertas-y += tx.o | 8 | libertas-y += tx.o |
11 | libertas-y += wext.o | ||
12 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o | 9 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o |
13 | 10 | ||
14 | usb8xxx-objs += if_usb.o | 11 | usb8xxx-objs += if_usb.o |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c deleted file mode 100644 index aa06070e5eab..000000000000 --- a/drivers/net/wireless/libertas/assoc.c +++ /dev/null | |||
@@ -1,2264 +0,0 @@ | |||
1 | /* Copyright (C) 2006, Red Hat, Inc. */ | ||
2 | |||
3 | #include <linux/types.h> | ||
4 | #include <linux/etherdevice.h> | ||
5 | #include <linux/ieee80211.h> | ||
6 | #include <linux/if_arp.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <net/lib80211.h> | ||
9 | |||
10 | #include "assoc.h" | ||
11 | #include "decl.h" | ||
12 | #include "host.h" | ||
13 | #include "scan.h" | ||
14 | #include "cmd.h" | ||
15 | |||
16 | static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = | ||
17 | { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
18 | static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = | ||
19 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
20 | |||
21 | /* The firmware needs the following bits masked out of the beacon-derived | ||
22 | * capability field when associating/joining to a BSS: | ||
23 | * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) | ||
24 | */ | ||
25 | #define CAPINFO_MASK (~(0xda00)) | ||
26 | |||
27 | /** | ||
28 | * 802.11b/g supported bitrates (in 500Kb/s units) | ||
29 | */ | ||
30 | u8 lbs_bg_rates[MAX_RATES] = | ||
31 | { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, | ||
32 | 0x00, 0x00 }; | ||
33 | |||
34 | |||
35 | static int assoc_helper_wep_keys(struct lbs_private *priv, | ||
36 | struct assoc_request *assoc_req); | ||
37 | |||
38 | /** | ||
39 | * @brief This function finds common rates between rates and card rates. | ||
40 | * | ||
41 | * It will fill common rates in rates as output if found. | ||
42 | * | ||
43 | * NOTE: Setting the MSB of the basic rates need to be taken | ||
44 | * care, either before or after calling this function | ||
45 | * | ||
46 | * @param priv A pointer to struct lbs_private structure | ||
47 | * @param rates the buffer which keeps input and output | ||
48 | * @param rates_size the size of rates buffer; new size of buffer on return, | ||
49 | * which will be less than or equal to original rates_size | ||
50 | * | ||
51 | * @return 0 on success, or -1 on error | ||
52 | */ | ||
53 | static int get_common_rates(struct lbs_private *priv, | ||
54 | u8 *rates, | ||
55 | u16 *rates_size) | ||
56 | { | ||
57 | int i, j; | ||
58 | u8 intersection[MAX_RATES]; | ||
59 | u16 intersection_size; | ||
60 | u16 num_rates = 0; | ||
61 | |||
62 | intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection)); | ||
63 | |||
64 | /* Allow each rate from 'rates' that is supported by the hardware */ | ||
65 | for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) { | ||
66 | for (j = 0; j < intersection_size && rates[j]; j++) { | ||
67 | if (rates[j] == lbs_bg_rates[i]) | ||
68 | intersection[num_rates++] = rates[j]; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); | ||
73 | lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates, | ||
74 | ARRAY_SIZE(lbs_bg_rates)); | ||
75 | lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates); | ||
76 | lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); | ||
77 | |||
78 | if (!priv->enablehwauto) { | ||
79 | for (i = 0; i < num_rates; i++) { | ||
80 | if (intersection[i] == priv->cur_rate) | ||
81 | goto done; | ||
82 | } | ||
83 | lbs_pr_alert("Previously set fixed data rate %#x isn't " | ||
84 | "compatible with the network.\n", priv->cur_rate); | ||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | done: | ||
89 | memset(rates, 0, *rates_size); | ||
90 | *rates_size = num_rates; | ||
91 | memcpy(rates, intersection, num_rates); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * @brief Sets the MSB on basic rates as the firmware requires | ||
98 | * | ||
99 | * Scan through an array and set the MSB for basic data rates. | ||
100 | * | ||
101 | * @param rates buffer of data rates | ||
102 | * @param len size of buffer | ||
103 | */ | ||
104 | static void lbs_set_basic_rate_flags(u8 *rates, size_t len) | ||
105 | { | ||
106 | int i; | ||
107 | |||
108 | for (i = 0; i < len; i++) { | ||
109 | if (rates[i] == 0x02 || rates[i] == 0x04 || | ||
110 | rates[i] == 0x0b || rates[i] == 0x16) | ||
111 | rates[i] |= 0x80; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | |||
116 | static u8 iw_auth_to_ieee_auth(u8 auth) | ||
117 | { | ||
118 | if (auth == IW_AUTH_ALG_OPEN_SYSTEM) | ||
119 | return 0x00; | ||
120 | else if (auth == IW_AUTH_ALG_SHARED_KEY) | ||
121 | return 0x01; | ||
122 | else if (auth == IW_AUTH_ALG_LEAP) | ||
123 | return 0x80; | ||
124 | |||
125 | lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * @brief This function prepares the authenticate command. AUTHENTICATE only | ||
131 | * sets the authentication suite for future associations, as the firmware | ||
132 | * handles authentication internally during the ASSOCIATE command. | ||
133 | * | ||
134 | * @param priv A pointer to struct lbs_private structure | ||
135 | * @param bssid The peer BSSID with which to authenticate | ||
136 | * @param auth The authentication mode to use (from wireless.h) | ||
137 | * | ||
138 | * @return 0 or -1 | ||
139 | */ | ||
140 | static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth) | ||
141 | { | ||
142 | struct cmd_ds_802_11_authenticate cmd; | ||
143 | int ret = -1; | ||
144 | |||
145 | lbs_deb_enter(LBS_DEB_JOIN); | ||
146 | |||
147 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
148 | memcpy(cmd.bssid, bssid, ETH_ALEN); | ||
149 | |||
150 | cmd.authtype = iw_auth_to_ieee_auth(auth); | ||
151 | |||
152 | lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype); | ||
153 | |||
154 | ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); | ||
155 | |||
156 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | |||
161 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
162 | struct assoc_request *assoc) | ||
163 | { | ||
164 | struct cmd_ds_802_11_set_wep cmd; | ||
165 | int ret = 0; | ||
166 | |||
167 | lbs_deb_enter(LBS_DEB_CMD); | ||
168 | |||
169 | memset(&cmd, 0, sizeof(cmd)); | ||
170 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | ||
171 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
172 | |||
173 | cmd.action = cpu_to_le16(cmd_action); | ||
174 | |||
175 | if (cmd_action == CMD_ACT_ADD) { | ||
176 | int i; | ||
177 | |||
178 | /* default tx key index */ | ||
179 | cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & | ||
180 | CMD_WEP_KEY_INDEX_MASK); | ||
181 | |||
182 | /* Copy key types and material to host command structure */ | ||
183 | for (i = 0; i < 4; i++) { | ||
184 | struct enc_key *pkey = &assoc->wep_keys[i]; | ||
185 | |||
186 | switch (pkey->len) { | ||
187 | case KEY_LEN_WEP_40: | ||
188 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
189 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
190 | lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); | ||
191 | break; | ||
192 | case KEY_LEN_WEP_104: | ||
193 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
194 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
195 | lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); | ||
196 | break; | ||
197 | case 0: | ||
198 | break; | ||
199 | default: | ||
200 | lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", | ||
201 | i, pkey->len); | ||
202 | ret = -1; | ||
203 | goto done; | ||
204 | break; | ||
205 | } | ||
206 | } | ||
207 | } else if (cmd_action == CMD_ACT_REMOVE) { | ||
208 | /* ACT_REMOVE clears _all_ WEP keys */ | ||
209 | |||
210 | /* default tx key index */ | ||
211 | cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & | ||
212 | CMD_WEP_KEY_INDEX_MASK); | ||
213 | lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); | ||
214 | } | ||
215 | |||
216 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
217 | done: | ||
218 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
223 | uint16_t *enable) | ||
224 | { | ||
225 | struct cmd_ds_802_11_enable_rsn cmd; | ||
226 | int ret; | ||
227 | |||
228 | lbs_deb_enter(LBS_DEB_CMD); | ||
229 | |||
230 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
231 | cmd.action = cpu_to_le16(cmd_action); | ||
232 | |||
233 | if (cmd_action == CMD_ACT_GET) | ||
234 | cmd.enable = 0; | ||
235 | else { | ||
236 | if (*enable) | ||
237 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | ||
238 | else | ||
239 | cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); | ||
240 | lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); | ||
241 | } | ||
242 | |||
243 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
244 | if (!ret && cmd_action == CMD_ACT_GET) | ||
245 | *enable = le16_to_cpu(cmd.enable); | ||
246 | |||
247 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, | ||
252 | struct enc_key *key) | ||
253 | { | ||
254 | lbs_deb_enter(LBS_DEB_CMD); | ||
255 | |||
256 | if (key->flags & KEY_INFO_WPA_ENABLED) | ||
257 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | ||
258 | if (key->flags & KEY_INFO_WPA_UNICAST) | ||
259 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | ||
260 | if (key->flags & KEY_INFO_WPA_MCAST) | ||
261 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | ||
262 | |||
263 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
264 | keyparam->keytypeid = cpu_to_le16(key->type); | ||
265 | keyparam->keylen = cpu_to_le16(key->len); | ||
266 | memcpy(keyparam->key, key->key, key->len); | ||
267 | |||
268 | /* Length field doesn't include the {type,length} header */ | ||
269 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); | ||
270 | lbs_deb_leave(LBS_DEB_CMD); | ||
271 | } | ||
272 | |||
273 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
274 | struct assoc_request *assoc) | ||
275 | { | ||
276 | struct cmd_ds_802_11_key_material cmd; | ||
277 | int ret = 0; | ||
278 | int index = 0; | ||
279 | |||
280 | lbs_deb_enter(LBS_DEB_CMD); | ||
281 | |||
282 | cmd.action = cpu_to_le16(cmd_action); | ||
283 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
284 | |||
285 | if (cmd_action == CMD_ACT_GET) { | ||
286 | cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2); | ||
287 | } else { | ||
288 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); | ||
289 | |||
290 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { | ||
291 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
292 | &assoc->wpa_unicast_key); | ||
293 | index++; | ||
294 | } | ||
295 | |||
296 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { | ||
297 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
298 | &assoc->wpa_mcast_key); | ||
299 | index++; | ||
300 | } | ||
301 | |||
302 | /* The common header and as many keys as we included */ | ||
303 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), | ||
304 | keyParamSet[index])); | ||
305 | } | ||
306 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | ||
307 | /* Copy the returned key to driver private data */ | ||
308 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
309 | void *buf_ptr = cmd.keyParamSet; | ||
310 | void *resp_end = &(&cmd)[1]; | ||
311 | |||
312 | while (buf_ptr < resp_end) { | ||
313 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
314 | struct enc_key *key; | ||
315 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
316 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
317 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
318 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
319 | void *end; | ||
320 | |||
321 | end = (void *)keyparam + sizeof(keyparam->type) | ||
322 | + sizeof(keyparam->length) + param_set_len; | ||
323 | |||
324 | /* Make sure we don't access past the end of the IEs */ | ||
325 | if (end > resp_end) | ||
326 | break; | ||
327 | |||
328 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
329 | key = &priv->wpa_unicast_key; | ||
330 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
331 | key = &priv->wpa_mcast_key; | ||
332 | else | ||
333 | break; | ||
334 | |||
335 | /* Copy returned key into driver */ | ||
336 | memset(key, 0, sizeof(struct enc_key)); | ||
337 | if (key_len > sizeof(key->key)) | ||
338 | break; | ||
339 | key->type = key_type; | ||
340 | key->flags = key_flags; | ||
341 | key->len = key_len; | ||
342 | memcpy(key->key, keyparam->key, key->len); | ||
343 | |||
344 | buf_ptr = end + 1; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) | ||
353 | { | ||
354 | /* Bit Rate | ||
355 | * 15:13 Reserved | ||
356 | * 12 54 Mbps | ||
357 | * 11 48 Mbps | ||
358 | * 10 36 Mbps | ||
359 | * 9 24 Mbps | ||
360 | * 8 18 Mbps | ||
361 | * 7 12 Mbps | ||
362 | * 6 9 Mbps | ||
363 | * 5 6 Mbps | ||
364 | * 4 Reserved | ||
365 | * 3 11 Mbps | ||
366 | * 2 5.5 Mbps | ||
367 | * 1 2 Mbps | ||
368 | * 0 1 Mbps | ||
369 | **/ | ||
370 | |||
371 | uint16_t ratemask; | ||
372 | int i = lbs_data_rate_to_fw_index(rate); | ||
373 | if (lower_rates_ok) | ||
374 | ratemask = (0x1fef >> (12 - i)); | ||
375 | else | ||
376 | ratemask = (1 << i); | ||
377 | return cpu_to_le16(ratemask); | ||
378 | } | ||
379 | |||
380 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
381 | uint16_t cmd_action) | ||
382 | { | ||
383 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
384 | int ret; | ||
385 | |||
386 | lbs_deb_enter(LBS_DEB_CMD); | ||
387 | |||
388 | if (!priv->cur_rate && !priv->enablehwauto) | ||
389 | return -EINVAL; | ||
390 | |||
391 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
392 | |||
393 | cmd.action = cpu_to_le16(cmd_action); | ||
394 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | ||
395 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | ||
396 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | ||
397 | if (!ret && cmd_action == CMD_ACT_GET) | ||
398 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | ||
399 | |||
400 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * @brief Set the data rate | ||
406 | * | ||
407 | * @param priv A pointer to struct lbs_private structure | ||
408 | * @param rate The desired data rate, or 0 to clear a locked rate | ||
409 | * | ||
410 | * @return 0 on success, error on failure | ||
411 | */ | ||
412 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate) | ||
413 | { | ||
414 | struct cmd_ds_802_11_data_rate cmd; | ||
415 | int ret = 0; | ||
416 | |||
417 | lbs_deb_enter(LBS_DEB_CMD); | ||
418 | |||
419 | memset(&cmd, 0, sizeof(cmd)); | ||
420 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
421 | |||
422 | if (rate > 0) { | ||
423 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); | ||
424 | cmd.rates[0] = lbs_data_rate_to_fw_index(rate); | ||
425 | if (cmd.rates[0] == 0) { | ||
426 | lbs_deb_cmd("DATA_RATE: invalid requested rate of" | ||
427 | " 0x%02X\n", rate); | ||
428 | ret = 0; | ||
429 | goto out; | ||
430 | } | ||
431 | lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); | ||
432 | } else { | ||
433 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); | ||
434 | lbs_deb_cmd("DATA_RATE: setting auto\n"); | ||
435 | } | ||
436 | |||
437 | ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); | ||
438 | if (ret) | ||
439 | goto out; | ||
440 | |||
441 | lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd)); | ||
442 | |||
443 | /* FIXME: get actual rates FW can do if this command actually returns | ||
444 | * all data rates supported. | ||
445 | */ | ||
446 | priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); | ||
447 | lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); | ||
448 | |||
449 | out: | ||
450 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | |||
455 | int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
456 | struct cmd_ds_command *cmd) | ||
457 | { | ||
458 | |||
459 | lbs_deb_enter(LBS_DEB_CMD); | ||
460 | cmd->command = cpu_to_le16(CMD_802_11_RSSI); | ||
461 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + | ||
462 | sizeof(struct cmd_header)); | ||
463 | cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
464 | |||
465 | /* reset Beacon SNR/NF/RSSI values */ | ||
466 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
467 | priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; | ||
468 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
469 | priv->NF[TYPE_BEACON][TYPE_AVG] = 0; | ||
470 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
471 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; | ||
472 | |||
473 | lbs_deb_leave(LBS_DEB_CMD); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
478 | struct cmd_ds_command *resp) | ||
479 | { | ||
480 | struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; | ||
481 | |||
482 | lbs_deb_enter(LBS_DEB_CMD); | ||
483 | |||
484 | /* store the non average value */ | ||
485 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); | ||
486 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = | ||
487 | get_unaligned_le16(&rssirsp->noisefloor); | ||
488 | |||
489 | priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); | ||
490 | priv->NF[TYPE_BEACON][TYPE_AVG] = | ||
491 | get_unaligned_le16(&rssirsp->avgnoisefloor); | ||
492 | |||
493 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = | ||
494 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], | ||
495 | priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
496 | |||
497 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = | ||
498 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, | ||
499 | priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); | ||
500 | |||
501 | lbs_deb_cmd("RSSI: beacon %d, avg %d\n", | ||
502 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG], | ||
503 | priv->RSSI[TYPE_BEACON][TYPE_AVG]); | ||
504 | |||
505 | lbs_deb_leave(LBS_DEB_CMD); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | |||
510 | int lbs_cmd_bcn_ctrl(struct lbs_private *priv, | ||
511 | struct cmd_ds_command *cmd, | ||
512 | u16 cmd_action) | ||
513 | { | ||
514 | struct cmd_ds_802_11_beacon_control | ||
515 | *bcn_ctrl = &cmd->params.bcn_ctrl; | ||
516 | |||
517 | lbs_deb_enter(LBS_DEB_CMD); | ||
518 | cmd->size = | ||
519 | cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) | ||
520 | + sizeof(struct cmd_header)); | ||
521 | cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); | ||
522 | |||
523 | bcn_ctrl->action = cpu_to_le16(cmd_action); | ||
524 | bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); | ||
525 | bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); | ||
526 | |||
527 | lbs_deb_leave(LBS_DEB_CMD); | ||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv, | ||
532 | struct cmd_ds_command *resp) | ||
533 | { | ||
534 | struct cmd_ds_802_11_beacon_control *bcn_ctrl = | ||
535 | &resp->params.bcn_ctrl; | ||
536 | |||
537 | lbs_deb_enter(LBS_DEB_CMD); | ||
538 | |||
539 | if (bcn_ctrl->action == CMD_ACT_GET) { | ||
540 | priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); | ||
541 | priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); | ||
542 | } | ||
543 | |||
544 | lbs_deb_enter(LBS_DEB_CMD); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | |||
549 | |||
550 | static int lbs_assoc_post(struct lbs_private *priv, | ||
551 | struct cmd_ds_802_11_associate_response *resp) | ||
552 | { | ||
553 | int ret = 0; | ||
554 | union iwreq_data wrqu; | ||
555 | struct bss_descriptor *bss; | ||
556 | u16 status_code; | ||
557 | |||
558 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
559 | |||
560 | if (!priv->in_progress_assoc_req) { | ||
561 | lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); | ||
562 | ret = -1; | ||
563 | goto done; | ||
564 | } | ||
565 | bss = &priv->in_progress_assoc_req->bss; | ||
566 | |||
567 | /* | ||
568 | * Older FW versions map the IEEE 802.11 Status Code in the association | ||
569 | * response to the following values returned in resp->statuscode: | ||
570 | * | ||
571 | * IEEE Status Code Marvell Status Code | ||
572 | * 0 -> 0x0000 ASSOC_RESULT_SUCCESS | ||
573 | * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
574 | * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
575 | * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
576 | * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
577 | * others -> 0x0003 ASSOC_RESULT_REFUSED | ||
578 | * | ||
579 | * Other response codes: | ||
580 | * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) | ||
581 | * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for | ||
582 | * association response from the AP) | ||
583 | */ | ||
584 | |||
585 | status_code = le16_to_cpu(resp->statuscode); | ||
586 | if (priv->fwrelease < 0x09000000) { | ||
587 | switch (status_code) { | ||
588 | case 0x00: | ||
589 | break; | ||
590 | case 0x01: | ||
591 | lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); | ||
592 | break; | ||
593 | case 0x02: | ||
594 | lbs_deb_assoc("ASSOC_RESP: internal timer " | ||
595 | "expired while waiting for the AP\n"); | ||
596 | break; | ||
597 | case 0x03: | ||
598 | lbs_deb_assoc("ASSOC_RESP: association " | ||
599 | "refused by AP\n"); | ||
600 | break; | ||
601 | case 0x04: | ||
602 | lbs_deb_assoc("ASSOC_RESP: authentication " | ||
603 | "refused by AP\n"); | ||
604 | break; | ||
605 | default: | ||
606 | lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " | ||
607 | " unknown\n", status_code); | ||
608 | break; | ||
609 | } | ||
610 | } else { | ||
611 | /* v9+ returns the AP's association response */ | ||
612 | lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code); | ||
613 | } | ||
614 | |||
615 | if (status_code) { | ||
616 | lbs_mac_event_disconnected(priv); | ||
617 | ret = status_code; | ||
618 | goto done; | ||
619 | } | ||
620 | |||
621 | lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", | ||
622 | (void *) (resp + sizeof (resp->hdr)), | ||
623 | le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr)); | ||
624 | |||
625 | /* Send a Media Connected event, according to the Spec */ | ||
626 | priv->connect_status = LBS_CONNECTED; | ||
627 | |||
628 | /* Update current SSID and BSSID */ | ||
629 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); | ||
630 | priv->curbssparams.ssid_len = bss->ssid_len; | ||
631 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | ||
632 | |||
633 | priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; | ||
634 | priv->NF[TYPE_RXPD][TYPE_AVG] = 0; | ||
635 | |||
636 | memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); | ||
637 | memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); | ||
638 | priv->nextSNRNF = 0; | ||
639 | priv->numSNRNF = 0; | ||
640 | |||
641 | netif_carrier_on(priv->dev); | ||
642 | if (!priv->tx_pending_len) | ||
643 | netif_wake_queue(priv->dev); | ||
644 | |||
645 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
646 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
647 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
648 | |||
649 | done: | ||
650 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
651 | return ret; | ||
652 | } | ||
653 | |||
654 | /** | ||
655 | * @brief This function prepares an association-class command. | ||
656 | * | ||
657 | * @param priv A pointer to struct lbs_private structure | ||
658 | * @param assoc_req The association request describing the BSS to associate | ||
659 | * or reassociate with | ||
660 | * @param command The actual command, either CMD_802_11_ASSOCIATE or | ||
661 | * CMD_802_11_REASSOCIATE | ||
662 | * | ||
663 | * @return 0 or -1 | ||
664 | */ | ||
665 | static int lbs_associate(struct lbs_private *priv, | ||
666 | struct assoc_request *assoc_req, | ||
667 | u16 command) | ||
668 | { | ||
669 | struct cmd_ds_802_11_associate cmd; | ||
670 | int ret = 0; | ||
671 | struct bss_descriptor *bss = &assoc_req->bss; | ||
672 | u8 *pos = &(cmd.iebuf[0]); | ||
673 | u16 tmpcap, tmplen, tmpauth; | ||
674 | struct mrvl_ie_ssid_param_set *ssid; | ||
675 | struct mrvl_ie_ds_param_set *ds; | ||
676 | struct mrvl_ie_cf_param_set *cf; | ||
677 | struct mrvl_ie_rates_param_set *rates; | ||
678 | struct mrvl_ie_rsn_param_set *rsn; | ||
679 | struct mrvl_ie_auth_type *auth; | ||
680 | |||
681 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
682 | |||
683 | BUG_ON((command != CMD_802_11_ASSOCIATE) && | ||
684 | (command != CMD_802_11_REASSOCIATE)); | ||
685 | |||
686 | memset(&cmd, 0, sizeof(cmd)); | ||
687 | cmd.hdr.command = cpu_to_le16(command); | ||
688 | |||
689 | /* Fill in static fields */ | ||
690 | memcpy(cmd.bssid, bss->bssid, ETH_ALEN); | ||
691 | cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); | ||
692 | |||
693 | /* Capability info */ | ||
694 | tmpcap = (bss->capability & CAPINFO_MASK); | ||
695 | if (bss->mode == IW_MODE_INFRA) | ||
696 | tmpcap |= WLAN_CAPABILITY_ESS; | ||
697 | cmd.capability = cpu_to_le16(tmpcap); | ||
698 | lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); | ||
699 | |||
700 | /* SSID */ | ||
701 | ssid = (struct mrvl_ie_ssid_param_set *) pos; | ||
702 | ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
703 | tmplen = bss->ssid_len; | ||
704 | ssid->header.len = cpu_to_le16(tmplen); | ||
705 | memcpy(ssid->ssid, bss->ssid, tmplen); | ||
706 | pos += sizeof(ssid->header) + tmplen; | ||
707 | |||
708 | ds = (struct mrvl_ie_ds_param_set *) pos; | ||
709 | ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); | ||
710 | ds->header.len = cpu_to_le16(1); | ||
711 | ds->channel = bss->phy.ds.channel; | ||
712 | pos += sizeof(ds->header) + 1; | ||
713 | |||
714 | cf = (struct mrvl_ie_cf_param_set *) pos; | ||
715 | cf->header.type = cpu_to_le16(TLV_TYPE_CF); | ||
716 | tmplen = sizeof(*cf) - sizeof (cf->header); | ||
717 | cf->header.len = cpu_to_le16(tmplen); | ||
718 | /* IE payload should be zeroed, firmware fills it in for us */ | ||
719 | pos += sizeof(*cf); | ||
720 | |||
721 | rates = (struct mrvl_ie_rates_param_set *) pos; | ||
722 | rates->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
723 | tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES); | ||
724 | memcpy(&rates->rates, &bss->rates, tmplen); | ||
725 | if (get_common_rates(priv, rates->rates, &tmplen)) { | ||
726 | ret = -1; | ||
727 | goto done; | ||
728 | } | ||
729 | pos += sizeof(rates->header) + tmplen; | ||
730 | rates->header.len = cpu_to_le16(tmplen); | ||
731 | lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); | ||
732 | |||
733 | /* Copy the infra. association rates into Current BSS state structure */ | ||
734 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
735 | memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); | ||
736 | |||
737 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
738 | * copying to current bss rates. | ||
739 | */ | ||
740 | lbs_set_basic_rate_flags(rates->rates, tmplen); | ||
741 | |||
742 | /* Firmware v9+ indicate authentication suites as a TLV */ | ||
743 | if (priv->fwrelease >= 0x09000000) { | ||
744 | auth = (struct mrvl_ie_auth_type *) pos; | ||
745 | auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); | ||
746 | auth->header.len = cpu_to_le16(2); | ||
747 | tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode); | ||
748 | auth->auth = cpu_to_le16(tmpauth); | ||
749 | pos += sizeof(auth->header) + 2; | ||
750 | |||
751 | lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", | ||
752 | bss->bssid, priv->secinfo.auth_mode); | ||
753 | } | ||
754 | |||
755 | /* WPA/WPA2 IEs */ | ||
756 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { | ||
757 | rsn = (struct mrvl_ie_rsn_param_set *) pos; | ||
758 | /* WPA_IE or WPA2_IE */ | ||
759 | rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); | ||
760 | tmplen = (u16) assoc_req->wpa_ie[1]; | ||
761 | rsn->header.len = cpu_to_le16(tmplen); | ||
762 | memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); | ||
763 | lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn, | ||
764 | sizeof(rsn->header) + tmplen); | ||
765 | pos += sizeof(rsn->header) + tmplen; | ||
766 | } | ||
767 | |||
768 | cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) + | ||
769 | (u16)(pos - (u8 *) &cmd.iebuf)); | ||
770 | |||
771 | /* update curbssparams */ | ||
772 | priv->channel = bss->phy.ds.channel; | ||
773 | |||
774 | ret = lbs_cmd_with_response(priv, command, &cmd); | ||
775 | if (ret == 0) { | ||
776 | ret = lbs_assoc_post(priv, | ||
777 | (struct cmd_ds_802_11_associate_response *) &cmd); | ||
778 | } | ||
779 | |||
780 | done: | ||
781 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
782 | return ret; | ||
783 | } | ||
784 | |||
785 | /** | ||
786 | * @brief Associate to a specific BSS discovered in a scan | ||
787 | * | ||
788 | * @param priv A pointer to struct lbs_private structure | ||
789 | * @param assoc_req The association request describing the BSS to associate with | ||
790 | * | ||
791 | * @return 0-success, otherwise fail | ||
792 | */ | ||
793 | static int lbs_try_associate(struct lbs_private *priv, | ||
794 | struct assoc_request *assoc_req) | ||
795 | { | ||
796 | int ret; | ||
797 | u8 preamble = RADIO_PREAMBLE_LONG; | ||
798 | |||
799 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
800 | |||
801 | /* FW v9 and higher indicate authentication suites as a TLV in the | ||
802 | * association command, not as a separate authentication command. | ||
803 | */ | ||
804 | if (priv->fwrelease < 0x09000000) { | ||
805 | ret = lbs_set_authentication(priv, assoc_req->bss.bssid, | ||
806 | priv->secinfo.auth_mode); | ||
807 | if (ret) | ||
808 | goto out; | ||
809 | } | ||
810 | |||
811 | /* Use short preamble only when both the BSS and firmware support it */ | ||
812 | if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
813 | preamble = RADIO_PREAMBLE_SHORT; | ||
814 | |||
815 | ret = lbs_set_radio(priv, preamble, 1); | ||
816 | if (ret) | ||
817 | goto out; | ||
818 | |||
819 | ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); | ||
820 | /* If the association fails with current auth mode, let's | ||
821 | * try by changing the auth mode | ||
822 | */ | ||
823 | if ((priv->authtype_auto) && | ||
824 | (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) && | ||
825 | (assoc_req->secinfo.wep_enabled) && | ||
826 | (priv->connect_status != LBS_CONNECTED)) { | ||
827 | if (priv->secinfo.auth_mode == IW_AUTH_ALG_OPEN_SYSTEM) | ||
828 | priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | ||
829 | else | ||
830 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
831 | if (!assoc_helper_wep_keys(priv, assoc_req)) | ||
832 | ret = lbs_associate(priv, assoc_req, | ||
833 | CMD_802_11_ASSOCIATE); | ||
834 | } | ||
835 | |||
836 | if (ret) | ||
837 | ret = -1; | ||
838 | out: | ||
839 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | static int lbs_adhoc_post(struct lbs_private *priv, | ||
844 | struct cmd_ds_802_11_ad_hoc_result *resp) | ||
845 | { | ||
846 | int ret = 0; | ||
847 | u16 command = le16_to_cpu(resp->hdr.command); | ||
848 | u16 result = le16_to_cpu(resp->hdr.result); | ||
849 | union iwreq_data wrqu; | ||
850 | struct bss_descriptor *bss; | ||
851 | DECLARE_SSID_BUF(ssid); | ||
852 | |||
853 | lbs_deb_enter(LBS_DEB_JOIN); | ||
854 | |||
855 | if (!priv->in_progress_assoc_req) { | ||
856 | lbs_deb_join("ADHOC_RESP: no in-progress association " | ||
857 | "request\n"); | ||
858 | ret = -1; | ||
859 | goto done; | ||
860 | } | ||
861 | bss = &priv->in_progress_assoc_req->bss; | ||
862 | |||
863 | /* | ||
864 | * Join result code 0 --> SUCCESS | ||
865 | */ | ||
866 | if (result) { | ||
867 | lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); | ||
868 | if (priv->connect_status == LBS_CONNECTED) | ||
869 | lbs_mac_event_disconnected(priv); | ||
870 | ret = -1; | ||
871 | goto done; | ||
872 | } | ||
873 | |||
874 | /* Send a Media Connected event, according to the Spec */ | ||
875 | priv->connect_status = LBS_CONNECTED; | ||
876 | |||
877 | if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { | ||
878 | /* Update the created network descriptor with the new BSSID */ | ||
879 | memcpy(bss->bssid, resp->bssid, ETH_ALEN); | ||
880 | } | ||
881 | |||
882 | /* Set the BSSID from the joined/started descriptor */ | ||
883 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | ||
884 | |||
885 | /* Set the new SSID to current SSID */ | ||
886 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); | ||
887 | priv->curbssparams.ssid_len = bss->ssid_len; | ||
888 | |||
889 | netif_carrier_on(priv->dev); | ||
890 | if (!priv->tx_pending_len) | ||
891 | netif_wake_queue(priv->dev); | ||
892 | |||
893 | memset(&wrqu, 0, sizeof(wrqu)); | ||
894 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
895 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
896 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
897 | |||
898 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", | ||
899 | print_ssid(ssid, bss->ssid, bss->ssid_len), | ||
900 | priv->curbssparams.bssid, | ||
901 | priv->channel); | ||
902 | |||
903 | done: | ||
904 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * @brief Join an adhoc network found in a previous scan | ||
910 | * | ||
911 | * @param priv A pointer to struct lbs_private structure | ||
912 | * @param assoc_req The association request describing the BSS to join | ||
913 | * | ||
914 | * @return 0 on success, error on failure | ||
915 | */ | ||
916 | static int lbs_adhoc_join(struct lbs_private *priv, | ||
917 | struct assoc_request *assoc_req) | ||
918 | { | ||
919 | struct cmd_ds_802_11_ad_hoc_join cmd; | ||
920 | struct bss_descriptor *bss = &assoc_req->bss; | ||
921 | u8 preamble = RADIO_PREAMBLE_LONG; | ||
922 | DECLARE_SSID_BUF(ssid); | ||
923 | u16 ratesize = 0; | ||
924 | int ret = 0; | ||
925 | |||
926 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
927 | |||
928 | lbs_deb_join("current SSID '%s', ssid length %u\n", | ||
929 | print_ssid(ssid, priv->curbssparams.ssid, | ||
930 | priv->curbssparams.ssid_len), | ||
931 | priv->curbssparams.ssid_len); | ||
932 | lbs_deb_join("requested ssid '%s', ssid length %u\n", | ||
933 | print_ssid(ssid, bss->ssid, bss->ssid_len), | ||
934 | bss->ssid_len); | ||
935 | |||
936 | /* check if the requested SSID is already joined */ | ||
937 | if (priv->curbssparams.ssid_len && | ||
938 | !lbs_ssid_cmp(priv->curbssparams.ssid, | ||
939 | priv->curbssparams.ssid_len, | ||
940 | bss->ssid, bss->ssid_len) && | ||
941 | (priv->mode == IW_MODE_ADHOC) && | ||
942 | (priv->connect_status == LBS_CONNECTED)) { | ||
943 | union iwreq_data wrqu; | ||
944 | |||
945 | lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as " | ||
946 | "current, not attempting to re-join"); | ||
947 | |||
948 | /* Send the re-association event though, because the association | ||
949 | * request really was successful, even if just a null-op. | ||
950 | */ | ||
951 | memset(&wrqu, 0, sizeof(wrqu)); | ||
952 | memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, | ||
953 | ETH_ALEN); | ||
954 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
955 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
956 | goto out; | ||
957 | } | ||
958 | |||
959 | /* Use short preamble only when both the BSS and firmware support it */ | ||
960 | if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { | ||
961 | lbs_deb_join("AdhocJoin: Short preamble\n"); | ||
962 | preamble = RADIO_PREAMBLE_SHORT; | ||
963 | } | ||
964 | |||
965 | ret = lbs_set_radio(priv, preamble, 1); | ||
966 | if (ret) | ||
967 | goto out; | ||
968 | |||
969 | lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); | ||
970 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); | ||
971 | |||
972 | priv->adhoccreate = 0; | ||
973 | priv->channel = bss->channel; | ||
974 | |||
975 | /* Build the join command */ | ||
976 | memset(&cmd, 0, sizeof(cmd)); | ||
977 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
978 | |||
979 | cmd.bss.type = CMD_BSS_TYPE_IBSS; | ||
980 | cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod); | ||
981 | |||
982 | memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); | ||
983 | memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); | ||
984 | |||
985 | memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set)); | ||
986 | |||
987 | memcpy(&cmd.bss.ibss, &bss->ss.ibss, | ||
988 | sizeof(struct ieee_ie_ibss_param_set)); | ||
989 | |||
990 | cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); | ||
991 | lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", | ||
992 | bss->capability, CAPINFO_MASK); | ||
993 | |||
994 | /* information on BSSID descriptor passed to FW */ | ||
995 | lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n", | ||
996 | cmd.bss.bssid, cmd.bss.ssid); | ||
997 | |||
998 | /* Only v8 and below support setting these */ | ||
999 | if (priv->fwrelease < 0x09000000) { | ||
1000 | /* failtimeout */ | ||
1001 | cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); | ||
1002 | /* probedelay */ | ||
1003 | cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
1004 | } | ||
1005 | |||
1006 | /* Copy Data rates from the rates recorded in scan response */ | ||
1007 | memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates)); | ||
1008 | ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates)); | ||
1009 | memcpy(cmd.bss.rates, bss->rates, ratesize); | ||
1010 | if (get_common_rates(priv, cmd.bss.rates, &ratesize)) { | ||
1011 | lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n"); | ||
1012 | ret = -1; | ||
1013 | goto out; | ||
1014 | } | ||
1015 | |||
1016 | /* Copy the ad-hoc creation rates into Current BSS state structure */ | ||
1017 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
1018 | memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize); | ||
1019 | |||
1020 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
1021 | * copying to current bss rates. | ||
1022 | */ | ||
1023 | lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); | ||
1024 | |||
1025 | cmd.bss.ibss.atimwindow = bss->atimwindow; | ||
1026 | |||
1027 | if (assoc_req->secinfo.wep_enabled) { | ||
1028 | u16 tmp = le16_to_cpu(cmd.bss.capability); | ||
1029 | tmp |= WLAN_CAPABILITY_PRIVACY; | ||
1030 | cmd.bss.capability = cpu_to_le16(tmp); | ||
1031 | } | ||
1032 | |||
1033 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | ||
1034 | __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM); | ||
1035 | |||
1036 | /* wake up first */ | ||
1037 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, | ||
1038 | CMD_ACT_SET, 0, 0, | ||
1039 | &local_ps_mode); | ||
1040 | if (ret) { | ||
1041 | ret = -1; | ||
1042 | goto out; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); | ||
1047 | if (ret == 0) { | ||
1048 | ret = lbs_adhoc_post(priv, | ||
1049 | (struct cmd_ds_802_11_ad_hoc_result *)&cmd); | ||
1050 | } | ||
1051 | |||
1052 | out: | ||
1053 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1054 | return ret; | ||
1055 | } | ||
1056 | |||
1057 | /** | ||
1058 | * @brief Start an Adhoc Network | ||
1059 | * | ||
1060 | * @param priv A pointer to struct lbs_private structure | ||
1061 | * @param assoc_req The association request describing the BSS to start | ||
1062 | * | ||
1063 | * @return 0 on success, error on failure | ||
1064 | */ | ||
1065 | static int lbs_adhoc_start(struct lbs_private *priv, | ||
1066 | struct assoc_request *assoc_req) | ||
1067 | { | ||
1068 | struct cmd_ds_802_11_ad_hoc_start cmd; | ||
1069 | u8 preamble = RADIO_PREAMBLE_SHORT; | ||
1070 | size_t ratesize = 0; | ||
1071 | u16 tmpcap = 0; | ||
1072 | int ret = 0; | ||
1073 | DECLARE_SSID_BUF(ssid); | ||
1074 | |||
1075 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1076 | |||
1077 | ret = lbs_set_radio(priv, preamble, 1); | ||
1078 | if (ret) | ||
1079 | goto out; | ||
1080 | |||
1081 | /* Build the start command */ | ||
1082 | memset(&cmd, 0, sizeof(cmd)); | ||
1083 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1084 | |||
1085 | memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len); | ||
1086 | |||
1087 | lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n", | ||
1088 | print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len), | ||
1089 | assoc_req->ssid_len); | ||
1090 | |||
1091 | cmd.bsstype = CMD_BSS_TYPE_IBSS; | ||
1092 | |||
1093 | if (priv->beacon_period == 0) | ||
1094 | priv->beacon_period = MRVDRV_BEACON_INTERVAL; | ||
1095 | cmd.beaconperiod = cpu_to_le16(priv->beacon_period); | ||
1096 | |||
1097 | WARN_ON(!assoc_req->channel); | ||
1098 | |||
1099 | /* set Physical parameter set */ | ||
1100 | cmd.ds.header.id = WLAN_EID_DS_PARAMS; | ||
1101 | cmd.ds.header.len = 1; | ||
1102 | cmd.ds.channel = assoc_req->channel; | ||
1103 | |||
1104 | /* set IBSS parameter set */ | ||
1105 | cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; | ||
1106 | cmd.ibss.header.len = 2; | ||
1107 | cmd.ibss.atimwindow = cpu_to_le16(0); | ||
1108 | |||
1109 | /* set capability info */ | ||
1110 | tmpcap = WLAN_CAPABILITY_IBSS; | ||
1111 | if (assoc_req->secinfo.wep_enabled || | ||
1112 | assoc_req->secinfo.WPAenabled || | ||
1113 | assoc_req->secinfo.WPA2enabled) { | ||
1114 | lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n"); | ||
1115 | tmpcap |= WLAN_CAPABILITY_PRIVACY; | ||
1116 | } else | ||
1117 | lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n"); | ||
1118 | |||
1119 | cmd.capability = cpu_to_le16(tmpcap); | ||
1120 | |||
1121 | /* Only v8 and below support setting probe delay */ | ||
1122 | if (priv->fwrelease < 0x09000000) | ||
1123 | cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
1124 | |||
1125 | ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates)); | ||
1126 | memcpy(cmd.rates, lbs_bg_rates, ratesize); | ||
1127 | |||
1128 | /* Copy the ad-hoc creating rates into Current BSS state structure */ | ||
1129 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
1130 | memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize); | ||
1131 | |||
1132 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
1133 | * copying to current bss rates. | ||
1134 | */ | ||
1135 | lbs_set_basic_rate_flags(cmd.rates, ratesize); | ||
1136 | |||
1137 | lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", | ||
1138 | cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); | ||
1139 | |||
1140 | lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", | ||
1141 | assoc_req->channel, assoc_req->band); | ||
1142 | |||
1143 | priv->adhoccreate = 1; | ||
1144 | priv->mode = IW_MODE_ADHOC; | ||
1145 | |||
1146 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); | ||
1147 | if (ret == 0) | ||
1148 | ret = lbs_adhoc_post(priv, | ||
1149 | (struct cmd_ds_802_11_ad_hoc_result *)&cmd); | ||
1150 | |||
1151 | out: | ||
1152 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1156 | /** | ||
1157 | * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode | ||
1158 | * | ||
1159 | * @param priv A pointer to struct lbs_private structure | ||
1160 | * @return 0 on success, or an error | ||
1161 | */ | ||
1162 | int lbs_adhoc_stop(struct lbs_private *priv) | ||
1163 | { | ||
1164 | struct cmd_ds_802_11_ad_hoc_stop cmd; | ||
1165 | int ret; | ||
1166 | |||
1167 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1168 | |||
1169 | memset(&cmd, 0, sizeof (cmd)); | ||
1170 | cmd.hdr.size = cpu_to_le16 (sizeof (cmd)); | ||
1171 | |||
1172 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd); | ||
1173 | |||
1174 | /* Clean up everything even if there was an error */ | ||
1175 | lbs_mac_event_disconnected(priv); | ||
1176 | |||
1177 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1178 | return ret; | ||
1179 | } | ||
1180 | |||
1181 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | ||
1182 | struct bss_descriptor *match_bss) | ||
1183 | { | ||
1184 | if (!secinfo->wep_enabled && | ||
1185 | !secinfo->WPAenabled && !secinfo->WPA2enabled && | ||
1186 | match_bss->wpa_ie[0] != WLAN_EID_GENERIC && | ||
1187 | match_bss->rsn_ie[0] != WLAN_EID_RSN && | ||
1188 | !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | ||
1189 | return 1; | ||
1190 | else | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | ||
1195 | struct bss_descriptor *match_bss) | ||
1196 | { | ||
1197 | if (secinfo->wep_enabled && | ||
1198 | !secinfo->WPAenabled && !secinfo->WPA2enabled && | ||
1199 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | ||
1200 | return 1; | ||
1201 | else | ||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, | ||
1206 | struct bss_descriptor *match_bss) | ||
1207 | { | ||
1208 | if (!secinfo->wep_enabled && secinfo->WPAenabled && | ||
1209 | (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) | ||
1210 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | ||
1211 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ | ||
1212 | ) | ||
1213 | return 1; | ||
1214 | else | ||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, | ||
1219 | struct bss_descriptor *match_bss) | ||
1220 | { | ||
1221 | if (!secinfo->wep_enabled && secinfo->WPA2enabled && | ||
1222 | (match_bss->rsn_ie[0] == WLAN_EID_RSN) | ||
1223 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | ||
1224 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ | ||
1225 | ) | ||
1226 | return 1; | ||
1227 | else | ||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | ||
1232 | struct bss_descriptor *match_bss) | ||
1233 | { | ||
1234 | if (!secinfo->wep_enabled && | ||
1235 | !secinfo->WPAenabled && !secinfo->WPA2enabled && | ||
1236 | (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) && | ||
1237 | (match_bss->rsn_ie[0] != WLAN_EID_RSN) && | ||
1238 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | ||
1239 | return 1; | ||
1240 | else | ||
1241 | return 0; | ||
1242 | } | ||
1243 | |||
1244 | /** | ||
1245 | * @brief Check if a scanned network compatible with the driver settings | ||
1246 | * | ||
1247 | * WEP WPA WPA2 ad-hoc encrypt Network | ||
1248 | * enabled enabled enabled AES mode privacy WPA WPA2 Compatible | ||
1249 | * 0 0 0 0 NONE 0 0 0 yes No security | ||
1250 | * 1 0 0 0 NONE 1 0 0 yes Static WEP | ||
1251 | * 0 1 0 0 x 1x 1 x yes WPA | ||
1252 | * 0 0 1 0 x 1x x 1 yes WPA2 | ||
1253 | * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES | ||
1254 | * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP | ||
1255 | * | ||
1256 | * | ||
1257 | * @param priv A pointer to struct lbs_private | ||
1258 | * @param index Index in scantable to check against current driver settings | ||
1259 | * @param mode Network mode: Infrastructure or IBSS | ||
1260 | * | ||
1261 | * @return Index in scantable, or error code if negative | ||
1262 | */ | ||
1263 | static int is_network_compatible(struct lbs_private *priv, | ||
1264 | struct bss_descriptor *bss, uint8_t mode) | ||
1265 | { | ||
1266 | int matched = 0; | ||
1267 | |||
1268 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1269 | |||
1270 | if (bss->mode != mode) | ||
1271 | goto done; | ||
1272 | |||
1273 | matched = match_bss_no_security(&priv->secinfo, bss); | ||
1274 | if (matched) | ||
1275 | goto done; | ||
1276 | matched = match_bss_static_wep(&priv->secinfo, bss); | ||
1277 | if (matched) | ||
1278 | goto done; | ||
1279 | matched = match_bss_wpa(&priv->secinfo, bss); | ||
1280 | if (matched) { | ||
1281 | lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " | ||
1282 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | ||
1283 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | ||
1284 | priv->secinfo.wep_enabled ? "e" : "d", | ||
1285 | priv->secinfo.WPAenabled ? "e" : "d", | ||
1286 | priv->secinfo.WPA2enabled ? "e" : "d", | ||
1287 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
1288 | goto done; | ||
1289 | } | ||
1290 | matched = match_bss_wpa2(&priv->secinfo, bss); | ||
1291 | if (matched) { | ||
1292 | lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " | ||
1293 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | ||
1294 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | ||
1295 | priv->secinfo.wep_enabled ? "e" : "d", | ||
1296 | priv->secinfo.WPAenabled ? "e" : "d", | ||
1297 | priv->secinfo.WPA2enabled ? "e" : "d", | ||
1298 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
1299 | goto done; | ||
1300 | } | ||
1301 | matched = match_bss_dynamic_wep(&priv->secinfo, bss); | ||
1302 | if (matched) { | ||
1303 | lbs_deb_scan("is_network_compatible() dynamic WEP: " | ||
1304 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", | ||
1305 | bss->wpa_ie[0], bss->rsn_ie[0], | ||
1306 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
1307 | goto done; | ||
1308 | } | ||
1309 | |||
1310 | /* bss security settings don't match those configured on card */ | ||
1311 | lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " | ||
1312 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", | ||
1313 | bss->wpa_ie[0], bss->rsn_ie[0], | ||
1314 | priv->secinfo.wep_enabled ? "e" : "d", | ||
1315 | priv->secinfo.WPAenabled ? "e" : "d", | ||
1316 | priv->secinfo.WPA2enabled ? "e" : "d", | ||
1317 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
1318 | |||
1319 | done: | ||
1320 | lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); | ||
1321 | return matched; | ||
1322 | } | ||
1323 | |||
1324 | /** | ||
1325 | * @brief This function finds a specific compatible BSSID in the scan list | ||
1326 | * | ||
1327 | * Used in association code | ||
1328 | * | ||
1329 | * @param priv A pointer to struct lbs_private | ||
1330 | * @param bssid BSSID to find in the scan list | ||
1331 | * @param mode Network mode: Infrastructure or IBSS | ||
1332 | * | ||
1333 | * @return index in BSSID list, or error return code (< 0) | ||
1334 | */ | ||
1335 | static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, | ||
1336 | uint8_t *bssid, uint8_t mode) | ||
1337 | { | ||
1338 | struct bss_descriptor *iter_bss; | ||
1339 | struct bss_descriptor *found_bss = NULL; | ||
1340 | |||
1341 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1342 | |||
1343 | if (!bssid) | ||
1344 | goto out; | ||
1345 | |||
1346 | lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); | ||
1347 | |||
1348 | /* Look through the scan table for a compatible match. The loop will | ||
1349 | * continue past a matched bssid that is not compatible in case there | ||
1350 | * is an AP with multiple SSIDs assigned to the same BSSID | ||
1351 | */ | ||
1352 | mutex_lock(&priv->lock); | ||
1353 | list_for_each_entry(iter_bss, &priv->network_list, list) { | ||
1354 | if (compare_ether_addr(iter_bss->bssid, bssid)) | ||
1355 | continue; /* bssid doesn't match */ | ||
1356 | switch (mode) { | ||
1357 | case IW_MODE_INFRA: | ||
1358 | case IW_MODE_ADHOC: | ||
1359 | if (!is_network_compatible(priv, iter_bss, mode)) | ||
1360 | break; | ||
1361 | found_bss = iter_bss; | ||
1362 | break; | ||
1363 | default: | ||
1364 | found_bss = iter_bss; | ||
1365 | break; | ||
1366 | } | ||
1367 | } | ||
1368 | mutex_unlock(&priv->lock); | ||
1369 | |||
1370 | out: | ||
1371 | lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); | ||
1372 | return found_bss; | ||
1373 | } | ||
1374 | |||
1375 | /** | ||
1376 | * @brief This function finds ssid in ssid list. | ||
1377 | * | ||
1378 | * Used in association code | ||
1379 | * | ||
1380 | * @param priv A pointer to struct lbs_private | ||
1381 | * @param ssid SSID to find in the list | ||
1382 | * @param bssid BSSID to qualify the SSID selection (if provided) | ||
1383 | * @param mode Network mode: Infrastructure or IBSS | ||
1384 | * | ||
1385 | * @return index in BSSID list | ||
1386 | */ | ||
1387 | static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, | ||
1388 | uint8_t *ssid, uint8_t ssid_len, | ||
1389 | uint8_t *bssid, uint8_t mode, | ||
1390 | int channel) | ||
1391 | { | ||
1392 | u32 bestrssi = 0; | ||
1393 | struct bss_descriptor *iter_bss = NULL; | ||
1394 | struct bss_descriptor *found_bss = NULL; | ||
1395 | struct bss_descriptor *tmp_oldest = NULL; | ||
1396 | |||
1397 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1398 | |||
1399 | mutex_lock(&priv->lock); | ||
1400 | |||
1401 | list_for_each_entry(iter_bss, &priv->network_list, list) { | ||
1402 | if (!tmp_oldest || | ||
1403 | (iter_bss->last_scanned < tmp_oldest->last_scanned)) | ||
1404 | tmp_oldest = iter_bss; | ||
1405 | |||
1406 | if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, | ||
1407 | ssid, ssid_len) != 0) | ||
1408 | continue; /* ssid doesn't match */ | ||
1409 | if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) | ||
1410 | continue; /* bssid doesn't match */ | ||
1411 | if ((channel > 0) && (iter_bss->channel != channel)) | ||
1412 | continue; /* channel doesn't match */ | ||
1413 | |||
1414 | switch (mode) { | ||
1415 | case IW_MODE_INFRA: | ||
1416 | case IW_MODE_ADHOC: | ||
1417 | if (!is_network_compatible(priv, iter_bss, mode)) | ||
1418 | break; | ||
1419 | |||
1420 | if (bssid) { | ||
1421 | /* Found requested BSSID */ | ||
1422 | found_bss = iter_bss; | ||
1423 | goto out; | ||
1424 | } | ||
1425 | |||
1426 | if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { | ||
1427 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1428 | found_bss = iter_bss; | ||
1429 | } | ||
1430 | break; | ||
1431 | case IW_MODE_AUTO: | ||
1432 | default: | ||
1433 | if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { | ||
1434 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1435 | found_bss = iter_bss; | ||
1436 | } | ||
1437 | break; | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | out: | ||
1442 | mutex_unlock(&priv->lock); | ||
1443 | lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); | ||
1444 | return found_bss; | ||
1445 | } | ||
1446 | |||
1447 | static int assoc_helper_essid(struct lbs_private *priv, | ||
1448 | struct assoc_request * assoc_req) | ||
1449 | { | ||
1450 | int ret = 0; | ||
1451 | struct bss_descriptor * bss; | ||
1452 | int channel = -1; | ||
1453 | DECLARE_SSID_BUF(ssid); | ||
1454 | |||
1455 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1456 | |||
1457 | /* FIXME: take channel into account when picking SSIDs if a channel | ||
1458 | * is set. | ||
1459 | */ | ||
1460 | |||
1461 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) | ||
1462 | channel = assoc_req->channel; | ||
1463 | |||
1464 | lbs_deb_assoc("SSID '%s' requested\n", | ||
1465 | print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len)); | ||
1466 | if (assoc_req->mode == IW_MODE_INFRA) { | ||
1467 | lbs_send_specific_ssid_scan(priv, assoc_req->ssid, | ||
1468 | assoc_req->ssid_len); | ||
1469 | |||
1470 | bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, | ||
1471 | assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); | ||
1472 | if (bss != NULL) { | ||
1473 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); | ||
1474 | ret = lbs_try_associate(priv, assoc_req); | ||
1475 | } else { | ||
1476 | lbs_deb_assoc("SSID not found; cannot associate\n"); | ||
1477 | } | ||
1478 | } else if (assoc_req->mode == IW_MODE_ADHOC) { | ||
1479 | /* Scan for the network, do not save previous results. Stale | ||
1480 | * scan data will cause us to join a non-existant adhoc network | ||
1481 | */ | ||
1482 | lbs_send_specific_ssid_scan(priv, assoc_req->ssid, | ||
1483 | assoc_req->ssid_len); | ||
1484 | |||
1485 | /* Search for the requested SSID in the scan table */ | ||
1486 | bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, | ||
1487 | assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel); | ||
1488 | if (bss != NULL) { | ||
1489 | lbs_deb_assoc("SSID found, will join\n"); | ||
1490 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); | ||
1491 | lbs_adhoc_join(priv, assoc_req); | ||
1492 | } else { | ||
1493 | /* else send START command */ | ||
1494 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); | ||
1495 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, | ||
1496 | IEEE80211_MAX_SSID_LEN); | ||
1497 | assoc_req->bss.ssid_len = assoc_req->ssid_len; | ||
1498 | lbs_adhoc_start(priv, assoc_req); | ||
1499 | } | ||
1500 | } | ||
1501 | |||
1502 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1503 | return ret; | ||
1504 | } | ||
1505 | |||
1506 | |||
1507 | static int assoc_helper_bssid(struct lbs_private *priv, | ||
1508 | struct assoc_request * assoc_req) | ||
1509 | { | ||
1510 | int ret = 0; | ||
1511 | struct bss_descriptor * bss; | ||
1512 | |||
1513 | lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid); | ||
1514 | |||
1515 | /* Search for index position in list for requested MAC */ | ||
1516 | bss = lbs_find_bssid_in_list(priv, assoc_req->bssid, | ||
1517 | assoc_req->mode); | ||
1518 | if (bss == NULL) { | ||
1519 | lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, " | ||
1520 | "cannot associate.\n", assoc_req->bssid); | ||
1521 | goto out; | ||
1522 | } | ||
1523 | |||
1524 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); | ||
1525 | if (assoc_req->mode == IW_MODE_INFRA) { | ||
1526 | ret = lbs_try_associate(priv, assoc_req); | ||
1527 | lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n", | ||
1528 | ret); | ||
1529 | } else if (assoc_req->mode == IW_MODE_ADHOC) { | ||
1530 | lbs_adhoc_join(priv, assoc_req); | ||
1531 | } | ||
1532 | |||
1533 | out: | ||
1534 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1535 | return ret; | ||
1536 | } | ||
1537 | |||
1538 | |||
1539 | static int assoc_helper_associate(struct lbs_private *priv, | ||
1540 | struct assoc_request * assoc_req) | ||
1541 | { | ||
1542 | int ret = 0, done = 0; | ||
1543 | |||
1544 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1545 | |||
1546 | /* If we're given and 'any' BSSID, try associating based on SSID */ | ||
1547 | |||
1548 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | ||
1549 | if (compare_ether_addr(bssid_any, assoc_req->bssid) && | ||
1550 | compare_ether_addr(bssid_off, assoc_req->bssid)) { | ||
1551 | ret = assoc_helper_bssid(priv, assoc_req); | ||
1552 | done = 1; | ||
1553 | } | ||
1554 | } | ||
1555 | |||
1556 | if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | ||
1557 | ret = assoc_helper_essid(priv, assoc_req); | ||
1558 | } | ||
1559 | |||
1560 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1561 | return ret; | ||
1562 | } | ||
1563 | |||
1564 | |||
1565 | static int assoc_helper_mode(struct lbs_private *priv, | ||
1566 | struct assoc_request * assoc_req) | ||
1567 | { | ||
1568 | int ret = 0; | ||
1569 | |||
1570 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1571 | |||
1572 | if (assoc_req->mode == priv->mode) | ||
1573 | goto done; | ||
1574 | |||
1575 | if (assoc_req->mode == IW_MODE_INFRA) { | ||
1576 | if (priv->psstate != PS_STATE_FULL_POWER) | ||
1577 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | ||
1578 | priv->psmode = LBS802_11POWERMODECAM; | ||
1579 | } | ||
1580 | |||
1581 | priv->mode = assoc_req->mode; | ||
1582 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, | ||
1583 | assoc_req->mode == IW_MODE_ADHOC ? 2 : 1); | ||
1584 | |||
1585 | done: | ||
1586 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1587 | return ret; | ||
1588 | } | ||
1589 | |||
1590 | static int assoc_helper_channel(struct lbs_private *priv, | ||
1591 | struct assoc_request * assoc_req) | ||
1592 | { | ||
1593 | int ret = 0; | ||
1594 | |||
1595 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1596 | |||
1597 | ret = lbs_update_channel(priv); | ||
1598 | if (ret) { | ||
1599 | lbs_deb_assoc("ASSOC: channel: error getting channel.\n"); | ||
1600 | goto done; | ||
1601 | } | ||
1602 | |||
1603 | if (assoc_req->channel == priv->channel) | ||
1604 | goto done; | ||
1605 | |||
1606 | if (priv->mesh_dev) { | ||
1607 | /* Change mesh channel first; 21.p21 firmware won't let | ||
1608 | you change channel otherwise (even though it'll return | ||
1609 | an error to this */ | ||
1610 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, | ||
1611 | assoc_req->channel); | ||
1612 | } | ||
1613 | |||
1614 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", | ||
1615 | priv->channel, assoc_req->channel); | ||
1616 | |||
1617 | ret = lbs_set_channel(priv, assoc_req->channel); | ||
1618 | if (ret < 0) | ||
1619 | lbs_deb_assoc("ASSOC: channel: error setting channel.\n"); | ||
1620 | |||
1621 | /* FIXME: shouldn't need to grab the channel _again_ after setting | ||
1622 | * it since the firmware is supposed to return the new channel, but | ||
1623 | * whatever... */ | ||
1624 | ret = lbs_update_channel(priv); | ||
1625 | if (ret) { | ||
1626 | lbs_deb_assoc("ASSOC: channel: error getting channel.\n"); | ||
1627 | goto done; | ||
1628 | } | ||
1629 | |||
1630 | if (assoc_req->channel != priv->channel) { | ||
1631 | lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", | ||
1632 | assoc_req->channel); | ||
1633 | goto restore_mesh; | ||
1634 | } | ||
1635 | |||
1636 | if (assoc_req->secinfo.wep_enabled && | ||
1637 | (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || | ||
1638 | assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) { | ||
1639 | /* Make sure WEP keys are re-sent to firmware */ | ||
1640 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); | ||
1641 | } | ||
1642 | |||
1643 | /* Must restart/rejoin adhoc networks after channel change */ | ||
1644 | set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); | ||
1645 | |||
1646 | restore_mesh: | ||
1647 | if (priv->mesh_dev) | ||
1648 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
1649 | priv->channel); | ||
1650 | |||
1651 | done: | ||
1652 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1653 | return ret; | ||
1654 | } | ||
1655 | |||
1656 | |||
1657 | static int assoc_helper_wep_keys(struct lbs_private *priv, | ||
1658 | struct assoc_request *assoc_req) | ||
1659 | { | ||
1660 | int i; | ||
1661 | int ret = 0; | ||
1662 | |||
1663 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1664 | |||
1665 | /* Set or remove WEP keys */ | ||
1666 | if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || | ||
1667 | assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len) | ||
1668 | ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req); | ||
1669 | else | ||
1670 | ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req); | ||
1671 | |||
1672 | if (ret) | ||
1673 | goto out; | ||
1674 | |||
1675 | /* enable/disable the MAC's WEP packet filter */ | ||
1676 | if (assoc_req->secinfo.wep_enabled) | ||
1677 | priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE; | ||
1678 | else | ||
1679 | priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; | ||
1680 | |||
1681 | lbs_set_mac_control(priv); | ||
1682 | |||
1683 | mutex_lock(&priv->lock); | ||
1684 | |||
1685 | /* Copy WEP keys into priv wep key fields */ | ||
1686 | for (i = 0; i < 4; i++) { | ||
1687 | memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i], | ||
1688 | sizeof(struct enc_key)); | ||
1689 | } | ||
1690 | priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx; | ||
1691 | |||
1692 | mutex_unlock(&priv->lock); | ||
1693 | |||
1694 | out: | ||
1695 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1696 | return ret; | ||
1697 | } | ||
1698 | |||
1699 | static int assoc_helper_secinfo(struct lbs_private *priv, | ||
1700 | struct assoc_request * assoc_req) | ||
1701 | { | ||
1702 | int ret = 0; | ||
1703 | uint16_t do_wpa; | ||
1704 | uint16_t rsn = 0; | ||
1705 | |||
1706 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1707 | |||
1708 | memcpy(&priv->secinfo, &assoc_req->secinfo, | ||
1709 | sizeof(struct lbs_802_11_security)); | ||
1710 | |||
1711 | lbs_set_mac_control(priv); | ||
1712 | |||
1713 | /* If RSN is already enabled, don't try to enable it again, since | ||
1714 | * ENABLE_RSN resets internal state machines and will clobber the | ||
1715 | * 4-way WPA handshake. | ||
1716 | */ | ||
1717 | |||
1718 | /* Get RSN enabled/disabled */ | ||
1719 | ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn); | ||
1720 | if (ret) { | ||
1721 | lbs_deb_assoc("Failed to get RSN status: %d\n", ret); | ||
1722 | goto out; | ||
1723 | } | ||
1724 | |||
1725 | /* Don't re-enable RSN if it's already enabled */ | ||
1726 | do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled; | ||
1727 | if (do_wpa == rsn) | ||
1728 | goto out; | ||
1729 | |||
1730 | /* Set RSN enabled/disabled */ | ||
1731 | ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa); | ||
1732 | |||
1733 | out: | ||
1734 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1735 | return ret; | ||
1736 | } | ||
1737 | |||
1738 | |||
1739 | static int assoc_helper_wpa_keys(struct lbs_private *priv, | ||
1740 | struct assoc_request * assoc_req) | ||
1741 | { | ||
1742 | int ret = 0; | ||
1743 | unsigned int flags = assoc_req->flags; | ||
1744 | |||
1745 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1746 | |||
1747 | /* Work around older firmware bug where WPA unicast and multicast | ||
1748 | * keys must be set independently. Seen in SDIO parts with firmware | ||
1749 | * version 5.0.11p0. | ||
1750 | */ | ||
1751 | |||
1752 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | ||
1753 | clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); | ||
1754 | ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); | ||
1755 | assoc_req->flags = flags; | ||
1756 | } | ||
1757 | |||
1758 | if (ret) | ||
1759 | goto out; | ||
1760 | |||
1761 | memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key, | ||
1762 | sizeof(struct enc_key)); | ||
1763 | |||
1764 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { | ||
1765 | clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); | ||
1766 | |||
1767 | ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); | ||
1768 | assoc_req->flags = flags; | ||
1769 | |||
1770 | memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key, | ||
1771 | sizeof(struct enc_key)); | ||
1772 | } | ||
1773 | |||
1774 | out: | ||
1775 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1776 | return ret; | ||
1777 | } | ||
1778 | |||
1779 | |||
1780 | static int assoc_helper_wpa_ie(struct lbs_private *priv, | ||
1781 | struct assoc_request * assoc_req) | ||
1782 | { | ||
1783 | int ret = 0; | ||
1784 | |||
1785 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1786 | |||
1787 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { | ||
1788 | memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len); | ||
1789 | priv->wpa_ie_len = assoc_req->wpa_ie_len; | ||
1790 | } else { | ||
1791 | memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN); | ||
1792 | priv->wpa_ie_len = 0; | ||
1793 | } | ||
1794 | |||
1795 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1796 | return ret; | ||
1797 | } | ||
1798 | |||
1799 | |||
1800 | static int should_deauth_infrastructure(struct lbs_private *priv, | ||
1801 | struct assoc_request * assoc_req) | ||
1802 | { | ||
1803 | int ret = 0; | ||
1804 | |||
1805 | if (priv->connect_status != LBS_CONNECTED) | ||
1806 | return 0; | ||
1807 | |||
1808 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1809 | if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | ||
1810 | lbs_deb_assoc("Deauthenticating due to new SSID\n"); | ||
1811 | ret = 1; | ||
1812 | goto out; | ||
1813 | } | ||
1814 | |||
1815 | if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { | ||
1816 | if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) { | ||
1817 | lbs_deb_assoc("Deauthenticating due to new security\n"); | ||
1818 | ret = 1; | ||
1819 | goto out; | ||
1820 | } | ||
1821 | } | ||
1822 | |||
1823 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | ||
1824 | lbs_deb_assoc("Deauthenticating due to new BSSID\n"); | ||
1825 | ret = 1; | ||
1826 | goto out; | ||
1827 | } | ||
1828 | |||
1829 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { | ||
1830 | lbs_deb_assoc("Deauthenticating due to channel switch\n"); | ||
1831 | ret = 1; | ||
1832 | goto out; | ||
1833 | } | ||
1834 | |||
1835 | /* FIXME: deal with 'auto' mode somehow */ | ||
1836 | if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { | ||
1837 | if (assoc_req->mode != IW_MODE_INFRA) { | ||
1838 | lbs_deb_assoc("Deauthenticating due to leaving " | ||
1839 | "infra mode\n"); | ||
1840 | ret = 1; | ||
1841 | goto out; | ||
1842 | } | ||
1843 | } | ||
1844 | |||
1845 | out: | ||
1846 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
1847 | return ret; | ||
1848 | } | ||
1849 | |||
1850 | |||
1851 | static int should_stop_adhoc(struct lbs_private *priv, | ||
1852 | struct assoc_request * assoc_req) | ||
1853 | { | ||
1854 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1855 | |||
1856 | if (priv->connect_status != LBS_CONNECTED) | ||
1857 | return 0; | ||
1858 | |||
1859 | if (lbs_ssid_cmp(priv->curbssparams.ssid, | ||
1860 | priv->curbssparams.ssid_len, | ||
1861 | assoc_req->ssid, assoc_req->ssid_len) != 0) | ||
1862 | return 1; | ||
1863 | |||
1864 | /* FIXME: deal with 'auto' mode somehow */ | ||
1865 | if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { | ||
1866 | if (assoc_req->mode != IW_MODE_ADHOC) | ||
1867 | return 1; | ||
1868 | } | ||
1869 | |||
1870 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { | ||
1871 | if (assoc_req->channel != priv->channel) | ||
1872 | return 1; | ||
1873 | } | ||
1874 | |||
1875 | lbs_deb_leave(LBS_DEB_ASSOC); | ||
1876 | return 0; | ||
1877 | } | ||
1878 | |||
1879 | |||
1880 | /** | ||
1881 | * @brief This function finds the best SSID in the Scan List | ||
1882 | * | ||
1883 | * Search the scan table for the best SSID that also matches the current | ||
1884 | * adapter network preference (infrastructure or adhoc) | ||
1885 | * | ||
1886 | * @param priv A pointer to struct lbs_private | ||
1887 | * | ||
1888 | * @return index in BSSID list | ||
1889 | */ | ||
1890 | static struct bss_descriptor *lbs_find_best_ssid_in_list( | ||
1891 | struct lbs_private *priv, uint8_t mode) | ||
1892 | { | ||
1893 | uint8_t bestrssi = 0; | ||
1894 | struct bss_descriptor *iter_bss; | ||
1895 | struct bss_descriptor *best_bss = NULL; | ||
1896 | |||
1897 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1898 | |||
1899 | mutex_lock(&priv->lock); | ||
1900 | |||
1901 | list_for_each_entry(iter_bss, &priv->network_list, list) { | ||
1902 | switch (mode) { | ||
1903 | case IW_MODE_INFRA: | ||
1904 | case IW_MODE_ADHOC: | ||
1905 | if (!is_network_compatible(priv, iter_bss, mode)) | ||
1906 | break; | ||
1907 | if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) | ||
1908 | break; | ||
1909 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1910 | best_bss = iter_bss; | ||
1911 | break; | ||
1912 | case IW_MODE_AUTO: | ||
1913 | default: | ||
1914 | if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) | ||
1915 | break; | ||
1916 | bestrssi = SCAN_RSSI(iter_bss->rssi); | ||
1917 | best_bss = iter_bss; | ||
1918 | break; | ||
1919 | } | ||
1920 | } | ||
1921 | |||
1922 | mutex_unlock(&priv->lock); | ||
1923 | lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss); | ||
1924 | return best_bss; | ||
1925 | } | ||
1926 | |||
1927 | /** | ||
1928 | * @brief Find the best AP | ||
1929 | * | ||
1930 | * Used from association worker. | ||
1931 | * | ||
1932 | * @param priv A pointer to struct lbs_private structure | ||
1933 | * @param pSSID A pointer to AP's ssid | ||
1934 | * | ||
1935 | * @return 0--success, otherwise--fail | ||
1936 | */ | ||
1937 | static int lbs_find_best_network_ssid(struct lbs_private *priv, | ||
1938 | uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode, | ||
1939 | uint8_t *out_mode) | ||
1940 | { | ||
1941 | int ret = -1; | ||
1942 | struct bss_descriptor *found; | ||
1943 | |||
1944 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1945 | |||
1946 | priv->scan_ssid_len = 0; | ||
1947 | lbs_scan_networks(priv, 1); | ||
1948 | if (priv->surpriseremoved) | ||
1949 | goto out; | ||
1950 | |||
1951 | found = lbs_find_best_ssid_in_list(priv, preferred_mode); | ||
1952 | if (found && (found->ssid_len > 0)) { | ||
1953 | memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN); | ||
1954 | *out_ssid_len = found->ssid_len; | ||
1955 | *out_mode = found->mode; | ||
1956 | ret = 0; | ||
1957 | } | ||
1958 | |||
1959 | out: | ||
1960 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
1961 | return ret; | ||
1962 | } | ||
1963 | |||
1964 | |||
1965 | void lbs_association_worker(struct work_struct *work) | ||
1966 | { | ||
1967 | struct lbs_private *priv = container_of(work, struct lbs_private, | ||
1968 | assoc_work.work); | ||
1969 | struct assoc_request * assoc_req = NULL; | ||
1970 | int ret = 0; | ||
1971 | int find_any_ssid = 0; | ||
1972 | DECLARE_SSID_BUF(ssid); | ||
1973 | |||
1974 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
1975 | |||
1976 | mutex_lock(&priv->lock); | ||
1977 | assoc_req = priv->pending_assoc_req; | ||
1978 | priv->pending_assoc_req = NULL; | ||
1979 | priv->in_progress_assoc_req = assoc_req; | ||
1980 | mutex_unlock(&priv->lock); | ||
1981 | |||
1982 | if (!assoc_req) | ||
1983 | goto done; | ||
1984 | |||
1985 | lbs_deb_assoc( | ||
1986 | "Association Request:\n" | ||
1987 | " flags: 0x%08lx\n" | ||
1988 | " SSID: '%s'\n" | ||
1989 | " chann: %d\n" | ||
1990 | " band: %d\n" | ||
1991 | " mode: %d\n" | ||
1992 | " BSSID: %pM\n" | ||
1993 | " secinfo: %s%s%s\n" | ||
1994 | " auth_mode: %d\n", | ||
1995 | assoc_req->flags, | ||
1996 | print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len), | ||
1997 | assoc_req->channel, assoc_req->band, assoc_req->mode, | ||
1998 | assoc_req->bssid, | ||
1999 | assoc_req->secinfo.WPAenabled ? " WPA" : "", | ||
2000 | assoc_req->secinfo.WPA2enabled ? " WPA2" : "", | ||
2001 | assoc_req->secinfo.wep_enabled ? " WEP" : "", | ||
2002 | assoc_req->secinfo.auth_mode); | ||
2003 | |||
2004 | /* If 'any' SSID was specified, find an SSID to associate with */ | ||
2005 | if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) && | ||
2006 | !assoc_req->ssid_len) | ||
2007 | find_any_ssid = 1; | ||
2008 | |||
2009 | /* But don't use 'any' SSID if there's a valid locked BSSID to use */ | ||
2010 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | ||
2011 | if (compare_ether_addr(assoc_req->bssid, bssid_any) && | ||
2012 | compare_ether_addr(assoc_req->bssid, bssid_off)) | ||
2013 | find_any_ssid = 0; | ||
2014 | } | ||
2015 | |||
2016 | if (find_any_ssid) { | ||
2017 | u8 new_mode = assoc_req->mode; | ||
2018 | |||
2019 | ret = lbs_find_best_network_ssid(priv, assoc_req->ssid, | ||
2020 | &assoc_req->ssid_len, assoc_req->mode, &new_mode); | ||
2021 | if (ret) { | ||
2022 | lbs_deb_assoc("Could not find best network\n"); | ||
2023 | ret = -ENETUNREACH; | ||
2024 | goto out; | ||
2025 | } | ||
2026 | |||
2027 | /* Ensure we switch to the mode of the AP */ | ||
2028 | if (assoc_req->mode == IW_MODE_AUTO) { | ||
2029 | set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); | ||
2030 | assoc_req->mode = new_mode; | ||
2031 | } | ||
2032 | } | ||
2033 | |||
2034 | /* | ||
2035 | * Check if the attributes being changing require deauthentication | ||
2036 | * from the currently associated infrastructure access point. | ||
2037 | */ | ||
2038 | if (priv->mode == IW_MODE_INFRA) { | ||
2039 | if (should_deauth_infrastructure(priv, assoc_req)) { | ||
2040 | ret = lbs_cmd_80211_deauthenticate(priv, | ||
2041 | priv->curbssparams.bssid, | ||
2042 | WLAN_REASON_DEAUTH_LEAVING); | ||
2043 | if (ret) { | ||
2044 | lbs_deb_assoc("Deauthentication due to new " | ||
2045 | "configuration request failed: %d\n", | ||
2046 | ret); | ||
2047 | } | ||
2048 | } | ||
2049 | } else if (priv->mode == IW_MODE_ADHOC) { | ||
2050 | if (should_stop_adhoc(priv, assoc_req)) { | ||
2051 | ret = lbs_adhoc_stop(priv); | ||
2052 | if (ret) { | ||
2053 | lbs_deb_assoc("Teardown of AdHoc network due to " | ||
2054 | "new configuration request failed: %d\n", | ||
2055 | ret); | ||
2056 | } | ||
2057 | |||
2058 | } | ||
2059 | } | ||
2060 | |||
2061 | /* Send the various configuration bits to the firmware */ | ||
2062 | if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { | ||
2063 | ret = assoc_helper_mode(priv, assoc_req); | ||
2064 | if (ret) | ||
2065 | goto out; | ||
2066 | } | ||
2067 | |||
2068 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { | ||
2069 | ret = assoc_helper_channel(priv, assoc_req); | ||
2070 | if (ret) | ||
2071 | goto out; | ||
2072 | } | ||
2073 | |||
2074 | if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { | ||
2075 | ret = assoc_helper_secinfo(priv, assoc_req); | ||
2076 | if (ret) | ||
2077 | goto out; | ||
2078 | } | ||
2079 | |||
2080 | if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { | ||
2081 | ret = assoc_helper_wpa_ie(priv, assoc_req); | ||
2082 | if (ret) | ||
2083 | goto out; | ||
2084 | } | ||
2085 | |||
2086 | /* | ||
2087 | * v10 FW wants WPA keys to be set/cleared before WEP key operations, | ||
2088 | * otherwise it will fail to correctly associate to WEP networks. | ||
2089 | * Other firmware versions don't appear to care. | ||
2090 | */ | ||
2091 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) || | ||
2092 | test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | ||
2093 | ret = assoc_helper_wpa_keys(priv, assoc_req); | ||
2094 | if (ret) | ||
2095 | goto out; | ||
2096 | } | ||
2097 | |||
2098 | if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) || | ||
2099 | test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { | ||
2100 | ret = assoc_helper_wep_keys(priv, assoc_req); | ||
2101 | if (ret) | ||
2102 | goto out; | ||
2103 | } | ||
2104 | |||
2105 | |||
2106 | /* SSID/BSSID should be the _last_ config option set, because they | ||
2107 | * trigger the association attempt. | ||
2108 | */ | ||
2109 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) || | ||
2110 | test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | ||
2111 | int success = 1; | ||
2112 | |||
2113 | ret = assoc_helper_associate(priv, assoc_req); | ||
2114 | if (ret) { | ||
2115 | lbs_deb_assoc("ASSOC: association unsuccessful: %d\n", | ||
2116 | ret); | ||
2117 | success = 0; | ||
2118 | } | ||
2119 | |||
2120 | if (priv->connect_status != LBS_CONNECTED) { | ||
2121 | lbs_deb_assoc("ASSOC: association unsuccessful, " | ||
2122 | "not connected\n"); | ||
2123 | success = 0; | ||
2124 | } | ||
2125 | |||
2126 | if (success) { | ||
2127 | lbs_deb_assoc("associated to %pM\n", | ||
2128 | priv->curbssparams.bssid); | ||
2129 | lbs_prepare_and_send_command(priv, | ||
2130 | CMD_802_11_RSSI, | ||
2131 | 0, CMD_OPTION_WAITFORRSP, 0, NULL); | ||
2132 | } else { | ||
2133 | ret = -1; | ||
2134 | } | ||
2135 | } | ||
2136 | |||
2137 | out: | ||
2138 | if (ret) { | ||
2139 | lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n", | ||
2140 | ret); | ||
2141 | } | ||
2142 | |||
2143 | mutex_lock(&priv->lock); | ||
2144 | priv->in_progress_assoc_req = NULL; | ||
2145 | mutex_unlock(&priv->lock); | ||
2146 | kfree(assoc_req); | ||
2147 | |||
2148 | done: | ||
2149 | lbs_deb_leave(LBS_DEB_ASSOC); | ||
2150 | } | ||
2151 | |||
2152 | |||
2153 | /* | ||
2154 | * Caller MUST hold any necessary locks | ||
2155 | */ | ||
2156 | struct assoc_request *lbs_get_association_request(struct lbs_private *priv) | ||
2157 | { | ||
2158 | struct assoc_request * assoc_req; | ||
2159 | |||
2160 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
2161 | if (!priv->pending_assoc_req) { | ||
2162 | priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request), | ||
2163 | GFP_KERNEL); | ||
2164 | if (!priv->pending_assoc_req) { | ||
2165 | lbs_pr_info("Not enough memory to allocate association" | ||
2166 | " request!\n"); | ||
2167 | return NULL; | ||
2168 | } | ||
2169 | } | ||
2170 | |||
2171 | /* Copy current configuration attributes to the association request, | ||
2172 | * but don't overwrite any that are already set. | ||
2173 | */ | ||
2174 | assoc_req = priv->pending_assoc_req; | ||
2175 | if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | ||
2176 | memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, | ||
2177 | IEEE80211_MAX_SSID_LEN); | ||
2178 | assoc_req->ssid_len = priv->curbssparams.ssid_len; | ||
2179 | } | ||
2180 | |||
2181 | if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) | ||
2182 | assoc_req->channel = priv->channel; | ||
2183 | |||
2184 | if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) | ||
2185 | assoc_req->band = priv->curbssparams.band; | ||
2186 | |||
2187 | if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) | ||
2188 | assoc_req->mode = priv->mode; | ||
2189 | |||
2190 | if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | ||
2191 | memcpy(&assoc_req->bssid, priv->curbssparams.bssid, | ||
2192 | ETH_ALEN); | ||
2193 | } | ||
2194 | |||
2195 | if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) { | ||
2196 | int i; | ||
2197 | for (i = 0; i < 4; i++) { | ||
2198 | memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i], | ||
2199 | sizeof(struct enc_key)); | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2203 | if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) | ||
2204 | assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx; | ||
2205 | |||
2206 | if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { | ||
2207 | memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key, | ||
2208 | sizeof(struct enc_key)); | ||
2209 | } | ||
2210 | |||
2211 | if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | ||
2212 | memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key, | ||
2213 | sizeof(struct enc_key)); | ||
2214 | } | ||
2215 | |||
2216 | if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { | ||
2217 | memcpy(&assoc_req->secinfo, &priv->secinfo, | ||
2218 | sizeof(struct lbs_802_11_security)); | ||
2219 | } | ||
2220 | |||
2221 | if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { | ||
2222 | memcpy(&assoc_req->wpa_ie, &priv->wpa_ie, | ||
2223 | MAX_WPA_IE_LEN); | ||
2224 | assoc_req->wpa_ie_len = priv->wpa_ie_len; | ||
2225 | } | ||
2226 | |||
2227 | lbs_deb_leave(LBS_DEB_ASSOC); | ||
2228 | return assoc_req; | ||
2229 | } | ||
2230 | |||
2231 | |||
2232 | /** | ||
2233 | * @brief Deauthenticate from a specific BSS | ||
2234 | * | ||
2235 | * @param priv A pointer to struct lbs_private structure | ||
2236 | * @param bssid The specific BSS to deauthenticate from | ||
2237 | * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating | ||
2238 | * | ||
2239 | * @return 0 on success, error on failure | ||
2240 | */ | ||
2241 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], | ||
2242 | u16 reason) | ||
2243 | { | ||
2244 | struct cmd_ds_802_11_deauthenticate cmd; | ||
2245 | int ret; | ||
2246 | |||
2247 | lbs_deb_enter(LBS_DEB_JOIN); | ||
2248 | |||
2249 | memset(&cmd, 0, sizeof(cmd)); | ||
2250 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
2251 | memcpy(cmd.macaddr, &bssid[0], ETH_ALEN); | ||
2252 | cmd.reasoncode = cpu_to_le16(reason); | ||
2253 | |||
2254 | ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd); | ||
2255 | |||
2256 | /* Clean up everything even if there was an error; can't assume that | ||
2257 | * we're still authenticated to the AP after trying to deauth. | ||
2258 | */ | ||
2259 | lbs_mac_event_disconnected(priv); | ||
2260 | |||
2261 | lbs_deb_leave(LBS_DEB_JOIN); | ||
2262 | return ret; | ||
2263 | } | ||
2264 | |||
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h deleted file mode 100644 index 40621b789fc5..000000000000 --- a/drivers/net/wireless/libertas/assoc.h +++ /dev/null | |||
@@ -1,155 +0,0 @@ | |||
1 | /* Copyright (C) 2006, Red Hat, Inc. */ | ||
2 | |||
3 | #ifndef _LBS_ASSOC_H_ | ||
4 | #define _LBS_ASSOC_H_ | ||
5 | |||
6 | |||
7 | #include "defs.h" | ||
8 | #include "host.h" | ||
9 | |||
10 | |||
11 | struct lbs_private; | ||
12 | |||
13 | /* | ||
14 | * In theory, the IE is limited to the IE length, 255, | ||
15 | * but in practice 64 bytes are enough. | ||
16 | */ | ||
17 | #define MAX_WPA_IE_LEN 64 | ||
18 | |||
19 | |||
20 | |||
21 | struct lbs_802_11_security { | ||
22 | u8 WPAenabled; | ||
23 | u8 WPA2enabled; | ||
24 | u8 wep_enabled; | ||
25 | u8 auth_mode; | ||
26 | u32 key_mgmt; | ||
27 | }; | ||
28 | |||
29 | /** Current Basic Service Set State Structure */ | ||
30 | struct current_bss_params { | ||
31 | /** bssid */ | ||
32 | u8 bssid[ETH_ALEN]; | ||
33 | /** ssid */ | ||
34 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
35 | u8 ssid_len; | ||
36 | |||
37 | /** band */ | ||
38 | u8 band; | ||
39 | /** channel is directly in priv->channel */ | ||
40 | /** zero-terminated array of supported data rates */ | ||
41 | u8 rates[MAX_RATES + 1]; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * @brief Structure used to store information for each beacon/probe response | ||
46 | */ | ||
47 | struct bss_descriptor { | ||
48 | u8 bssid[ETH_ALEN]; | ||
49 | |||
50 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
51 | u8 ssid_len; | ||
52 | |||
53 | u16 capability; | ||
54 | u32 rssi; | ||
55 | u32 channel; | ||
56 | u16 beaconperiod; | ||
57 | __le16 atimwindow; | ||
58 | |||
59 | /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ | ||
60 | u8 mode; | ||
61 | |||
62 | /* zero-terminated array of supported data rates */ | ||
63 | u8 rates[MAX_RATES + 1]; | ||
64 | |||
65 | unsigned long last_scanned; | ||
66 | |||
67 | union ieee_phy_param_set phy; | ||
68 | union ieee_ss_param_set ss; | ||
69 | |||
70 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
71 | size_t wpa_ie_len; | ||
72 | u8 rsn_ie[MAX_WPA_IE_LEN]; | ||
73 | size_t rsn_ie_len; | ||
74 | |||
75 | u8 mesh; | ||
76 | |||
77 | struct list_head list; | ||
78 | }; | ||
79 | |||
80 | /** Association request | ||
81 | * | ||
82 | * Encapsulates all the options that describe a specific assocation request | ||
83 | * or configuration of the wireless card's radio, mode, and security settings. | ||
84 | */ | ||
85 | struct assoc_request { | ||
86 | #define ASSOC_FLAG_SSID 1 | ||
87 | #define ASSOC_FLAG_CHANNEL 2 | ||
88 | #define ASSOC_FLAG_BAND 3 | ||
89 | #define ASSOC_FLAG_MODE 4 | ||
90 | #define ASSOC_FLAG_BSSID 5 | ||
91 | #define ASSOC_FLAG_WEP_KEYS 6 | ||
92 | #define ASSOC_FLAG_WEP_TX_KEYIDX 7 | ||
93 | #define ASSOC_FLAG_WPA_MCAST_KEY 8 | ||
94 | #define ASSOC_FLAG_WPA_UCAST_KEY 9 | ||
95 | #define ASSOC_FLAG_SECINFO 10 | ||
96 | #define ASSOC_FLAG_WPA_IE 11 | ||
97 | unsigned long flags; | ||
98 | |||
99 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
100 | u8 ssid_len; | ||
101 | u8 channel; | ||
102 | u8 band; | ||
103 | u8 mode; | ||
104 | u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); | ||
105 | |||
106 | /** WEP keys */ | ||
107 | struct enc_key wep_keys[4]; | ||
108 | u16 wep_tx_keyidx; | ||
109 | |||
110 | /** WPA keys */ | ||
111 | struct enc_key wpa_mcast_key; | ||
112 | struct enc_key wpa_unicast_key; | ||
113 | |||
114 | struct lbs_802_11_security secinfo; | ||
115 | |||
116 | /** WPA Information Elements*/ | ||
117 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
118 | u8 wpa_ie_len; | ||
119 | |||
120 | /* BSS to associate with for infrastructure of Ad-Hoc join */ | ||
121 | struct bss_descriptor bss; | ||
122 | }; | ||
123 | |||
124 | |||
125 | extern u8 lbs_bg_rates[MAX_RATES]; | ||
126 | |||
127 | void lbs_association_worker(struct work_struct *work); | ||
128 | struct assoc_request *lbs_get_association_request(struct lbs_private *priv); | ||
129 | |||
130 | int lbs_adhoc_stop(struct lbs_private *priv); | ||
131 | |||
132 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, | ||
133 | u8 bssid[ETH_ALEN], u16 reason); | ||
134 | |||
135 | int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
136 | struct cmd_ds_command *cmd); | ||
137 | int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
138 | struct cmd_ds_command *resp); | ||
139 | |||
140 | int lbs_cmd_bcn_ctrl(struct lbs_private *priv, | ||
141 | struct cmd_ds_command *cmd, | ||
142 | u16 cmd_action); | ||
143 | int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv, | ||
144 | struct cmd_ds_command *resp); | ||
145 | |||
146 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
147 | struct assoc_request *assoc); | ||
148 | |||
149 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
150 | uint16_t *enable); | ||
151 | |||
152 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
153 | struct assoc_request *assoc); | ||
154 | |||
155 | #endif /* _LBS_ASSOC_H */ | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 9d5d3ccf08c8..f36cc970ad1b 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -7,8 +7,12 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/if_arp.h> | ||
11 | #include <linux/ieee80211.h> | ||
10 | #include <net/cfg80211.h> | 12 | #include <net/cfg80211.h> |
13 | #include <asm/unaligned.h> | ||
11 | 14 | ||
15 | #include "decl.h" | ||
12 | #include "cfg.h" | 16 | #include "cfg.h" |
13 | #include "cmd.h" | 17 | #include "cmd.h" |
14 | 18 | ||
@@ -39,26 +43,27 @@ static struct ieee80211_channel lbs_2ghz_channels[] = { | |||
39 | CHAN2G(14, 2484, 0), | 43 | CHAN2G(14, 2484, 0), |
40 | }; | 44 | }; |
41 | 45 | ||
42 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | 46 | #define RATETAB_ENT(_rate, _hw_value, _flags) { \ |
43 | .bitrate = (_rate), \ | 47 | .bitrate = (_rate), \ |
44 | .hw_value = (_rateid), \ | 48 | .hw_value = (_hw_value), \ |
45 | .flags = (_flags), \ | 49 | .flags = (_flags), \ |
46 | } | 50 | } |
47 | 51 | ||
48 | 52 | ||
53 | /* Table 6 in section 3.2.1.1 */ | ||
49 | static struct ieee80211_rate lbs_rates[] = { | 54 | static struct ieee80211_rate lbs_rates[] = { |
50 | RATETAB_ENT(10, 0x1, 0), | 55 | RATETAB_ENT(10, 0, 0), |
51 | RATETAB_ENT(20, 0x2, 0), | 56 | RATETAB_ENT(20, 1, 0), |
52 | RATETAB_ENT(55, 0x4, 0), | 57 | RATETAB_ENT(55, 2, 0), |
53 | RATETAB_ENT(110, 0x8, 0), | 58 | RATETAB_ENT(110, 3, 0), |
54 | RATETAB_ENT(60, 0x10, 0), | 59 | RATETAB_ENT(60, 9, 0), |
55 | RATETAB_ENT(90, 0x20, 0), | 60 | RATETAB_ENT(90, 6, 0), |
56 | RATETAB_ENT(120, 0x40, 0), | 61 | RATETAB_ENT(120, 7, 0), |
57 | RATETAB_ENT(180, 0x80, 0), | 62 | RATETAB_ENT(180, 8, 0), |
58 | RATETAB_ENT(240, 0x100, 0), | 63 | RATETAB_ENT(240, 9, 0), |
59 | RATETAB_ENT(360, 0x200, 0), | 64 | RATETAB_ENT(360, 10, 0), |
60 | RATETAB_ENT(480, 0x400, 0), | 65 | RATETAB_ENT(480, 11, 0), |
61 | RATETAB_ENT(540, 0x800, 0), | 66 | RATETAB_ENT(540, 12, 0), |
62 | }; | 67 | }; |
63 | 68 | ||
64 | static struct ieee80211_supported_band lbs_band_2ghz = { | 69 | static struct ieee80211_supported_band lbs_band_2ghz = { |
@@ -76,22 +81,639 @@ static const u32 cipher_suites[] = { | |||
76 | WLAN_CIPHER_SUITE_CCMP, | 81 | WLAN_CIPHER_SUITE_CCMP, |
77 | }; | 82 | }; |
78 | 83 | ||
84 | /* Time to stay on the channel */ | ||
85 | #define LBS_DWELL_PASSIVE 100 | ||
86 | #define LBS_DWELL_ACTIVE 40 | ||
79 | 87 | ||
80 | 88 | ||
89 | /*************************************************************************** | ||
90 | * Misc utility functions | ||
91 | * | ||
92 | * TLVs are Marvell specific. They are very similar to IEs, they have the | ||
93 | * same structure: type, length, data*. The only difference: for IEs, the | ||
94 | * type and length are u8, but for TLVs they're __le16. | ||
95 | */ | ||
96 | |||
97 | /* | ||
98 | * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1 | ||
99 | * in the firmware spec | ||
100 | */ | ||
101 | static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type) | ||
102 | { | ||
103 | int ret = -ENOTSUPP; | ||
104 | |||
105 | switch (auth_type) { | ||
106 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
107 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
108 | ret = auth_type; | ||
109 | break; | ||
110 | case NL80211_AUTHTYPE_AUTOMATIC: | ||
111 | ret = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
112 | break; | ||
113 | case NL80211_AUTHTYPE_NETWORK_EAP: | ||
114 | ret = 0x80; | ||
115 | break; | ||
116 | default: | ||
117 | /* silence compiler */ | ||
118 | break; | ||
119 | } | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | |||
124 | /* Various firmware commands need the list of supported rates, but with | ||
125 | the hight-bit set for basic rates */ | ||
126 | static int lbs_add_rates(u8 *rates) | ||
127 | { | ||
128 | size_t i; | ||
129 | |||
130 | for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) { | ||
131 | u8 rate = lbs_rates[i].bitrate / 5; | ||
132 | if (rate == 0x02 || rate == 0x04 || | ||
133 | rate == 0x0b || rate == 0x16) | ||
134 | rate |= 0x80; | ||
135 | rates[i] = rate; | ||
136 | } | ||
137 | return ARRAY_SIZE(lbs_rates); | ||
138 | } | ||
139 | |||
140 | |||
141 | /*************************************************************************** | ||
142 | * TLV utility functions | ||
143 | * | ||
144 | * TLVs are Marvell specific. They are very similar to IEs, they have the | ||
145 | * same structure: type, length, data*. The only difference: for IEs, the | ||
146 | * type and length are u8, but for TLVs they're __le16. | ||
147 | */ | ||
148 | |||
149 | |||
150 | /* | ||
151 | * Add ssid TLV | ||
152 | */ | ||
153 | #define LBS_MAX_SSID_TLV_SIZE \ | ||
154 | (sizeof(struct mrvl_ie_header) \ | ||
155 | + IEEE80211_MAX_SSID_LEN) | ||
156 | |||
157 | static int lbs_add_ssid_tlv(u8 *tlv, const u8 *ssid, int ssid_len) | ||
158 | { | ||
159 | struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv; | ||
160 | |||
161 | /* | ||
162 | * TLV-ID SSID 00 00 | ||
163 | * length 06 00 | ||
164 | * ssid 4d 4e 54 45 53 54 | ||
165 | */ | ||
166 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
167 | ssid_tlv->header.len = cpu_to_le16(ssid_len); | ||
168 | memcpy(ssid_tlv->ssid, ssid, ssid_len); | ||
169 | return sizeof(ssid_tlv->header) + ssid_len; | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | ||
174 | * Add channel list TLV (section 8.4.2) | ||
175 | * | ||
176 | * Actual channel data comes from priv->wdev->wiphy->channels. | ||
177 | */ | ||
178 | #define LBS_MAX_CHANNEL_LIST_TLV_SIZE \ | ||
179 | (sizeof(struct mrvl_ie_header) \ | ||
180 | + (LBS_SCAN_BEFORE_NAP * sizeof(struct chanscanparamset))) | ||
181 | |||
182 | static int lbs_add_channel_list_tlv(struct lbs_private *priv, u8 *tlv, | ||
183 | int last_channel, int active_scan) | ||
184 | { | ||
185 | int chanscanparamsize = sizeof(struct chanscanparamset) * | ||
186 | (last_channel - priv->scan_channel); | ||
187 | |||
188 | struct mrvl_ie_header *header = (void *) tlv; | ||
189 | |||
190 | /* | ||
191 | * TLV-ID CHANLIST 01 01 | ||
192 | * length 0e 00 | ||
193 | * channel 00 01 00 00 00 64 00 | ||
194 | * radio type 00 | ||
195 | * channel 01 | ||
196 | * scan type 00 | ||
197 | * min scan time 00 00 | ||
198 | * max scan time 64 00 | ||
199 | * channel 2 00 02 00 00 00 64 00 | ||
200 | * | ||
201 | */ | ||
202 | |||
203 | header->type = cpu_to_le16(TLV_TYPE_CHANLIST); | ||
204 | header->len = cpu_to_le16(chanscanparamsize); | ||
205 | tlv += sizeof(struct mrvl_ie_header); | ||
206 | |||
207 | /* lbs_deb_scan("scan: channels %d to %d\n", priv->scan_channel, | ||
208 | last_channel); */ | ||
209 | memset(tlv, 0, chanscanparamsize); | ||
210 | |||
211 | while (priv->scan_channel < last_channel) { | ||
212 | struct chanscanparamset *param = (void *) tlv; | ||
213 | |||
214 | param->radiotype = CMD_SCAN_RADIO_TYPE_BG; | ||
215 | param->channumber = | ||
216 | priv->scan_req->channels[priv->scan_channel]->hw_value; | ||
217 | if (active_scan) { | ||
218 | param->maxscantime = cpu_to_le16(LBS_DWELL_ACTIVE); | ||
219 | } else { | ||
220 | param->chanscanmode.passivescan = 1; | ||
221 | param->maxscantime = cpu_to_le16(LBS_DWELL_PASSIVE); | ||
222 | } | ||
223 | tlv += sizeof(struct chanscanparamset); | ||
224 | priv->scan_channel++; | ||
225 | } | ||
226 | return sizeof(struct mrvl_ie_header) + chanscanparamsize; | ||
227 | } | ||
228 | |||
229 | |||
230 | /* | ||
231 | * Add rates TLV | ||
232 | * | ||
233 | * The rates are in lbs_bg_rates[], but for the 802.11b | ||
234 | * rates the high bit is set. We add this TLV only because | ||
235 | * there's a firmware which otherwise doesn't report all | ||
236 | * APs in range. | ||
237 | */ | ||
238 | #define LBS_MAX_RATES_TLV_SIZE \ | ||
239 | (sizeof(struct mrvl_ie_header) \ | ||
240 | + (ARRAY_SIZE(lbs_rates))) | ||
241 | |||
242 | /* Adds a TLV with all rates the hardware supports */ | ||
243 | static int lbs_add_supported_rates_tlv(u8 *tlv) | ||
244 | { | ||
245 | size_t i; | ||
246 | struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; | ||
247 | |||
248 | /* | ||
249 | * TLV-ID RATES 01 00 | ||
250 | * length 0e 00 | ||
251 | * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c | ||
252 | */ | ||
253 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
254 | tlv += sizeof(rate_tlv->header); | ||
255 | i = lbs_add_rates(tlv); | ||
256 | tlv += i; | ||
257 | rate_tlv->header.len = cpu_to_le16(i); | ||
258 | return sizeof(rate_tlv->header) + i; | ||
259 | } | ||
260 | |||
261 | |||
262 | /* | ||
263 | * Adds a TLV with all rates the hardware *and* BSS supports. | ||
264 | */ | ||
265 | static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss) | ||
266 | { | ||
267 | struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; | ||
268 | const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | ||
269 | int n; | ||
270 | |||
271 | /* | ||
272 | * 01 00 TLV_TYPE_RATES | ||
273 | * 04 00 len | ||
274 | * 82 84 8b 96 rates | ||
275 | */ | ||
276 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
277 | tlv += sizeof(rate_tlv->header); | ||
278 | |||
279 | if (!rates_eid) { | ||
280 | /* Fallback: add basic 802.11b rates */ | ||
281 | *tlv++ = 0x82; | ||
282 | *tlv++ = 0x84; | ||
283 | *tlv++ = 0x8b; | ||
284 | *tlv++ = 0x96; | ||
285 | n = 4; | ||
286 | } else { | ||
287 | int hw, ap; | ||
288 | u8 ap_max = rates_eid[1]; | ||
289 | n = 0; | ||
290 | for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { | ||
291 | u8 hw_rate = lbs_rates[hw].bitrate / 5; | ||
292 | for (ap = 0; ap < ap_max; ap++) { | ||
293 | if (hw_rate == (rates_eid[ap+2] & 0x7f)) { | ||
294 | *tlv++ = rates_eid[ap+2]; | ||
295 | n++; | ||
296 | } | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | |||
301 | rate_tlv->header.len = cpu_to_le16(n); | ||
302 | return sizeof(rate_tlv->header) + n; | ||
303 | } | ||
304 | |||
305 | |||
306 | /* | ||
307 | * Add auth type TLV. | ||
308 | * | ||
309 | * This is only needed for newer firmware (V9 and up). | ||
310 | */ | ||
311 | #define LBS_MAX_AUTH_TYPE_TLV_SIZE \ | ||
312 | sizeof(struct mrvl_ie_auth_type) | ||
313 | |||
314 | static int lbs_add_auth_type_tlv(u8 *tlv, enum nl80211_auth_type auth_type) | ||
315 | { | ||
316 | struct mrvl_ie_auth_type *auth = (void *) tlv; | ||
317 | |||
318 | /* | ||
319 | * 1f 01 TLV_TYPE_AUTH_TYPE | ||
320 | * 01 00 len | ||
321 | * 01 auth type | ||
322 | */ | ||
323 | auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); | ||
324 | auth->header.len = cpu_to_le16(sizeof(*auth)-sizeof(auth->header)); | ||
325 | auth->auth = cpu_to_le16(lbs_auth_to_authtype(auth_type)); | ||
326 | return sizeof(*auth); | ||
327 | } | ||
328 | |||
329 | |||
330 | /* | ||
331 | * Add channel (phy ds) TLV | ||
332 | */ | ||
333 | #define LBS_MAX_CHANNEL_TLV_SIZE \ | ||
334 | sizeof(struct mrvl_ie_header) | ||
335 | |||
336 | static int lbs_add_channel_tlv(u8 *tlv, u8 channel) | ||
337 | { | ||
338 | struct mrvl_ie_ds_param_set *ds = (void *) tlv; | ||
339 | |||
340 | /* | ||
341 | * 03 00 TLV_TYPE_PHY_DS | ||
342 | * 01 00 len | ||
343 | * 06 channel | ||
344 | */ | ||
345 | ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); | ||
346 | ds->header.len = cpu_to_le16(sizeof(*ds)-sizeof(ds->header)); | ||
347 | ds->channel = channel; | ||
348 | return sizeof(*ds); | ||
349 | } | ||
350 | |||
351 | |||
352 | /* | ||
353 | * Add (empty) CF param TLV of the form: | ||
354 | */ | ||
355 | #define LBS_MAX_CF_PARAM_TLV_SIZE \ | ||
356 | sizeof(struct mrvl_ie_header) | ||
357 | |||
358 | static int lbs_add_cf_param_tlv(u8 *tlv) | ||
359 | { | ||
360 | struct mrvl_ie_cf_param_set *cf = (void *)tlv; | ||
361 | |||
362 | /* | ||
363 | * 04 00 TLV_TYPE_CF | ||
364 | * 06 00 len | ||
365 | * 00 cfpcnt | ||
366 | * 00 cfpperiod | ||
367 | * 00 00 cfpmaxduration | ||
368 | * 00 00 cfpdurationremaining | ||
369 | */ | ||
370 | cf->header.type = cpu_to_le16(TLV_TYPE_CF); | ||
371 | cf->header.len = cpu_to_le16(sizeof(*cf)-sizeof(cf->header)); | ||
372 | return sizeof(*cf); | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Add WPA TLV | ||
377 | */ | ||
378 | #define LBS_MAX_WPA_TLV_SIZE \ | ||
379 | (sizeof(struct mrvl_ie_header) \ | ||
380 | + 128 /* TODO: I guessed the size */) | ||
381 | |||
382 | static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) | ||
383 | { | ||
384 | size_t tlv_len; | ||
385 | |||
386 | /* | ||
387 | * We need just convert an IE to an TLV. IEs use u8 for the header, | ||
388 | * u8 type | ||
389 | * u8 len | ||
390 | * u8[] data | ||
391 | * but TLVs use __le16 instead: | ||
392 | * __le16 type | ||
393 | * __le16 len | ||
394 | * u8[] data | ||
395 | */ | ||
396 | *tlv++ = *ie++; | ||
397 | *tlv++ = 0; | ||
398 | tlv_len = *tlv++ = *ie++; | ||
399 | *tlv++ = 0; | ||
400 | while (tlv_len--) | ||
401 | *tlv++ = *ie++; | ||
402 | /* the TLV is two bytes larger than the IE */ | ||
403 | return ie_len + 2; | ||
404 | } | ||
405 | |||
406 | /*************************************************************************** | ||
407 | * Set Channel | ||
408 | */ | ||
409 | |||
81 | static int lbs_cfg_set_channel(struct wiphy *wiphy, | 410 | static int lbs_cfg_set_channel(struct wiphy *wiphy, |
82 | struct net_device *netdev, | 411 | struct net_device *netdev, |
83 | struct ieee80211_channel *chan, | 412 | struct ieee80211_channel *channel, |
84 | enum nl80211_channel_type channel_type) | 413 | enum nl80211_channel_type channel_type) |
85 | { | 414 | { |
86 | struct lbs_private *priv = wiphy_priv(wiphy); | 415 | struct lbs_private *priv = wiphy_priv(wiphy); |
87 | int ret = -ENOTSUPP; | 416 | int ret = -ENOTSUPP; |
88 | 417 | ||
89 | lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type); | 418 | lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", |
419 | channel->center_freq, channel_type); | ||
90 | 420 | ||
91 | if (channel_type != NL80211_CHAN_NO_HT) | 421 | if (channel_type != NL80211_CHAN_NO_HT) |
92 | goto out; | 422 | goto out; |
93 | 423 | ||
94 | ret = lbs_set_channel(priv, chan->hw_value); | 424 | ret = lbs_set_channel(priv, channel->hw_value); |
425 | |||
426 | out: | ||
427 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | |||
432 | |||
433 | /*************************************************************************** | ||
434 | * Scanning | ||
435 | */ | ||
436 | |||
437 | /* | ||
438 | * When scanning, the firmware doesn't send a nul packet with the power-safe | ||
439 | * bit to the AP. So we cannot stay away from our current channel too long, | ||
440 | * otherwise we loose data. So take a "nap" while scanning every other | ||
441 | * while. | ||
442 | */ | ||
443 | #define LBS_SCAN_BEFORE_NAP 4 | ||
444 | |||
445 | |||
446 | /* | ||
447 | * When the firmware reports back a scan-result, it gives us an "u8 rssi", | ||
448 | * which isn't really an RSSI, as it becomes larger when moving away from | ||
449 | * the AP. Anyway, we need to convert that into mBm. | ||
450 | */ | ||
451 | #define LBS_SCAN_RSSI_TO_MBM(rssi) \ | ||
452 | ((-(int)rssi + 3)*100) | ||
453 | |||
454 | static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | ||
455 | struct cmd_header *resp) | ||
456 | { | ||
457 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; | ||
458 | int bsssize; | ||
459 | const u8 *pos; | ||
460 | u16 nr_sets; | ||
461 | const u8 *tsfdesc; | ||
462 | int tsfsize; | ||
463 | int i; | ||
464 | int ret = -EILSEQ; | ||
465 | |||
466 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
467 | |||
468 | bsssize = get_unaligned_le16(&scanresp->bssdescriptsize); | ||
469 | nr_sets = le16_to_cpu(resp->size); | ||
470 | |||
471 | /* | ||
472 | * The general layout of the scan response is described in chapter | ||
473 | * 5.7.1. Basically we have a common part, then any number of BSS | ||
474 | * descriptor sections. Finally we have section with the same number | ||
475 | * of TSFs. | ||
476 | * | ||
477 | * cmd_ds_802_11_scan_rsp | ||
478 | * cmd_header | ||
479 | * pos_size | ||
480 | * nr_sets | ||
481 | * bssdesc 1 | ||
482 | * bssid | ||
483 | * rssi | ||
484 | * timestamp | ||
485 | * intvl | ||
486 | * capa | ||
487 | * IEs | ||
488 | * bssdesc 2 | ||
489 | * bssdesc n | ||
490 | * MrvlIEtypes_TsfFimestamp_t | ||
491 | * TSF for BSS 1 | ||
492 | * TSF for BSS 2 | ||
493 | * TSF for BSS n | ||
494 | */ | ||
495 | |||
496 | pos = scanresp->bssdesc_and_tlvbuffer; | ||
497 | |||
498 | tsfdesc = pos + bsssize; | ||
499 | tsfsize = 4 + 8 * scanresp->nr_sets; | ||
500 | |||
501 | /* Validity check: we expect a Marvell-Local TLV */ | ||
502 | i = get_unaligned_le16(tsfdesc); | ||
503 | tsfdesc += 2; | ||
504 | if (i != TLV_TYPE_TSFTIMESTAMP) | ||
505 | goto done; | ||
506 | /* Validity check: the TLV holds TSF values with 8 bytes each, so | ||
507 | * the size in the TLV must match the nr_sets value */ | ||
508 | i = get_unaligned_le16(tsfdesc); | ||
509 | tsfdesc += 2; | ||
510 | if (i / 8 != scanresp->nr_sets) | ||
511 | goto done; | ||
512 | |||
513 | for (i = 0; i < scanresp->nr_sets; i++) { | ||
514 | const u8 *bssid; | ||
515 | const u8 *ie; | ||
516 | int left; | ||
517 | int ielen; | ||
518 | int rssi; | ||
519 | u16 intvl; | ||
520 | u16 capa; | ||
521 | int chan_no = -1; | ||
522 | const u8 *ssid = NULL; | ||
523 | u8 ssid_len = 0; | ||
524 | DECLARE_SSID_BUF(ssid_buf); | ||
525 | |||
526 | int len = get_unaligned_le16(pos); | ||
527 | pos += 2; | ||
528 | |||
529 | /* BSSID */ | ||
530 | bssid = pos; | ||
531 | pos += ETH_ALEN; | ||
532 | /* RSSI */ | ||
533 | rssi = *pos++; | ||
534 | /* Packet time stamp */ | ||
535 | pos += 8; | ||
536 | /* Beacon interval */ | ||
537 | intvl = get_unaligned_le16(pos); | ||
538 | pos += 2; | ||
539 | /* Capabilities */ | ||
540 | capa = get_unaligned_le16(pos); | ||
541 | pos += 2; | ||
542 | |||
543 | /* To find out the channel, we must parse the IEs */ | ||
544 | ie = pos; | ||
545 | /* 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon | ||
546 | interval, capabilities */ | ||
547 | ielen = left = len - (6 + 1 + 8 + 2 + 2); | ||
548 | while (left >= 2) { | ||
549 | u8 id, elen; | ||
550 | id = *pos++; | ||
551 | elen = *pos++; | ||
552 | left -= 2; | ||
553 | if (elen > left || elen == 0) | ||
554 | goto done; | ||
555 | if (id == WLAN_EID_DS_PARAMS) | ||
556 | chan_no = *pos; | ||
557 | if (id == WLAN_EID_SSID) { | ||
558 | ssid = pos; | ||
559 | ssid_len = elen; | ||
560 | } | ||
561 | left -= elen; | ||
562 | pos += elen; | ||
563 | } | ||
564 | |||
565 | /* No channel, no luck */ | ||
566 | if (chan_no != -1) { | ||
567 | struct wiphy *wiphy = priv->wdev->wiphy; | ||
568 | int freq = ieee80211_channel_to_frequency(chan_no); | ||
569 | struct ieee80211_channel *channel = | ||
570 | ieee80211_get_channel(wiphy, freq); | ||
571 | |||
572 | lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, " | ||
573 | "%d dBm\n", | ||
574 | bssid, capa, chan_no, | ||
575 | print_ssid(ssid_buf, ssid, ssid_len), | ||
576 | LBS_SCAN_RSSI_TO_MBM(rssi)/100); | ||
577 | |||
578 | if (channel || | ||
579 | !(channel->flags & IEEE80211_CHAN_DISABLED)) | ||
580 | cfg80211_inform_bss(wiphy, channel, | ||
581 | bssid, le64_to_cpu(*(__le64 *)tsfdesc), | ||
582 | capa, intvl, ie, ielen, | ||
583 | LBS_SCAN_RSSI_TO_MBM(rssi), | ||
584 | GFP_KERNEL); | ||
585 | } | ||
586 | tsfdesc += 8; | ||
587 | } | ||
588 | ret = 0; | ||
589 | |||
590 | done: | ||
591 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | |||
596 | /* | ||
597 | * Our scan command contains a TLV, consting of a SSID TLV, a channel list | ||
598 | * TLV and a rates TLV. Determine the maximum size of them: | ||
599 | */ | ||
600 | #define LBS_SCAN_MAX_CMD_SIZE \ | ||
601 | (sizeof(struct cmd_ds_802_11_scan) \ | ||
602 | + LBS_MAX_SSID_TLV_SIZE \ | ||
603 | + LBS_MAX_CHANNEL_LIST_TLV_SIZE \ | ||
604 | + LBS_MAX_RATES_TLV_SIZE) | ||
605 | |||
606 | /* | ||
607 | * Assumes priv->scan_req is initialized and valid | ||
608 | * Assumes priv->scan_channel is initialized | ||
609 | */ | ||
610 | static void lbs_scan_worker(struct work_struct *work) | ||
611 | { | ||
612 | struct lbs_private *priv = | ||
613 | container_of(work, struct lbs_private, scan_work.work); | ||
614 | struct cmd_ds_802_11_scan *scan_cmd; | ||
615 | u8 *tlv; /* pointer into our current, growing TLV storage area */ | ||
616 | int last_channel; | ||
617 | int running, carrier; | ||
618 | |||
619 | lbs_deb_enter(LBS_DEB_SCAN); | ||
620 | |||
621 | scan_cmd = kzalloc(LBS_SCAN_MAX_CMD_SIZE, GFP_KERNEL); | ||
622 | if (scan_cmd == NULL) | ||
623 | goto out_no_scan_cmd; | ||
624 | |||
625 | /* prepare fixed part of scan command */ | ||
626 | scan_cmd->bsstype = CMD_BSS_TYPE_ANY; | ||
627 | |||
628 | /* stop network while we're away from our main channel */ | ||
629 | running = !netif_queue_stopped(priv->dev); | ||
630 | carrier = netif_carrier_ok(priv->dev); | ||
631 | if (running) | ||
632 | netif_stop_queue(priv->dev); | ||
633 | if (carrier) | ||
634 | netif_carrier_off(priv->dev); | ||
635 | |||
636 | /* prepare fixed part of scan command */ | ||
637 | tlv = scan_cmd->tlvbuffer; | ||
638 | |||
639 | /* add SSID TLV */ | ||
640 | if (priv->scan_req->n_ssids) | ||
641 | tlv += lbs_add_ssid_tlv(tlv, | ||
642 | priv->scan_req->ssids[0].ssid, | ||
643 | priv->scan_req->ssids[0].ssid_len); | ||
644 | |||
645 | /* add channel TLVs */ | ||
646 | last_channel = priv->scan_channel + LBS_SCAN_BEFORE_NAP; | ||
647 | if (last_channel > priv->scan_req->n_channels) | ||
648 | last_channel = priv->scan_req->n_channels; | ||
649 | tlv += lbs_add_channel_list_tlv(priv, tlv, last_channel, | ||
650 | priv->scan_req->n_ssids); | ||
651 | |||
652 | /* add rates TLV */ | ||
653 | tlv += lbs_add_supported_rates_tlv(tlv); | ||
654 | |||
655 | if (priv->scan_channel < priv->scan_req->n_channels) { | ||
656 | cancel_delayed_work(&priv->scan_work); | ||
657 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
658 | msecs_to_jiffies(300)); | ||
659 | } | ||
660 | |||
661 | /* This is the final data we are about to send */ | ||
662 | scan_cmd->hdr.size = cpu_to_le16(tlv - (u8 *)scan_cmd); | ||
663 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, | ||
664 | sizeof(*scan_cmd)); | ||
665 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, | ||
666 | tlv - scan_cmd->tlvbuffer); | ||
667 | |||
668 | __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, | ||
669 | le16_to_cpu(scan_cmd->hdr.size), | ||
670 | lbs_ret_scan, 0); | ||
671 | |||
672 | if (priv->scan_channel >= priv->scan_req->n_channels) { | ||
673 | /* Mark scan done */ | ||
674 | cfg80211_scan_done(priv->scan_req, false); | ||
675 | priv->scan_req = NULL; | ||
676 | } | ||
677 | |||
678 | /* Restart network */ | ||
679 | if (carrier) | ||
680 | netif_carrier_on(priv->dev); | ||
681 | if (running && !priv->tx_pending_len) | ||
682 | netif_wake_queue(priv->dev); | ||
683 | |||
684 | kfree(scan_cmd); | ||
685 | |||
686 | out_no_scan_cmd: | ||
687 | lbs_deb_leave(LBS_DEB_SCAN); | ||
688 | } | ||
689 | |||
690 | |||
691 | static int lbs_cfg_scan(struct wiphy *wiphy, | ||
692 | struct net_device *dev, | ||
693 | struct cfg80211_scan_request *request) | ||
694 | { | ||
695 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
696 | int ret = 0; | ||
697 | |||
698 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
699 | |||
700 | if (priv->scan_req || delayed_work_pending(&priv->scan_work)) { | ||
701 | /* old scan request not yet processed */ | ||
702 | ret = -EAGAIN; | ||
703 | goto out; | ||
704 | } | ||
705 | |||
706 | lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n", | ||
707 | request->n_ssids, request->n_channels, request->ie_len); | ||
708 | |||
709 | priv->scan_channel = 0; | ||
710 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
711 | msecs_to_jiffies(50)); | ||
712 | |||
713 | if (priv->surpriseremoved) | ||
714 | ret = -EIO; | ||
715 | |||
716 | priv->scan_req = request; | ||
95 | 717 | ||
96 | out: | 718 | out: |
97 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 719 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
@@ -101,8 +723,1228 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy, | |||
101 | 723 | ||
102 | 724 | ||
103 | 725 | ||
726 | /*************************************************************************** | ||
727 | * Events | ||
728 | */ | ||
729 | |||
730 | void lbs_send_disconnect_notification(struct lbs_private *priv) | ||
731 | { | ||
732 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
733 | |||
734 | cfg80211_disconnected(priv->dev, | ||
735 | 0, | ||
736 | NULL, 0, | ||
737 | GFP_KERNEL); | ||
738 | |||
739 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
740 | } | ||
741 | |||
742 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event) | ||
743 | { | ||
744 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
745 | |||
746 | cfg80211_michael_mic_failure(priv->dev, | ||
747 | priv->assoc_bss, | ||
748 | event == MACREG_INT_CODE_MIC_ERR_MULTICAST ? | ||
749 | NL80211_KEYTYPE_GROUP : | ||
750 | NL80211_KEYTYPE_PAIRWISE, | ||
751 | -1, | ||
752 | NULL, | ||
753 | GFP_KERNEL); | ||
754 | |||
755 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
756 | } | ||
757 | |||
758 | |||
759 | |||
760 | |||
761 | /*************************************************************************** | ||
762 | * Connect/disconnect | ||
763 | */ | ||
764 | |||
765 | |||
766 | /* | ||
767 | * This removes all WEP keys | ||
768 | */ | ||
769 | static int lbs_remove_wep_keys(struct lbs_private *priv) | ||
770 | { | ||
771 | struct cmd_ds_802_11_set_wep cmd; | ||
772 | int ret; | ||
773 | |||
774 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
775 | |||
776 | memset(&cmd, 0, sizeof(cmd)); | ||
777 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
778 | cmd.keyindex = cpu_to_le16(priv->wep_tx_key); | ||
779 | cmd.action = cpu_to_le16(CMD_ACT_REMOVE); | ||
780 | |||
781 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
782 | |||
783 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | /* | ||
788 | * Set WEP keys | ||
789 | */ | ||
790 | static int lbs_set_wep_keys(struct lbs_private *priv) | ||
791 | { | ||
792 | struct cmd_ds_802_11_set_wep cmd; | ||
793 | int i; | ||
794 | int ret; | ||
795 | |||
796 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
797 | |||
798 | /* | ||
799 | * command 13 00 | ||
800 | * size 50 00 | ||
801 | * sequence xx xx | ||
802 | * result 00 00 | ||
803 | * action 02 00 ACT_ADD | ||
804 | * transmit key 00 00 | ||
805 | * type for key 1 01 WEP40 | ||
806 | * type for key 2 00 | ||
807 | * type for key 3 00 | ||
808 | * type for key 4 00 | ||
809 | * key 1 39 39 39 39 39 00 00 00 | ||
810 | * 00 00 00 00 00 00 00 00 | ||
811 | * key 2 00 00 00 00 00 00 00 00 | ||
812 | * 00 00 00 00 00 00 00 00 | ||
813 | * key 3 00 00 00 00 00 00 00 00 | ||
814 | * 00 00 00 00 00 00 00 00 | ||
815 | * key 4 00 00 00 00 00 00 00 00 | ||
816 | */ | ||
817 | if (priv->wep_key_len[0] || priv->wep_key_len[1] || | ||
818 | priv->wep_key_len[2] || priv->wep_key_len[3]) { | ||
819 | /* Only set wep keys if we have at least one of them */ | ||
820 | memset(&cmd, 0, sizeof(cmd)); | ||
821 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
822 | cmd.keyindex = cpu_to_le16(priv->wep_tx_key); | ||
823 | cmd.action = cpu_to_le16(CMD_ACT_ADD); | ||
824 | |||
825 | for (i = 0; i < 4; i++) { | ||
826 | switch (priv->wep_key_len[i]) { | ||
827 | case WLAN_KEY_LEN_WEP40: | ||
828 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
829 | break; | ||
830 | case WLAN_KEY_LEN_WEP104: | ||
831 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
832 | break; | ||
833 | default: | ||
834 | cmd.keytype[i] = 0; | ||
835 | break; | ||
836 | } | ||
837 | memcpy(cmd.keymaterial[i], priv->wep_key[i], | ||
838 | priv->wep_key_len[i]); | ||
839 | } | ||
840 | |||
841 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
842 | } else { | ||
843 | /* Otherwise remove all wep keys */ | ||
844 | ret = lbs_remove_wep_keys(priv); | ||
845 | } | ||
846 | |||
847 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
848 | return ret; | ||
849 | } | ||
850 | |||
851 | |||
852 | /* | ||
853 | * Enable/Disable RSN status | ||
854 | */ | ||
855 | static int lbs_enable_rsn(struct lbs_private *priv, int enable) | ||
856 | { | ||
857 | struct cmd_ds_802_11_enable_rsn cmd; | ||
858 | int ret; | ||
859 | |||
860 | lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", enable); | ||
861 | |||
862 | /* | ||
863 | * cmd 2f 00 | ||
864 | * size 0c 00 | ||
865 | * sequence xx xx | ||
866 | * result 00 00 | ||
867 | * action 01 00 ACT_SET | ||
868 | * enable 01 00 | ||
869 | */ | ||
870 | memset(&cmd, 0, sizeof(cmd)); | ||
871 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
872 | cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
873 | cmd.enable = cpu_to_le16(enable); | ||
874 | |||
875 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
876 | |||
877 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
878 | return ret; | ||
879 | } | ||
880 | |||
881 | |||
882 | /* | ||
883 | * Set WPA/WPA key material | ||
884 | */ | ||
885 | |||
886 | /* like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we | ||
887 | * get rid of WEXT, this should go into host.h */ | ||
888 | |||
889 | struct cmd_key_material { | ||
890 | struct cmd_header hdr; | ||
891 | |||
892 | __le16 action; | ||
893 | struct MrvlIEtype_keyParamSet param; | ||
894 | } __attribute__ ((packed)); | ||
895 | |||
896 | static int lbs_set_key_material(struct lbs_private *priv, | ||
897 | int key_type, | ||
898 | int key_info, | ||
899 | u8 *key, u16 key_len) | ||
900 | { | ||
901 | struct cmd_key_material cmd; | ||
902 | int ret; | ||
903 | |||
904 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
905 | |||
906 | /* | ||
907 | * Example for WPA (TKIP): | ||
908 | * | ||
909 | * cmd 5e 00 | ||
910 | * size 34 00 | ||
911 | * sequence xx xx | ||
912 | * result 00 00 | ||
913 | * action 01 00 | ||
914 | * TLV type 00 01 key param | ||
915 | * length 00 26 | ||
916 | * key type 01 00 TKIP | ||
917 | * key info 06 00 UNICAST | ENABLED | ||
918 | * key len 20 00 | ||
919 | * key 32 bytes | ||
920 | */ | ||
921 | memset(&cmd, 0, sizeof(cmd)); | ||
922 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
923 | cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
924 | cmd.param.type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
925 | cmd.param.length = cpu_to_le16(sizeof(cmd.param) - 4); | ||
926 | cmd.param.keytypeid = cpu_to_le16(key_type); | ||
927 | cmd.param.keyinfo = cpu_to_le16(key_info); | ||
928 | cmd.param.keylen = cpu_to_le16(key_len); | ||
929 | if (key && key_len) | ||
930 | memcpy(cmd.param.key, key, key_len); | ||
931 | |||
932 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | ||
933 | |||
934 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
935 | return ret; | ||
936 | } | ||
937 | |||
938 | |||
939 | /* | ||
940 | * Sets the auth type (open, shared, etc) in the firmware. That | ||
941 | * we use CMD_802_11_AUTHENTICATE is misleading, this firmware | ||
942 | * command doesn't send an authentication frame at all, it just | ||
943 | * stores the auth_type. | ||
944 | */ | ||
945 | static int lbs_set_authtype(struct lbs_private *priv, | ||
946 | struct cfg80211_connect_params *sme) | ||
947 | { | ||
948 | struct cmd_ds_802_11_authenticate cmd; | ||
949 | int ret; | ||
950 | |||
951 | lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", sme->auth_type); | ||
952 | |||
953 | /* | ||
954 | * cmd 11 00 | ||
955 | * size 19 00 | ||
956 | * sequence xx xx | ||
957 | * result 00 00 | ||
958 | * BSS id 00 13 19 80 da 30 | ||
959 | * auth type 00 | ||
960 | * reserved 00 00 00 00 00 00 00 00 00 00 | ||
961 | */ | ||
962 | memset(&cmd, 0, sizeof(cmd)); | ||
963 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
964 | if (sme->bssid) | ||
965 | memcpy(cmd.bssid, sme->bssid, ETH_ALEN); | ||
966 | /* convert auth_type */ | ||
967 | ret = lbs_auth_to_authtype(sme->auth_type); | ||
968 | if (ret < 0) | ||
969 | goto done; | ||
970 | |||
971 | cmd.authtype = ret; | ||
972 | ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); | ||
973 | |||
974 | done: | ||
975 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
976 | return ret; | ||
977 | } | ||
978 | |||
979 | |||
980 | /* | ||
981 | * Create association request | ||
982 | */ | ||
983 | #define LBS_ASSOC_MAX_CMD_SIZE \ | ||
984 | (sizeof(struct cmd_ds_802_11_associate) \ | ||
985 | - 512 /* cmd_ds_802_11_associate.iebuf */ \ | ||
986 | + LBS_MAX_SSID_TLV_SIZE \ | ||
987 | + LBS_MAX_CHANNEL_TLV_SIZE \ | ||
988 | + LBS_MAX_CF_PARAM_TLV_SIZE \ | ||
989 | + LBS_MAX_AUTH_TYPE_TLV_SIZE \ | ||
990 | + LBS_MAX_WPA_TLV_SIZE) | ||
991 | |||
992 | static int lbs_associate(struct lbs_private *priv, | ||
993 | struct cfg80211_bss *bss, | ||
994 | struct cfg80211_connect_params *sme) | ||
995 | { | ||
996 | struct cmd_ds_802_11_associate_response *resp; | ||
997 | struct cmd_ds_802_11_associate *cmd = kzalloc(LBS_ASSOC_MAX_CMD_SIZE, | ||
998 | GFP_KERNEL); | ||
999 | const u8 *ssid_eid; | ||
1000 | size_t len, resp_ie_len; | ||
1001 | int status; | ||
1002 | int ret; | ||
1003 | u8 *pos = &(cmd->iebuf[0]); | ||
1004 | |||
1005 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1006 | |||
1007 | if (!cmd) { | ||
1008 | ret = -ENOMEM; | ||
1009 | goto done; | ||
1010 | } | ||
1011 | |||
1012 | /* | ||
1013 | * cmd 50 00 | ||
1014 | * length 34 00 | ||
1015 | * sequence xx xx | ||
1016 | * result 00 00 | ||
1017 | * BSS id 00 13 19 80 da 30 | ||
1018 | * capabilities 11 00 | ||
1019 | * listen interval 0a 00 | ||
1020 | * beacon interval 00 00 | ||
1021 | * DTIM period 00 | ||
1022 | * TLVs xx (up to 512 bytes) | ||
1023 | */ | ||
1024 | cmd->hdr.command = cpu_to_le16(CMD_802_11_ASSOCIATE); | ||
1025 | |||
1026 | /* Fill in static fields */ | ||
1027 | memcpy(cmd->bssid, bss->bssid, ETH_ALEN); | ||
1028 | cmd->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); | ||
1029 | cmd->capability = cpu_to_le16(bss->capability); | ||
1030 | |||
1031 | /* add SSID TLV */ | ||
1032 | ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); | ||
1033 | if (ssid_eid) | ||
1034 | pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]); | ||
1035 | else | ||
1036 | lbs_deb_assoc("no SSID\n"); | ||
1037 | |||
1038 | /* add DS param TLV */ | ||
1039 | if (bss->channel) | ||
1040 | pos += lbs_add_channel_tlv(pos, bss->channel->hw_value); | ||
1041 | else | ||
1042 | lbs_deb_assoc("no channel\n"); | ||
1043 | |||
1044 | /* add (empty) CF param TLV */ | ||
1045 | pos += lbs_add_cf_param_tlv(pos); | ||
1046 | |||
1047 | /* add rates TLV */ | ||
1048 | pos += lbs_add_common_rates_tlv(pos, bss); | ||
1049 | |||
1050 | /* add auth type TLV */ | ||
1051 | if (priv->fwrelease >= 0x09000000) | ||
1052 | pos += lbs_add_auth_type_tlv(pos, sme->auth_type); | ||
1053 | |||
1054 | /* add WPA/WPA2 TLV */ | ||
1055 | if (sme->ie && sme->ie_len) | ||
1056 | pos += lbs_add_wpa_tlv(pos, sme->ie, sme->ie_len); | ||
1057 | |||
1058 | len = (sizeof(*cmd) - sizeof(cmd->iebuf)) + | ||
1059 | (u16)(pos - (u8 *) &cmd->iebuf); | ||
1060 | cmd->hdr.size = cpu_to_le16(len); | ||
1061 | |||
1062 | /* store for later use */ | ||
1063 | memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); | ||
1064 | |||
1065 | ret = lbs_cmd_with_response(priv, CMD_802_11_ASSOCIATE, cmd); | ||
1066 | if (ret) | ||
1067 | goto done; | ||
1068 | |||
1069 | |||
1070 | /* generate connect message to cfg80211 */ | ||
1071 | |||
1072 | resp = (void *) cmd; /* recast for easier field access */ | ||
1073 | status = le16_to_cpu(resp->statuscode); | ||
1074 | |||
1075 | /* Convert statis code of old firmware */ | ||
1076 | if (priv->fwrelease < 0x09000000) | ||
1077 | switch (status) { | ||
1078 | case 0: | ||
1079 | break; | ||
1080 | case 1: | ||
1081 | lbs_deb_assoc("invalid association parameters\n"); | ||
1082 | status = WLAN_STATUS_CAPS_UNSUPPORTED; | ||
1083 | break; | ||
1084 | case 2: | ||
1085 | lbs_deb_assoc("timer expired while waiting for AP\n"); | ||
1086 | status = WLAN_STATUS_AUTH_TIMEOUT; | ||
1087 | break; | ||
1088 | case 3: | ||
1089 | lbs_deb_assoc("association refused by AP\n"); | ||
1090 | status = WLAN_STATUS_ASSOC_DENIED_UNSPEC; | ||
1091 | break; | ||
1092 | case 4: | ||
1093 | lbs_deb_assoc("authentication refused by AP\n"); | ||
1094 | status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; | ||
1095 | break; | ||
1096 | default: | ||
1097 | lbs_deb_assoc("association failure %d\n", status); | ||
1098 | status = WLAN_STATUS_UNSPECIFIED_FAILURE; | ||
1099 | } | ||
1100 | |||
1101 | lbs_deb_assoc("status %d, capability 0x%04x\n", status, | ||
1102 | le16_to_cpu(resp->capability)); | ||
1103 | |||
1104 | resp_ie_len = le16_to_cpu(resp->hdr.size) | ||
1105 | - sizeof(resp->hdr) | ||
1106 | - 6; | ||
1107 | cfg80211_connect_result(priv->dev, | ||
1108 | priv->assoc_bss, | ||
1109 | sme->ie, sme->ie_len, | ||
1110 | resp->iebuf, resp_ie_len, | ||
1111 | status, | ||
1112 | GFP_KERNEL); | ||
1113 | |||
1114 | if (status == 0) { | ||
1115 | /* TODO: get rid of priv->connect_status */ | ||
1116 | priv->connect_status = LBS_CONNECTED; | ||
1117 | netif_carrier_on(priv->dev); | ||
1118 | if (!priv->tx_pending_len) | ||
1119 | netif_tx_wake_all_queues(priv->dev); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | done: | ||
1124 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1125 | return ret; | ||
1126 | } | ||
1127 | |||
1128 | |||
1129 | |||
1130 | static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | ||
1131 | struct cfg80211_connect_params *sme) | ||
1132 | { | ||
1133 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1134 | struct cfg80211_bss *bss = NULL; | ||
1135 | int ret = 0; | ||
1136 | u8 preamble = RADIO_PREAMBLE_SHORT; | ||
1137 | |||
1138 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1139 | |||
1140 | if (sme->bssid) { | ||
1141 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | ||
1142 | sme->ssid, sme->ssid_len, | ||
1143 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
1144 | } else { | ||
1145 | /* | ||
1146 | * Here we have an impedance mismatch. The firmware command | ||
1147 | * CMD_802_11_ASSOCIATE always needs a BSSID, it cannot | ||
1148 | * connect otherwise. However, for the connect-API of | ||
1149 | * cfg80211 the bssid is purely optional. We don't get one, | ||
1150 | * except the user specifies one on the "iw" command line. | ||
1151 | * | ||
1152 | * If we don't got one, we could initiate a scan and look | ||
1153 | * for the best matching cfg80211_bss entry. | ||
1154 | * | ||
1155 | * Or, better yet, net/wireless/sme.c get's rewritten into | ||
1156 | * something more generally useful. | ||
1157 | */ | ||
1158 | lbs_pr_err("TODO: no BSS specified\n"); | ||
1159 | ret = -ENOTSUPP; | ||
1160 | goto done; | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | if (!bss) { | ||
1165 | lbs_pr_err("assicate: bss %pM not in scan results\n", | ||
1166 | sme->bssid); | ||
1167 | ret = -ENOENT; | ||
1168 | goto done; | ||
1169 | } | ||
1170 | lbs_deb_assoc("trying %pM", sme->bssid); | ||
1171 | lbs_deb_assoc("cipher 0x%x, key index %d, key len %d\n", | ||
1172 | sme->crypto.cipher_group, | ||
1173 | sme->key_idx, sme->key_len); | ||
1174 | |||
1175 | /* As this is a new connection, clear locally stored WEP keys */ | ||
1176 | priv->wep_tx_key = 0; | ||
1177 | memset(priv->wep_key, 0, sizeof(priv->wep_key)); | ||
1178 | memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len)); | ||
1179 | |||
1180 | /* set/remove WEP keys */ | ||
1181 | switch (sme->crypto.cipher_group) { | ||
1182 | case WLAN_CIPHER_SUITE_WEP40: | ||
1183 | case WLAN_CIPHER_SUITE_WEP104: | ||
1184 | /* Store provided WEP keys in priv-> */ | ||
1185 | priv->wep_tx_key = sme->key_idx; | ||
1186 | priv->wep_key_len[sme->key_idx] = sme->key_len; | ||
1187 | memcpy(priv->wep_key[sme->key_idx], sme->key, sme->key_len); | ||
1188 | /* Set WEP keys and WEP mode */ | ||
1189 | lbs_set_wep_keys(priv); | ||
1190 | priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE; | ||
1191 | lbs_set_mac_control(priv); | ||
1192 | /* No RSN mode for WEP */ | ||
1193 | lbs_enable_rsn(priv, 0); | ||
1194 | break; | ||
1195 | case 0: /* there's no WLAN_CIPHER_SUITE_NONE definition */ | ||
1196 | /* | ||
1197 | * If we don't have no WEP, no WPA and no WPA2, | ||
1198 | * we remove all keys like in the WPA/WPA2 setup, | ||
1199 | * we just don't set RSN. | ||
1200 | * | ||
1201 | * Therefore: fall-throught | ||
1202 | */ | ||
1203 | case WLAN_CIPHER_SUITE_TKIP: | ||
1204 | case WLAN_CIPHER_SUITE_CCMP: | ||
1205 | /* Remove WEP keys and WEP mode */ | ||
1206 | lbs_remove_wep_keys(priv); | ||
1207 | priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; | ||
1208 | lbs_set_mac_control(priv); | ||
1209 | |||
1210 | /* clear the WPA/WPA2 keys */ | ||
1211 | lbs_set_key_material(priv, | ||
1212 | KEY_TYPE_ID_WEP, /* doesn't matter */ | ||
1213 | KEY_INFO_WPA_UNICAST, | ||
1214 | NULL, 0); | ||
1215 | lbs_set_key_material(priv, | ||
1216 | KEY_TYPE_ID_WEP, /* doesn't matter */ | ||
1217 | KEY_INFO_WPA_MCAST, | ||
1218 | NULL, 0); | ||
1219 | /* RSN mode for WPA/WPA2 */ | ||
1220 | lbs_enable_rsn(priv, sme->crypto.cipher_group != 0); | ||
1221 | break; | ||
1222 | default: | ||
1223 | lbs_pr_err("unsupported cipher group 0x%x\n", | ||
1224 | sme->crypto.cipher_group); | ||
1225 | ret = -ENOTSUPP; | ||
1226 | goto done; | ||
1227 | } | ||
1228 | |||
1229 | lbs_set_authtype(priv, sme); | ||
1230 | lbs_set_radio(priv, preamble, 1); | ||
1231 | |||
1232 | /* Do the actual association */ | ||
1233 | lbs_associate(priv, bss, sme); | ||
1234 | |||
1235 | done: | ||
1236 | if (bss) | ||
1237 | cfg80211_put_bss(bss); | ||
1238 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1239 | return ret; | ||
1240 | } | ||
1241 | |||
1242 | static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, | ||
1243 | u16 reason_code) | ||
1244 | { | ||
1245 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1246 | struct cmd_ds_802_11_deauthenticate cmd; | ||
1247 | |||
1248 | lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code); | ||
1249 | |||
1250 | /* store for lbs_cfg_ret_disconnect() */ | ||
1251 | priv->disassoc_reason = reason_code; | ||
1252 | |||
1253 | memset(&cmd, 0, sizeof(cmd)); | ||
1254 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1255 | /* Mildly ugly to use a locally store my own BSSID ... */ | ||
1256 | memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN); | ||
1257 | cmd.reasoncode = cpu_to_le16(reason_code); | ||
1258 | |||
1259 | if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd)) | ||
1260 | return -EFAULT; | ||
1261 | |||
1262 | cfg80211_disconnected(priv->dev, | ||
1263 | priv->disassoc_reason, | ||
1264 | NULL, 0, | ||
1265 | GFP_KERNEL); | ||
1266 | priv->connect_status = LBS_DISCONNECTED; | ||
1267 | |||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | static int lbs_cfg_set_default_key(struct wiphy *wiphy, | ||
1273 | struct net_device *netdev, | ||
1274 | u8 key_index) | ||
1275 | { | ||
1276 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1277 | |||
1278 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1279 | |||
1280 | if (key_index != priv->wep_tx_key) { | ||
1281 | lbs_deb_assoc("set_default_key: to %d\n", key_index); | ||
1282 | priv->wep_tx_key = key_index; | ||
1283 | lbs_set_wep_keys(priv); | ||
1284 | } | ||
1285 | |||
1286 | return 0; | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, | ||
1291 | u8 idx, const u8 *mac_addr, | ||
1292 | struct key_params *params) | ||
1293 | { | ||
1294 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1295 | u16 key_info; | ||
1296 | u16 key_type; | ||
1297 | int ret = 0; | ||
1298 | |||
1299 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1300 | |||
1301 | lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n", | ||
1302 | params->cipher, mac_addr); | ||
1303 | lbs_deb_assoc("add_key: key index %d, key len %d\n", | ||
1304 | idx, params->key_len); | ||
1305 | if (params->key_len) | ||
1306 | lbs_deb_hex(LBS_DEB_CFG80211, "KEY", | ||
1307 | params->key, params->key_len); | ||
1308 | |||
1309 | lbs_deb_assoc("add_key: seq len %d\n", params->seq_len); | ||
1310 | if (params->seq_len) | ||
1311 | lbs_deb_hex(LBS_DEB_CFG80211, "SEQ", | ||
1312 | params->seq, params->seq_len); | ||
1313 | |||
1314 | switch (params->cipher) { | ||
1315 | case WLAN_CIPHER_SUITE_WEP40: | ||
1316 | case WLAN_CIPHER_SUITE_WEP104: | ||
1317 | /* actually compare if something has changed ... */ | ||
1318 | if ((priv->wep_key_len[idx] != params->key_len) || | ||
1319 | memcmp(priv->wep_key[idx], | ||
1320 | params->key, params->key_len) != 0) { | ||
1321 | priv->wep_key_len[idx] = params->key_len; | ||
1322 | memcpy(priv->wep_key[idx], | ||
1323 | params->key, params->key_len); | ||
1324 | lbs_set_wep_keys(priv); | ||
1325 | } | ||
1326 | break; | ||
1327 | case WLAN_CIPHER_SUITE_TKIP: | ||
1328 | case WLAN_CIPHER_SUITE_CCMP: | ||
1329 | key_info = KEY_INFO_WPA_ENABLED | ((idx == 0) | ||
1330 | ? KEY_INFO_WPA_UNICAST | ||
1331 | : KEY_INFO_WPA_MCAST); | ||
1332 | key_type = (params->cipher == WLAN_CIPHER_SUITE_TKIP) | ||
1333 | ? KEY_TYPE_ID_TKIP | ||
1334 | : KEY_TYPE_ID_AES; | ||
1335 | lbs_set_key_material(priv, | ||
1336 | key_type, | ||
1337 | key_info, | ||
1338 | params->key, params->key_len); | ||
1339 | break; | ||
1340 | default: | ||
1341 | lbs_pr_err("unhandled cipher 0x%x\n", params->cipher); | ||
1342 | ret = -ENOTSUPP; | ||
1343 | break; | ||
1344 | } | ||
1345 | |||
1346 | return ret; | ||
1347 | } | ||
1348 | |||
1349 | |||
1350 | static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, | ||
1351 | u8 key_index, const u8 *mac_addr) | ||
1352 | { | ||
1353 | |||
1354 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1355 | |||
1356 | lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n", | ||
1357 | key_index, mac_addr); | ||
1358 | |||
1359 | #ifdef TODO | ||
1360 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1361 | /* | ||
1362 | * I think can keep this a NO-OP, because: | ||
1363 | |||
1364 | * - we clear all keys whenever we do lbs_cfg_connect() anyway | ||
1365 | * - neither "iw" nor "wpa_supplicant" won't call this during | ||
1366 | * an ongoing connection | ||
1367 | * - TODO: but I have to check if this is still true when | ||
1368 | * I set the AP to periodic re-keying | ||
1369 | * - we've not kzallec() something when we've added a key at | ||
1370 | * lbs_cfg_connect() or lbs_cfg_add_key(). | ||
1371 | * | ||
1372 | * This causes lbs_cfg_del_key() only called at disconnect time, | ||
1373 | * where we'd just waste time deleting a key that is not going | ||
1374 | * to be used anyway. | ||
1375 | */ | ||
1376 | if (key_index < 3 && priv->wep_key_len[key_index]) { | ||
1377 | priv->wep_key_len[key_index] = 0; | ||
1378 | lbs_set_wep_keys(priv); | ||
1379 | } | ||
1380 | #endif | ||
1381 | |||
1382 | return 0; | ||
1383 | } | ||
1384 | |||
1385 | |||
1386 | |||
1387 | /*************************************************************************** | ||
1388 | * Monitor mode | ||
1389 | */ | ||
1390 | |||
1391 | /* like "struct cmd_ds_802_11_monitor_mode", but with cmd_header. Once we | ||
1392 | * get rid of WEXT, this should go into host.h */ | ||
1393 | struct cmd_monitor_mode { | ||
1394 | struct cmd_header hdr; | ||
1395 | |||
1396 | __le16 action; | ||
1397 | __le16 mode; | ||
1398 | } __attribute__ ((packed)); | ||
1399 | |||
1400 | static int lbs_enable_monitor_mode(struct lbs_private *priv, int mode) | ||
1401 | { | ||
1402 | struct cmd_monitor_mode cmd; | ||
1403 | int ret; | ||
1404 | |||
1405 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1406 | |||
1407 | /* | ||
1408 | * cmd 98 00 | ||
1409 | * size 0c 00 | ||
1410 | * sequence xx xx | ||
1411 | * result 00 00 | ||
1412 | * action 01 00 ACT_SET | ||
1413 | * enable 01 00 | ||
1414 | */ | ||
1415 | memset(&cmd, 0, sizeof(cmd)); | ||
1416 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1417 | cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
1418 | cmd.mode = cpu_to_le16(mode); | ||
1419 | |||
1420 | ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd); | ||
1421 | |||
1422 | if (ret == 0) | ||
1423 | priv->dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
1424 | else | ||
1425 | priv->dev->type = ARPHRD_ETHER; | ||
1426 | |||
1427 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
1428 | return ret; | ||
1429 | } | ||
1430 | |||
1431 | |||
1432 | |||
1433 | |||
1434 | |||
1435 | |||
1436 | /*************************************************************************** | ||
1437 | * Get station | ||
1438 | */ | ||
1439 | |||
1440 | /* | ||
1441 | * Returns the signal or 0 in case of an error. | ||
1442 | */ | ||
1443 | |||
1444 | /* like "struct cmd_ds_802_11_rssi", but with cmd_header. Once we get rid | ||
1445 | * of WEXT, this should go into host.h */ | ||
1446 | struct cmd_rssi { | ||
1447 | struct cmd_header hdr; | ||
1448 | |||
1449 | __le16 n_or_snr; | ||
1450 | __le16 nf; | ||
1451 | __le16 avg_snr; | ||
1452 | __le16 avg_nf; | ||
1453 | } __attribute__ ((packed)); | ||
1454 | |||
1455 | static int lbs_get_signal(struct lbs_private *priv, s8 *signal, s8 *noise) | ||
1456 | { | ||
1457 | struct cmd_rssi cmd; | ||
1458 | int ret; | ||
1459 | |||
1460 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1461 | cmd.n_or_snr = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
1462 | ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd); | ||
1463 | |||
1464 | if (ret == 0) { | ||
1465 | *signal = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), | ||
1466 | le16_to_cpu(cmd.nf)); | ||
1467 | *noise = CAL_NF(le16_to_cpu(cmd.nf)); | ||
1468 | } | ||
1469 | return ret; | ||
1470 | } | ||
1471 | |||
1472 | |||
1473 | static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, | ||
1474 | u8 *mac, struct station_info *sinfo) | ||
1475 | { | ||
1476 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1477 | s8 signal, noise; | ||
1478 | int ret; | ||
1479 | size_t i; | ||
1480 | |||
1481 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1482 | |||
1483 | sinfo->filled |= STATION_INFO_TX_BYTES | | ||
1484 | STATION_INFO_TX_PACKETS | | ||
1485 | STATION_INFO_RX_BYTES | | ||
1486 | STATION_INFO_RX_PACKETS; | ||
1487 | sinfo->tx_bytes = priv->dev->stats.tx_bytes; | ||
1488 | sinfo->tx_packets = priv->dev->stats.tx_packets; | ||
1489 | sinfo->rx_bytes = priv->dev->stats.rx_bytes; | ||
1490 | sinfo->rx_packets = priv->dev->stats.rx_packets; | ||
1491 | |||
1492 | /* Get current RSSI */ | ||
1493 | ret = lbs_get_signal(priv, &signal, &noise); | ||
1494 | if (ret == 0) { | ||
1495 | sinfo->signal = signal; | ||
1496 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
1497 | } | ||
1498 | |||
1499 | /* Convert priv->cur_rate from hw_value to NL80211 value */ | ||
1500 | for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) { | ||
1501 | if (priv->cur_rate == lbs_rates[i].hw_value) { | ||
1502 | sinfo->txrate.legacy = lbs_rates[i].bitrate; | ||
1503 | sinfo->filled |= STATION_INFO_TX_BITRATE; | ||
1504 | break; | ||
1505 | } | ||
1506 | } | ||
1507 | |||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1511 | |||
1512 | |||
1513 | |||
1514 | /*************************************************************************** | ||
1515 | * "Site survey", here just current channel and noise level | ||
1516 | */ | ||
1517 | |||
1518 | static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev, | ||
1519 | int idx, struct survey_info *survey) | ||
1520 | { | ||
1521 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1522 | s8 signal, noise; | ||
1523 | int ret; | ||
1524 | |||
1525 | if (idx != 0) | ||
1526 | ret = -ENOENT; | ||
1527 | |||
1528 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1529 | |||
1530 | survey->channel = ieee80211_get_channel(wiphy, | ||
1531 | ieee80211_channel_to_frequency(priv->channel)); | ||
1532 | |||
1533 | ret = lbs_get_signal(priv, &signal, &noise); | ||
1534 | if (ret == 0) { | ||
1535 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
1536 | survey->noise = noise; | ||
1537 | } | ||
1538 | |||
1539 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1540 | return ret; | ||
1541 | } | ||
1542 | |||
1543 | |||
1544 | |||
1545 | |||
1546 | /*************************************************************************** | ||
1547 | * Change interface | ||
1548 | */ | ||
1549 | |||
1550 | static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, | ||
1551 | enum nl80211_iftype type, u32 *flags, | ||
1552 | struct vif_params *params) | ||
1553 | { | ||
1554 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1555 | int ret = 0; | ||
1556 | |||
1557 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1558 | |||
1559 | switch (type) { | ||
1560 | case NL80211_IFTYPE_MONITOR: | ||
1561 | ret = lbs_enable_monitor_mode(priv, 1); | ||
1562 | break; | ||
1563 | case NL80211_IFTYPE_STATION: | ||
1564 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
1565 | ret = lbs_enable_monitor_mode(priv, 0); | ||
1566 | if (!ret) | ||
1567 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); | ||
1568 | break; | ||
1569 | case NL80211_IFTYPE_ADHOC: | ||
1570 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
1571 | ret = lbs_enable_monitor_mode(priv, 0); | ||
1572 | if (!ret) | ||
1573 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); | ||
1574 | break; | ||
1575 | default: | ||
1576 | ret = -ENOTSUPP; | ||
1577 | } | ||
1578 | |||
1579 | if (!ret) | ||
1580 | priv->wdev->iftype = type; | ||
1581 | |||
1582 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1583 | return ret; | ||
1584 | } | ||
1585 | |||
1586 | |||
1587 | |||
1588 | /*************************************************************************** | ||
1589 | * IBSS (Ad-Hoc) | ||
1590 | */ | ||
1591 | |||
1592 | /* The firmware needs the following bits masked out of the beacon-derived | ||
1593 | * capability field when associating/joining to a BSS: | ||
1594 | * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) | ||
1595 | */ | ||
1596 | #define CAPINFO_MASK (~(0xda00)) | ||
1597 | |||
1598 | |||
1599 | static void lbs_join_post(struct lbs_private *priv, | ||
1600 | struct cfg80211_ibss_params *params, | ||
1601 | u8 *bssid, u16 capability) | ||
1602 | { | ||
1603 | u8 fake_ie[2 + IEEE80211_MAX_SSID_LEN + /* ssid */ | ||
1604 | 2 + 4 + /* basic rates */ | ||
1605 | 2 + 1 + /* DS parameter */ | ||
1606 | 2 + 2 + /* atim */ | ||
1607 | 2 + 8]; /* extended rates */ | ||
1608 | u8 *fake = fake_ie; | ||
1609 | |||
1610 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1611 | |||
1612 | /* | ||
1613 | * For cfg80211_inform_bss, we'll need a fake IE, as we can't get | ||
1614 | * the real IE from the firmware. So we fabricate a fake IE based on | ||
1615 | * what the firmware actually sends (sniffed with wireshark). | ||
1616 | */ | ||
1617 | /* Fake SSID IE */ | ||
1618 | *fake++ = WLAN_EID_SSID; | ||
1619 | *fake++ = params->ssid_len; | ||
1620 | memcpy(fake, params->ssid, params->ssid_len); | ||
1621 | fake += params->ssid_len; | ||
1622 | /* Fake supported basic rates IE */ | ||
1623 | *fake++ = WLAN_EID_SUPP_RATES; | ||
1624 | *fake++ = 4; | ||
1625 | *fake++ = 0x82; | ||
1626 | *fake++ = 0x84; | ||
1627 | *fake++ = 0x8b; | ||
1628 | *fake++ = 0x96; | ||
1629 | /* Fake DS channel IE */ | ||
1630 | *fake++ = WLAN_EID_DS_PARAMS; | ||
1631 | *fake++ = 1; | ||
1632 | *fake++ = params->channel->hw_value; | ||
1633 | /* Fake IBSS params IE */ | ||
1634 | *fake++ = WLAN_EID_IBSS_PARAMS; | ||
1635 | *fake++ = 2; | ||
1636 | *fake++ = 0; /* ATIM=0 */ | ||
1637 | *fake++ = 0; | ||
1638 | /* Fake extended rates IE, TODO: don't add this for 802.11b only, | ||
1639 | * but I don't know how this could be checked */ | ||
1640 | *fake++ = WLAN_EID_EXT_SUPP_RATES; | ||
1641 | *fake++ = 8; | ||
1642 | *fake++ = 0x0c; | ||
1643 | *fake++ = 0x12; | ||
1644 | *fake++ = 0x18; | ||
1645 | *fake++ = 0x24; | ||
1646 | *fake++ = 0x30; | ||
1647 | *fake++ = 0x48; | ||
1648 | *fake++ = 0x60; | ||
1649 | *fake++ = 0x6c; | ||
1650 | lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie); | ||
1651 | |||
1652 | cfg80211_inform_bss(priv->wdev->wiphy, | ||
1653 | params->channel, | ||
1654 | bssid, | ||
1655 | 0, | ||
1656 | capability, | ||
1657 | params->beacon_interval, | ||
1658 | fake_ie, fake - fake_ie, | ||
1659 | 0, GFP_KERNEL); | ||
1660 | |||
1661 | memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); | ||
1662 | priv->wdev->ssid_len = params->ssid_len; | ||
1663 | |||
1664 | cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL); | ||
1665 | |||
1666 | /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */ | ||
1667 | priv->connect_status = LBS_CONNECTED; | ||
1668 | netif_carrier_on(priv->dev); | ||
1669 | if (!priv->tx_pending_len) | ||
1670 | netif_wake_queue(priv->dev); | ||
1671 | |||
1672 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
1673 | } | ||
1674 | |||
1675 | static int lbs_ibss_join_existing(struct lbs_private *priv, | ||
1676 | struct cfg80211_ibss_params *params, | ||
1677 | struct cfg80211_bss *bss) | ||
1678 | { | ||
1679 | const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | ||
1680 | struct cmd_ds_802_11_ad_hoc_join cmd; | ||
1681 | u8 preamble = RADIO_PREAMBLE_SHORT; | ||
1682 | int ret = 0; | ||
1683 | |||
1684 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1685 | |||
1686 | /* TODO: set preamble based on scan result */ | ||
1687 | ret = lbs_set_radio(priv, preamble, 1); | ||
1688 | if (ret) | ||
1689 | goto out; | ||
1690 | |||
1691 | /* | ||
1692 | * Example CMD_802_11_AD_HOC_JOIN command: | ||
1693 | * | ||
1694 | * command 2c 00 CMD_802_11_AD_HOC_JOIN | ||
1695 | * size 65 00 | ||
1696 | * sequence xx xx | ||
1697 | * result 00 00 | ||
1698 | * bssid 02 27 27 97 2f 96 | ||
1699 | * ssid 49 42 53 53 00 00 00 00 | ||
1700 | * 00 00 00 00 00 00 00 00 | ||
1701 | * 00 00 00 00 00 00 00 00 | ||
1702 | * 00 00 00 00 00 00 00 00 | ||
1703 | * type 02 CMD_BSS_TYPE_IBSS | ||
1704 | * beacon period 64 00 | ||
1705 | * dtim period 00 | ||
1706 | * timestamp 00 00 00 00 00 00 00 00 | ||
1707 | * localtime 00 00 00 00 00 00 00 00 | ||
1708 | * IE DS 03 | ||
1709 | * IE DS len 01 | ||
1710 | * IE DS channel 01 | ||
1711 | * reserveed 00 00 00 00 | ||
1712 | * IE IBSS 06 | ||
1713 | * IE IBSS len 02 | ||
1714 | * IE IBSS atim 00 00 | ||
1715 | * reserved 00 00 00 00 | ||
1716 | * capability 02 00 | ||
1717 | * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c 00 | ||
1718 | * fail timeout ff 00 | ||
1719 | * probe delay 00 00 | ||
1720 | */ | ||
1721 | memset(&cmd, 0, sizeof(cmd)); | ||
1722 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1723 | |||
1724 | memcpy(cmd.bss.bssid, bss->bssid, ETH_ALEN); | ||
1725 | memcpy(cmd.bss.ssid, params->ssid, params->ssid_len); | ||
1726 | cmd.bss.type = CMD_BSS_TYPE_IBSS; | ||
1727 | cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval); | ||
1728 | cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS; | ||
1729 | cmd.bss.ds.header.len = 1; | ||
1730 | cmd.bss.ds.channel = params->channel->hw_value; | ||
1731 | cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS; | ||
1732 | cmd.bss.ibss.header.len = 2; | ||
1733 | cmd.bss.ibss.atimwindow = 0; | ||
1734 | cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); | ||
1735 | |||
1736 | /* set rates to the intersection of our rates and the rates in the | ||
1737 | bss */ | ||
1738 | if (!rates_eid) { | ||
1739 | lbs_add_rates(cmd.bss.rates); | ||
1740 | } else { | ||
1741 | int hw, i; | ||
1742 | u8 rates_max = rates_eid[1]; | ||
1743 | u8 *rates = cmd.bss.rates; | ||
1744 | for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { | ||
1745 | u8 hw_rate = lbs_rates[hw].bitrate / 5; | ||
1746 | for (i = 0; i < rates_max; i++) { | ||
1747 | if (hw_rate == (rates_eid[i+2] & 0x7f)) { | ||
1748 | u8 rate = rates_eid[i+2]; | ||
1749 | if (rate == 0x02 || rate == 0x04 || | ||
1750 | rate == 0x0b || rate == 0x16) | ||
1751 | rate |= 0x80; | ||
1752 | *rates++ = rate; | ||
1753 | } | ||
1754 | } | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1758 | /* Only v8 and below support setting this */ | ||
1759 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { | ||
1760 | cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); | ||
1761 | cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
1762 | } | ||
1763 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); | ||
1764 | if (ret) | ||
1765 | goto out; | ||
1766 | |||
1767 | /* | ||
1768 | * This is a sample response to CMD_802_11_AD_HOC_JOIN: | ||
1769 | * | ||
1770 | * response 2c 80 | ||
1771 | * size 09 00 | ||
1772 | * sequence xx xx | ||
1773 | * result 00 00 | ||
1774 | * reserved 00 | ||
1775 | */ | ||
1776 | lbs_join_post(priv, params, bss->bssid, bss->capability); | ||
1777 | |||
1778 | out: | ||
1779 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1780 | return ret; | ||
1781 | } | ||
1782 | |||
1783 | |||
1784 | |||
1785 | static int lbs_ibss_start_new(struct lbs_private *priv, | ||
1786 | struct cfg80211_ibss_params *params) | ||
1787 | { | ||
1788 | struct cmd_ds_802_11_ad_hoc_start cmd; | ||
1789 | struct cmd_ds_802_11_ad_hoc_result *resp = | ||
1790 | (struct cmd_ds_802_11_ad_hoc_result *) &cmd; | ||
1791 | u8 preamble = RADIO_PREAMBLE_SHORT; | ||
1792 | int ret = 0; | ||
1793 | u16 capability; | ||
1794 | |||
1795 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1796 | |||
1797 | ret = lbs_set_radio(priv, preamble, 1); | ||
1798 | if (ret) | ||
1799 | goto out; | ||
1800 | |||
1801 | /* | ||
1802 | * Example CMD_802_11_AD_HOC_START command: | ||
1803 | * | ||
1804 | * command 2b 00 CMD_802_11_AD_HOC_START | ||
1805 | * size b1 00 | ||
1806 | * sequence xx xx | ||
1807 | * result 00 00 | ||
1808 | * ssid 54 45 53 54 00 00 00 00 | ||
1809 | * 00 00 00 00 00 00 00 00 | ||
1810 | * 00 00 00 00 00 00 00 00 | ||
1811 | * 00 00 00 00 00 00 00 00 | ||
1812 | * bss type 02 | ||
1813 | * beacon period 64 00 | ||
1814 | * dtim period 00 | ||
1815 | * IE IBSS 06 | ||
1816 | * IE IBSS len 02 | ||
1817 | * IE IBSS atim 00 00 | ||
1818 | * reserved 00 00 00 00 | ||
1819 | * IE DS 03 | ||
1820 | * IE DS len 01 | ||
1821 | * IE DS channel 01 | ||
1822 | * reserved 00 00 00 00 | ||
1823 | * probe delay 00 00 | ||
1824 | * capability 02 00 | ||
1825 | * rates 82 84 8b 96 (basic rates with have bit 7 set) | ||
1826 | * 0c 12 18 24 30 48 60 6c | ||
1827 | * padding 100 bytes | ||
1828 | */ | ||
1829 | memset(&cmd, 0, sizeof(cmd)); | ||
1830 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1831 | memcpy(cmd.ssid, params->ssid, params->ssid_len); | ||
1832 | cmd.bsstype = CMD_BSS_TYPE_IBSS; | ||
1833 | cmd.beaconperiod = cpu_to_le16(params->beacon_interval); | ||
1834 | cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; | ||
1835 | cmd.ibss.header.len = 2; | ||
1836 | cmd.ibss.atimwindow = 0; | ||
1837 | cmd.ds.header.id = WLAN_EID_DS_PARAMS; | ||
1838 | cmd.ds.header.len = 1; | ||
1839 | cmd.ds.channel = params->channel->hw_value; | ||
1840 | /* Only v8 and below support setting probe delay */ | ||
1841 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) | ||
1842 | cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
1843 | /* TODO: mix in WLAN_CAPABILITY_PRIVACY */ | ||
1844 | capability = WLAN_CAPABILITY_IBSS; | ||
1845 | cmd.capability = cpu_to_le16(capability); | ||
1846 | lbs_add_rates(cmd.rates); | ||
1847 | |||
1848 | |||
1849 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); | ||
1850 | if (ret) | ||
1851 | goto out; | ||
1852 | |||
1853 | /* | ||
1854 | * This is a sample response to CMD_802_11_AD_HOC_JOIN: | ||
1855 | * | ||
1856 | * response 2b 80 | ||
1857 | * size 14 00 | ||
1858 | * sequence xx xx | ||
1859 | * result 00 00 | ||
1860 | * reserved 00 | ||
1861 | * bssid 02 2b 7b 0f 86 0e | ||
1862 | */ | ||
1863 | lbs_join_post(priv, params, resp->bssid, capability); | ||
1864 | |||
1865 | out: | ||
1866 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1867 | return ret; | ||
1868 | } | ||
1869 | |||
1870 | |||
1871 | static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, | ||
1872 | struct cfg80211_ibss_params *params) | ||
1873 | { | ||
1874 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1875 | int ret = 0; | ||
1876 | struct cfg80211_bss *bss; | ||
1877 | DECLARE_SSID_BUF(ssid_buf); | ||
1878 | |||
1879 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1880 | |||
1881 | if (!params->channel) { | ||
1882 | ret = -ENOTSUPP; | ||
1883 | goto out; | ||
1884 | } | ||
1885 | |||
1886 | ret = lbs_set_channel(priv, params->channel->hw_value); | ||
1887 | if (ret) | ||
1888 | goto out; | ||
1889 | |||
1890 | /* Search if someone is beaconing. This assumes that the | ||
1891 | * bss list is populated already */ | ||
1892 | bss = cfg80211_get_bss(wiphy, params->channel, params->bssid, | ||
1893 | params->ssid, params->ssid_len, | ||
1894 | WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); | ||
1895 | |||
1896 | if (bss) { | ||
1897 | ret = lbs_ibss_join_existing(priv, params, bss); | ||
1898 | cfg80211_put_bss(bss); | ||
1899 | } else | ||
1900 | ret = lbs_ibss_start_new(priv, params); | ||
1901 | |||
1902 | |||
1903 | out: | ||
1904 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1905 | return ret; | ||
1906 | } | ||
1907 | |||
1908 | |||
1909 | static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | ||
1910 | { | ||
1911 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
1912 | struct cmd_ds_802_11_ad_hoc_stop cmd; | ||
1913 | int ret = 0; | ||
1914 | |||
1915 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1916 | |||
1917 | memset(&cmd, 0, sizeof(cmd)); | ||
1918 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
1919 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd); | ||
1920 | |||
1921 | /* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */ | ||
1922 | lbs_mac_event_disconnected(priv); | ||
1923 | |||
1924 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
1925 | return ret; | ||
1926 | } | ||
1927 | |||
1928 | |||
1929 | |||
1930 | |||
1931 | /*************************************************************************** | ||
1932 | * Initialization | ||
1933 | */ | ||
1934 | |||
104 | static struct cfg80211_ops lbs_cfg80211_ops = { | 1935 | static struct cfg80211_ops lbs_cfg80211_ops = { |
105 | .set_channel = lbs_cfg_set_channel, | 1936 | .set_channel = lbs_cfg_set_channel, |
1937 | .scan = lbs_cfg_scan, | ||
1938 | .connect = lbs_cfg_connect, | ||
1939 | .disconnect = lbs_cfg_disconnect, | ||
1940 | .add_key = lbs_cfg_add_key, | ||
1941 | .del_key = lbs_cfg_del_key, | ||
1942 | .set_default_key = lbs_cfg_set_default_key, | ||
1943 | .get_station = lbs_cfg_get_station, | ||
1944 | .dump_survey = lbs_get_survey, | ||
1945 | .change_virtual_intf = lbs_change_intf, | ||
1946 | .join_ibss = lbs_join_ibss, | ||
1947 | .leave_ibss = lbs_leave_ibss, | ||
106 | }; | 1948 | }; |
107 | 1949 | ||
108 | 1950 | ||
@@ -142,6 +1984,36 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev) | |||
142 | } | 1984 | } |
143 | 1985 | ||
144 | 1986 | ||
1987 | static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv) | ||
1988 | { | ||
1989 | struct region_code_mapping { | ||
1990 | const char *cn; | ||
1991 | int code; | ||
1992 | }; | ||
1993 | |||
1994 | /* Section 5.17.2 */ | ||
1995 | static struct region_code_mapping regmap[] = { | ||
1996 | {"US ", 0x10}, /* US FCC */ | ||
1997 | {"CA ", 0x20}, /* Canada */ | ||
1998 | {"EU ", 0x30}, /* ETSI */ | ||
1999 | {"ES ", 0x31}, /* Spain */ | ||
2000 | {"FR ", 0x32}, /* France */ | ||
2001 | {"JP ", 0x40}, /* Japan */ | ||
2002 | }; | ||
2003 | size_t i; | ||
2004 | |||
2005 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
2006 | |||
2007 | for (i = 0; i < ARRAY_SIZE(regmap); i++) | ||
2008 | if (regmap[i].code == priv->regioncode) { | ||
2009 | regulatory_hint(priv->wdev->wiphy, regmap[i].cn); | ||
2010 | break; | ||
2011 | } | ||
2012 | |||
2013 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
2014 | } | ||
2015 | |||
2016 | |||
145 | /* | 2017 | /* |
146 | * This function get's called after lbs_setup_firmware() determined the | 2018 | * This function get's called after lbs_setup_firmware() determined the |
147 | * firmware capabities. So we can setup the wiphy according to our | 2019 | * firmware capabities. So we can setup the wiphy according to our |
@@ -157,10 +2029,12 @@ int lbs_cfg_register(struct lbs_private *priv) | |||
157 | wdev->wiphy->max_scan_ssids = 1; | 2029 | wdev->wiphy->max_scan_ssids = 1; |
158 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 2030 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
159 | 2031 | ||
160 | /* TODO: BIT(NL80211_IFTYPE_ADHOC); */ | 2032 | wdev->wiphy->interface_modes = |
161 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 2033 | BIT(NL80211_IFTYPE_STATION) | |
2034 | BIT(NL80211_IFTYPE_ADHOC); | ||
2035 | if (lbs_rtap_supported(priv)) | ||
2036 | wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | ||
162 | 2037 | ||
163 | /* TODO: honor priv->regioncode */ | ||
164 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; | 2038 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; |
165 | 2039 | ||
166 | /* | 2040 | /* |
@@ -169,6 +2043,7 @@ int lbs_cfg_register(struct lbs_private *priv) | |||
169 | */ | 2043 | */ |
170 | wdev->wiphy->cipher_suites = cipher_suites; | 2044 | wdev->wiphy->cipher_suites = cipher_suites; |
171 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 2045 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
2046 | wdev->wiphy->reg_notifier = lbs_reg_notifier; | ||
172 | 2047 | ||
173 | ret = wiphy_register(wdev->wiphy); | 2048 | ret = wiphy_register(wdev->wiphy); |
174 | if (ret < 0) | 2049 | if (ret < 0) |
@@ -180,10 +2055,129 @@ int lbs_cfg_register(struct lbs_private *priv) | |||
180 | if (ret) | 2055 | if (ret) |
181 | lbs_pr_err("cannot register network device\n"); | 2056 | lbs_pr_err("cannot register network device\n"); |
182 | 2057 | ||
2058 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | ||
2059 | |||
2060 | lbs_cfg_set_regulatory_hint(priv); | ||
2061 | |||
183 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 2062 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
184 | return ret; | 2063 | return ret; |
185 | } | 2064 | } |
186 | 2065 | ||
2066 | /** | ||
2067 | * @brief This function sets DOMAIN INFO to FW | ||
2068 | * @param priv pointer to struct lbs_private | ||
2069 | * @return 0; -1 | ||
2070 | */ | ||
2071 | static int lbs_11d_set_domain_info(struct lbs_private *priv) | ||
2072 | { | ||
2073 | int ret; | ||
2074 | |||
2075 | ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO, | ||
2076 | CMD_ACT_SET, | ||
2077 | CMD_OPTION_WAITFORRSP, 0, NULL); | ||
2078 | if (ret) | ||
2079 | lbs_deb_11d("fail to dnld domain info\n"); | ||
2080 | |||
2081 | return ret; | ||
2082 | } | ||
2083 | |||
2084 | static void lbs_send_domain_info_cmd_fw(struct wiphy *wiphy, | ||
2085 | struct regulatory_request *request) | ||
2086 | { | ||
2087 | u8 no_of_triplet = 0; | ||
2088 | u8 no_of_parsed_chan = 0; | ||
2089 | u8 first_channel = 0, next_chan = 0, max_pwr = 0; | ||
2090 | u8 i, flag = 0; | ||
2091 | enum ieee80211_band band; | ||
2092 | struct ieee80211_supported_band *sband; | ||
2093 | struct ieee80211_channel *ch; | ||
2094 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
2095 | struct lbs_802_11d_domain_reg *domain_info = &priv->domain_reg; | ||
2096 | int ret = 0; | ||
2097 | |||
2098 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
2099 | |||
2100 | /* Set country code */ | ||
2101 | domain_info->country_code[0] = request->alpha2[0]; | ||
2102 | domain_info->country_code[1] = request->alpha2[1]; | ||
2103 | domain_info->country_code[2] = ' '; | ||
2104 | |||
2105 | for (band = 0; band < IEEE80211_NUM_BANDS ; band++) { | ||
2106 | |||
2107 | if (!wiphy->bands[band]) | ||
2108 | continue; | ||
2109 | |||
2110 | sband = wiphy->bands[band]; | ||
2111 | |||
2112 | for (i = 0; i < sband->n_channels ; i++) { | ||
2113 | ch = &sband->channels[i]; | ||
2114 | if (ch->flags & IEEE80211_CHAN_DISABLED) | ||
2115 | continue; | ||
2116 | |||
2117 | if (!flag) { | ||
2118 | flag = 1; | ||
2119 | next_chan = first_channel = (u32) ch->hw_value; | ||
2120 | max_pwr = ch->max_power; | ||
2121 | no_of_parsed_chan = 1; | ||
2122 | continue; | ||
2123 | } | ||
2124 | |||
2125 | if (ch->hw_value == next_chan + 1 && | ||
2126 | ch->max_power == max_pwr) { | ||
2127 | next_chan++; | ||
2128 | no_of_parsed_chan++; | ||
2129 | } else { | ||
2130 | domain_info->triplet[no_of_triplet] | ||
2131 | .chans.first_channel = first_channel; | ||
2132 | domain_info->triplet[no_of_triplet] | ||
2133 | .chans.num_channels = no_of_parsed_chan; | ||
2134 | domain_info->triplet[no_of_triplet] | ||
2135 | .chans.max_power = max_pwr; | ||
2136 | no_of_triplet++; | ||
2137 | flag = 0; | ||
2138 | } | ||
2139 | } | ||
2140 | if (flag) { | ||
2141 | domain_info->triplet[no_of_triplet] | ||
2142 | .chans.first_channel = first_channel; | ||
2143 | domain_info->triplet[no_of_triplet] | ||
2144 | .chans.num_channels = no_of_parsed_chan; | ||
2145 | domain_info->triplet[no_of_triplet] | ||
2146 | .chans.max_power = max_pwr; | ||
2147 | no_of_triplet++; | ||
2148 | } | ||
2149 | } | ||
2150 | |||
2151 | domain_info->no_triplet = no_of_triplet; | ||
2152 | |||
2153 | /* Set domain info */ | ||
2154 | ret = lbs_11d_set_domain_info(priv); | ||
2155 | if (ret) | ||
2156 | lbs_pr_err("11D: error setting domain info in FW\n"); | ||
2157 | |||
2158 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
2159 | } | ||
2160 | |||
2161 | int lbs_reg_notifier(struct wiphy *wiphy, | ||
2162 | struct regulatory_request *request) | ||
2163 | { | ||
2164 | lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain " | ||
2165 | "callback for domain %c%c\n", request->alpha2[0], | ||
2166 | request->alpha2[1]); | ||
2167 | |||
2168 | lbs_send_domain_info_cmd_fw(wiphy, request); | ||
2169 | |||
2170 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
2171 | |||
2172 | return 0; | ||
2173 | } | ||
2174 | |||
2175 | void lbs_scan_deinit(struct lbs_private *priv) | ||
2176 | { | ||
2177 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
2178 | cancel_delayed_work_sync(&priv->scan_work); | ||
2179 | } | ||
2180 | |||
187 | 2181 | ||
188 | void lbs_cfg_free(struct lbs_private *priv) | 2182 | void lbs_cfg_free(struct lbs_private *priv) |
189 | { | 2183 | { |
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h index e09a193a34d6..756fb98f9f05 100644 --- a/drivers/net/wireless/libertas/cfg.h +++ b/drivers/net/wireless/libertas/cfg.h | |||
@@ -1,16 +1,27 @@ | |||
1 | #ifndef __LBS_CFG80211_H__ | 1 | #ifndef __LBS_CFG80211_H__ |
2 | #define __LBS_CFG80211_H__ | 2 | #define __LBS_CFG80211_H__ |
3 | 3 | ||
4 | #include "dev.h" | 4 | struct device; |
5 | struct lbs_private; | ||
6 | struct regulatory_request; | ||
7 | struct wiphy; | ||
5 | 8 | ||
6 | struct wireless_dev *lbs_cfg_alloc(struct device *dev); | 9 | struct wireless_dev *lbs_cfg_alloc(struct device *dev); |
7 | int lbs_cfg_register(struct lbs_private *priv); | 10 | int lbs_cfg_register(struct lbs_private *priv); |
8 | void lbs_cfg_free(struct lbs_private *priv); | 11 | void lbs_cfg_free(struct lbs_private *priv); |
9 | 12 | ||
10 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | 13 | int lbs_reg_notifier(struct wiphy *wiphy, |
11 | u8 ssid_len); | 14 | struct regulatory_request *request); |
12 | int lbs_scan_networks(struct lbs_private *priv, int full_scan); | ||
13 | void lbs_cfg_scan_worker(struct work_struct *work); | ||
14 | 15 | ||
16 | /* All of those are TODOs: */ | ||
17 | #define lbs_cmd_802_11_rssi(priv, cmdptr) (0) | ||
18 | #define lbs_ret_802_11_rssi(priv, resp) (0) | ||
19 | #define lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action) (0) | ||
20 | #define lbs_ret_802_11_bcn_ctrl(priv, resp) (0) | ||
21 | |||
22 | void lbs_send_disconnect_notification(struct lbs_private *priv); | ||
23 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); | ||
24 | |||
25 | void lbs_scan_deinit(struct lbs_private *priv); | ||
15 | 26 | ||
16 | #endif | 27 | #endif |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index cdb9b9650d73..6c8a9d952a01 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -7,13 +7,8 @@ | |||
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
9 | 9 | ||
10 | #include "host.h" | ||
11 | #include "decl.h" | 10 | #include "decl.h" |
12 | #include "defs.h" | 11 | #include "cfg.h" |
13 | #include "dev.h" | ||
14 | #include "assoc.h" | ||
15 | #include "wext.h" | ||
16 | #include "scan.h" | ||
17 | #include "cmd.h" | 12 | #include "cmd.h" |
18 | 13 | ||
19 | 14 | ||
@@ -70,6 +65,8 @@ static u8 is_command_allowed_in_ps(u16 cmd) | |||
70 | switch (cmd) { | 65 | switch (cmd) { |
71 | case CMD_802_11_RSSI: | 66 | case CMD_802_11_RSSI: |
72 | return 1; | 67 | return 1; |
68 | case CMD_802_11_HOST_SLEEP_CFG: | ||
69 | return 1; | ||
73 | default: | 70 | default: |
74 | break; | 71 | break; |
75 | } | 72 | } |
@@ -175,16 +172,28 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
175 | if (priv->mesh_dev) | 172 | if (priv->mesh_dev) |
176 | memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); | 173 | memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); |
177 | 174 | ||
178 | if (lbs_set_regiontable(priv, priv->regioncode, 0)) { | ||
179 | ret = -1; | ||
180 | goto out; | ||
181 | } | ||
182 | |||
183 | out: | 175 | out: |
184 | lbs_deb_leave(LBS_DEB_CMD); | 176 | lbs_deb_leave(LBS_DEB_CMD); |
185 | return ret; | 177 | return ret; |
186 | } | 178 | } |
187 | 179 | ||
180 | static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy, | ||
181 | struct cmd_header *resp) | ||
182 | { | ||
183 | lbs_deb_enter(LBS_DEB_CMD); | ||
184 | if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { | ||
185 | priv->is_host_sleep_configured = 0; | ||
186 | if (priv->psstate == PS_STATE_FULL_POWER) { | ||
187 | priv->is_host_sleep_activated = 0; | ||
188 | wake_up_interruptible(&priv->host_sleep_q); | ||
189 | } | ||
190 | } else { | ||
191 | priv->is_host_sleep_configured = 1; | ||
192 | } | ||
193 | lbs_deb_leave(LBS_DEB_CMD); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
188 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | 197 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, |
189 | struct wol_config *p_wol_config) | 198 | struct wol_config *p_wol_config) |
190 | { | 199 | { |
@@ -202,12 +211,11 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | |||
202 | else | 211 | else |
203 | cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; | 212 | cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; |
204 | 213 | ||
205 | ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); | 214 | ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr, |
215 | le16_to_cpu(cmd_config.hdr.size), | ||
216 | lbs_ret_host_sleep_cfg, 0); | ||
206 | if (!ret) { | 217 | if (!ret) { |
207 | if (criteria) { | 218 | if (p_wol_config) |
208 | lbs_deb_cmd("Set WOL criteria to %x\n", criteria); | ||
209 | priv->wol_criteria = criteria; | ||
210 | } else | ||
211 | memcpy((uint8_t *) p_wol_config, | 219 | memcpy((uint8_t *) p_wol_config, |
212 | (uint8_t *)&cmd_config.wol_conf, | 220 | (uint8_t *)&cmd_config.wol_conf, |
213 | sizeof(struct wol_config)); | 221 | sizeof(struct wol_config)); |
@@ -712,6 +720,10 @@ static void lbs_queue_cmd(struct lbs_private *priv, | |||
712 | } | 720 | } |
713 | } | 721 | } |
714 | 722 | ||
723 | if (le16_to_cpu(cmdnode->cmdbuf->command) == | ||
724 | CMD_802_11_WAKEUP_CONFIRM) | ||
725 | addtail = 0; | ||
726 | |||
715 | spin_lock_irqsave(&priv->driver_lock, flags); | 727 | spin_lock_irqsave(&priv->driver_lock, flags); |
716 | 728 | ||
717 | if (addtail) | 729 | if (addtail) |
@@ -887,6 +899,66 @@ void lbs_set_mac_control(struct lbs_private *priv) | |||
887 | } | 899 | } |
888 | 900 | ||
889 | /** | 901 | /** |
902 | * @brief This function implements command CMD_802_11D_DOMAIN_INFO | ||
903 | * @param priv pointer to struct lbs_private | ||
904 | * @param cmd pointer to cmd buffer | ||
905 | * @param cmdno cmd ID | ||
906 | * @param cmdOption cmd action | ||
907 | * @return 0 | ||
908 | */ | ||
909 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
910 | struct cmd_ds_command *cmd, | ||
911 | u16 cmdoption) | ||
912 | { | ||
913 | struct cmd_ds_802_11d_domain_info *pdomaininfo = | ||
914 | &cmd->params.domaininfo; | ||
915 | struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; | ||
916 | u8 nr_triplet = priv->domain_reg.no_triplet; | ||
917 | |||
918 | lbs_deb_enter(LBS_DEB_11D); | ||
919 | |||
920 | lbs_deb_11d("nr_triplet=%x\n", nr_triplet); | ||
921 | |||
922 | pdomaininfo->action = cpu_to_le16(cmdoption); | ||
923 | if (cmdoption == CMD_ACT_GET) { | ||
924 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
925 | sizeof(struct cmd_header)); | ||
926 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, | ||
927 | le16_to_cpu(cmd->size)); | ||
928 | goto done; | ||
929 | } | ||
930 | |||
931 | domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); | ||
932 | memcpy(domain->countrycode, priv->domain_reg.country_code, | ||
933 | sizeof(domain->countrycode)); | ||
934 | |||
935 | domain->header.len = cpu_to_le16(nr_triplet | ||
936 | * sizeof(struct ieee80211_country_ie_triplet) | ||
937 | + sizeof(domain->countrycode)); | ||
938 | |||
939 | if (nr_triplet) { | ||
940 | memcpy(domain->triplet, priv->domain_reg.triplet, | ||
941 | nr_triplet * | ||
942 | sizeof(struct ieee80211_country_ie_triplet)); | ||
943 | |||
944 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
945 | le16_to_cpu(domain->header.len) + | ||
946 | sizeof(struct mrvl_ie_header) + | ||
947 | sizeof(struct cmd_header)); | ||
948 | } else { | ||
949 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
950 | sizeof(struct cmd_header)); | ||
951 | } | ||
952 | |||
953 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, | ||
954 | le16_to_cpu(cmd->size)); | ||
955 | |||
956 | done: | ||
957 | lbs_deb_enter(LBS_DEB_11D); | ||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | /** | ||
890 | * @brief This function prepare the command before send to firmware. | 962 | * @brief This function prepare the command before send to firmware. |
891 | * | 963 | * |
892 | * @param priv A pointer to struct lbs_private structure | 964 | * @param priv A pointer to struct lbs_private structure |
@@ -984,6 +1056,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
984 | ret = 0; | 1056 | ret = 0; |
985 | goto done; | 1057 | goto done; |
986 | 1058 | ||
1059 | case CMD_802_11D_DOMAIN_INFO: | ||
1060 | cmdptr->command = cpu_to_le16(cmd_no); | ||
1061 | ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action); | ||
1062 | break; | ||
1063 | |||
987 | case CMD_802_11_TPC_CFG: | 1064 | case CMD_802_11_TPC_CFG: |
988 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); | 1065 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); |
989 | cmdptr->size = | 1066 | cmdptr->size = |
@@ -1303,6 +1380,15 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1303 | * check if in power save mode, if yes, put the device back | 1380 | * check if in power save mode, if yes, put the device back |
1304 | * to PS mode | 1381 | * to PS mode |
1305 | */ | 1382 | */ |
1383 | #ifdef TODO | ||
1384 | /* | ||
1385 | * This was the old code for libertas+wext. Someone that | ||
1386 | * understands this beast should re-code it in a sane way. | ||
1387 | * | ||
1388 | * I actually don't understand why this is related to WPA | ||
1389 | * and to connection status, shouldn't powering should be | ||
1390 | * independ of such things? | ||
1391 | */ | ||
1306 | if ((priv->psmode != LBS802_11POWERMODECAM) && | 1392 | if ((priv->psmode != LBS802_11POWERMODECAM) && |
1307 | (priv->psstate == PS_STATE_FULL_POWER) && | 1393 | (priv->psstate == PS_STATE_FULL_POWER) && |
1308 | ((priv->connect_status == LBS_CONNECTED) || | 1394 | ((priv->connect_status == LBS_CONNECTED) || |
@@ -1324,6 +1410,7 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1324 | lbs_ps_sleep(priv, 0); | 1410 | lbs_ps_sleep(priv, 0); |
1325 | } | 1411 | } |
1326 | } | 1412 | } |
1413 | #endif | ||
1327 | } | 1414 | } |
1328 | 1415 | ||
1329 | ret = 0; | 1416 | ret = 0; |
@@ -1353,6 +1440,11 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) | |||
1353 | /* We don't get a response on the sleep-confirmation */ | 1440 | /* We don't get a response on the sleep-confirmation */ |
1354 | priv->dnld_sent = DNLD_RES_RECEIVED; | 1441 | priv->dnld_sent = DNLD_RES_RECEIVED; |
1355 | 1442 | ||
1443 | if (priv->is_host_sleep_configured) { | ||
1444 | priv->is_host_sleep_activated = 1; | ||
1445 | wake_up_interruptible(&priv->host_sleep_q); | ||
1446 | } | ||
1447 | |||
1356 | /* If nothing to do, go back to sleep (?) */ | 1448 | /* If nothing to do, go back to sleep (?) */ |
1357 | if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) | 1449 | if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) |
1358 | priv->psstate = PS_STATE_SLEEP; | 1450 | priv->psstate = PS_STATE_SLEEP; |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 88f7131d66e9..a0d9482ef5e2 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -5,18 +5,11 @@ | |||
5 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/if_arp.h> | ||
9 | #include <linux/netdevice.h> | ||
10 | #include <asm/unaligned.h> | 8 | #include <asm/unaligned.h> |
11 | #include <net/iw_handler.h> | 9 | #include <net/cfg80211.h> |
12 | 10 | ||
13 | #include "host.h" | 11 | #include "cfg.h" |
14 | #include "decl.h" | ||
15 | #include "cmd.h" | 12 | #include "cmd.h" |
16 | #include "defs.h" | ||
17 | #include "dev.h" | ||
18 | #include "assoc.h" | ||
19 | #include "wext.h" | ||
20 | 13 | ||
21 | /** | 14 | /** |
22 | * @brief This function handles disconnect event. it | 15 | * @brief This function handles disconnect event. it |
@@ -38,7 +31,9 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) | |||
38 | * It causes problem in the Supplicant | 31 | * It causes problem in the Supplicant |
39 | */ | 32 | */ |
40 | msleep_interruptible(1000); | 33 | msleep_interruptible(1000); |
41 | lbs_send_disconnect_notification(priv); | 34 | |
35 | if (priv->wdev->iftype == NL80211_IFTYPE_STATION) | ||
36 | lbs_send_disconnect_notification(priv); | ||
42 | 37 | ||
43 | /* report disconnect to upper layer */ | 38 | /* report disconnect to upper layer */ |
44 | netif_stop_queue(priv->dev); | 39 | netif_stop_queue(priv->dev); |
@@ -49,23 +44,8 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) | |||
49 | priv->currenttxskb = NULL; | 44 | priv->currenttxskb = NULL; |
50 | priv->tx_pending_len = 0; | 45 | priv->tx_pending_len = 0; |
51 | 46 | ||
52 | /* reset SNR/NF/RSSI values */ | ||
53 | memset(priv->SNR, 0x00, sizeof(priv->SNR)); | ||
54 | memset(priv->NF, 0x00, sizeof(priv->NF)); | ||
55 | memset(priv->RSSI, 0x00, sizeof(priv->RSSI)); | ||
56 | memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); | ||
57 | memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); | ||
58 | priv->nextSNRNF = 0; | ||
59 | priv->numSNRNF = 0; | ||
60 | priv->connect_status = LBS_DISCONNECTED; | 47 | priv->connect_status = LBS_DISCONNECTED; |
61 | 48 | ||
62 | /* Clear out associated SSID and BSSID since connection is | ||
63 | * no longer valid. | ||
64 | */ | ||
65 | memset(&priv->curbssparams.bssid, 0, ETH_ALEN); | ||
66 | memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN); | ||
67 | priv->curbssparams.ssid_len = 0; | ||
68 | |||
69 | if (priv->psstate != PS_STATE_FULL_POWER) { | 49 | if (priv->psstate != PS_STATE_FULL_POWER) { |
70 | /* make firmware to exit PS mode */ | 50 | /* make firmware to exit PS mode */ |
71 | lbs_deb_cmd("disconnected, so exit PS mode\n"); | 51 | lbs_deb_cmd("disconnected, so exit PS mode\n"); |
@@ -117,6 +97,52 @@ static int lbs_ret_reg_access(struct lbs_private *priv, | |||
117 | return ret; | 97 | return ret; |
118 | } | 98 | } |
119 | 99 | ||
100 | /** | ||
101 | * @brief This function parses countryinfo from AP and download country info to FW | ||
102 | * @param priv pointer to struct lbs_private | ||
103 | * @param resp pointer to command response buffer | ||
104 | * @return 0; -1 | ||
105 | */ | ||
106 | static int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) | ||
107 | { | ||
108 | struct cmd_ds_802_11d_domain_info *domaininfo = | ||
109 | &resp->params.domaininforesp; | ||
110 | struct mrvl_ie_domain_param_set *domain = &domaininfo->domain; | ||
111 | u16 action = le16_to_cpu(domaininfo->action); | ||
112 | s16 ret = 0; | ||
113 | u8 nr_triplet = 0; | ||
114 | |||
115 | lbs_deb_enter(LBS_DEB_11D); | ||
116 | |||
117 | lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp, | ||
118 | (int)le16_to_cpu(resp->size)); | ||
119 | |||
120 | nr_triplet = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / | ||
121 | sizeof(struct ieee80211_country_ie_triplet); | ||
122 | |||
123 | lbs_deb_11d("domain info resp: nr_triplet %d\n", nr_triplet); | ||
124 | |||
125 | if (nr_triplet > MRVDRV_MAX_TRIPLET_802_11D) { | ||
126 | lbs_deb_11d("invalid number of triplets returned!!\n"); | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | switch (action) { | ||
131 | case CMD_ACT_SET: /*Proc set action */ | ||
132 | break; | ||
133 | |||
134 | case CMD_ACT_GET: | ||
135 | break; | ||
136 | default: | ||
137 | lbs_deb_11d("invalid action:%d\n", domaininfo->action); | ||
138 | ret = -1; | ||
139 | break; | ||
140 | } | ||
141 | |||
142 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
120 | static inline int handle_cmd_response(struct lbs_private *priv, | 146 | static inline int handle_cmd_response(struct lbs_private *priv, |
121 | struct cmd_header *cmd_response) | 147 | struct cmd_header *cmd_response) |
122 | { | 148 | { |
@@ -150,6 +176,10 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
150 | ret = lbs_ret_802_11_rssi(priv, resp); | 176 | ret = lbs_ret_802_11_rssi(priv, resp); |
151 | break; | 177 | break; |
152 | 178 | ||
179 | case CMD_RET(CMD_802_11D_DOMAIN_INFO): | ||
180 | ret = lbs_ret_802_11d_domain_info(resp); | ||
181 | break; | ||
182 | |||
153 | case CMD_RET(CMD_802_11_TPC_CFG): | 183 | case CMD_RET(CMD_802_11_TPC_CFG): |
154 | spin_lock_irqsave(&priv->driver_lock, flags); | 184 | spin_lock_irqsave(&priv->driver_lock, flags); |
155 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, | 185 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, |
@@ -261,7 +291,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) | |||
261 | * ad-hoc mode. It takes place in | 291 | * ad-hoc mode. It takes place in |
262 | * lbs_execute_next_command(). | 292 | * lbs_execute_next_command(). |
263 | */ | 293 | */ |
264 | if (priv->mode == IW_MODE_ADHOC && | 294 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR && |
265 | action == CMD_SUBCMD_ENTER_PS) | 295 | action == CMD_SUBCMD_ENTER_PS) |
266 | priv->psmode = LBS802_11POWERMODECAM; | 296 | priv->psmode = LBS802_11POWERMODECAM; |
267 | } else if (action == CMD_SUBCMD_ENTER_PS) { | 297 | } else if (action == CMD_SUBCMD_ENTER_PS) { |
@@ -341,32 +371,10 @@ done: | |||
341 | return ret; | 371 | return ret; |
342 | } | 372 | } |
343 | 373 | ||
344 | static int lbs_send_confirmwake(struct lbs_private *priv) | ||
345 | { | ||
346 | struct cmd_header cmd; | ||
347 | int ret = 0; | ||
348 | |||
349 | lbs_deb_enter(LBS_DEB_HOST); | ||
350 | |||
351 | cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM); | ||
352 | cmd.size = cpu_to_le16(sizeof(cmd)); | ||
353 | cmd.seqnum = cpu_to_le16(++priv->seqnum); | ||
354 | cmd.result = 0; | ||
355 | |||
356 | lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd, | ||
357 | sizeof(cmd)); | ||
358 | |||
359 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd)); | ||
360 | if (ret) | ||
361 | lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n"); | ||
362 | |||
363 | lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | int lbs_process_event(struct lbs_private *priv, u32 event) | 374 | int lbs_process_event(struct lbs_private *priv, u32 event) |
368 | { | 375 | { |
369 | int ret = 0; | 376 | int ret = 0; |
377 | struct cmd_header cmd; | ||
370 | 378 | ||
371 | lbs_deb_enter(LBS_DEB_CMD); | 379 | lbs_deb_enter(LBS_DEB_CMD); |
372 | 380 | ||
@@ -410,7 +418,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
410 | if (priv->reset_deep_sleep_wakeup) | 418 | if (priv->reset_deep_sleep_wakeup) |
411 | priv->reset_deep_sleep_wakeup(priv); | 419 | priv->reset_deep_sleep_wakeup(priv); |
412 | priv->is_deep_sleep = 0; | 420 | priv->is_deep_sleep = 0; |
413 | lbs_send_confirmwake(priv); | 421 | lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd, |
422 | sizeof(cmd)); | ||
423 | priv->is_host_sleep_activated = 0; | ||
424 | wake_up_interruptible(&priv->host_sleep_q); | ||
414 | break; | 425 | break; |
415 | 426 | ||
416 | case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: | 427 | case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index de2caac11dd6..17367463c855 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -1,18 +1,13 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/dcache.h> | 1 | #include <linux/dcache.h> |
3 | #include <linux/debugfs.h> | 2 | #include <linux/debugfs.h> |
4 | #include <linux/delay.h> | 3 | #include <linux/delay.h> |
5 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
6 | #include <linux/string.h> | 5 | #include <linux/string.h> |
7 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
8 | #include <net/iw_handler.h> | ||
9 | #include <net/lib80211.h> | ||
10 | 7 | ||
11 | #include "dev.h" | ||
12 | #include "decl.h" | 8 | #include "decl.h" |
13 | #include "host.h" | ||
14 | #include "debugfs.h" | ||
15 | #include "cmd.h" | 9 | #include "cmd.h" |
10 | #include "debugfs.h" | ||
16 | 11 | ||
17 | static struct dentry *lbs_dir; | 12 | static struct dentry *lbs_dir; |
18 | static char *szStates[] = { | 13 | static char *szStates[] = { |
@@ -60,51 +55,6 @@ static ssize_t lbs_dev_info(struct file *file, char __user *userbuf, | |||
60 | return res; | 55 | return res; |
61 | } | 56 | } |
62 | 57 | ||
63 | |||
64 | static ssize_t lbs_getscantable(struct file *file, char __user *userbuf, | ||
65 | size_t count, loff_t *ppos) | ||
66 | { | ||
67 | struct lbs_private *priv = file->private_data; | ||
68 | size_t pos = 0; | ||
69 | int numscansdone = 0, res; | ||
70 | unsigned long addr = get_zeroed_page(GFP_KERNEL); | ||
71 | char *buf = (char *)addr; | ||
72 | DECLARE_SSID_BUF(ssid); | ||
73 | struct bss_descriptor * iter_bss; | ||
74 | if (!buf) | ||
75 | return -ENOMEM; | ||
76 | |||
77 | pos += snprintf(buf+pos, len-pos, | ||
78 | "# | ch | rssi | bssid | cap | Qual | SSID\n"); | ||
79 | |||
80 | mutex_lock(&priv->lock); | ||
81 | list_for_each_entry (iter_bss, &priv->network_list, list) { | ||
82 | u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS); | ||
83 | u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY); | ||
84 | u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT); | ||
85 | |||
86 | pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |", | ||
87 | numscansdone, iter_bss->channel, iter_bss->rssi, | ||
88 | iter_bss->bssid); | ||
89 | pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability); | ||
90 | pos += snprintf(buf+pos, len-pos, "%c%c%c |", | ||
91 | ibss ? 'A' : 'I', privacy ? 'P' : ' ', | ||
92 | spectrum_mgmt ? 'S' : ' '); | ||
93 | pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi)); | ||
94 | pos += snprintf(buf+pos, len-pos, " %s\n", | ||
95 | print_ssid(ssid, iter_bss->ssid, | ||
96 | iter_bss->ssid_len)); | ||
97 | |||
98 | numscansdone++; | ||
99 | } | ||
100 | mutex_unlock(&priv->lock); | ||
101 | |||
102 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | ||
103 | |||
104 | free_page(addr); | ||
105 | return res; | ||
106 | } | ||
107 | |||
108 | static ssize_t lbs_sleepparams_write(struct file *file, | 58 | static ssize_t lbs_sleepparams_write(struct file *file, |
109 | const char __user *user_buf, size_t count, | 59 | const char __user *user_buf, size_t count, |
110 | loff_t *ppos) | 60 | loff_t *ppos) |
@@ -723,8 +673,6 @@ struct lbs_debugfs_files { | |||
723 | 673 | ||
724 | static const struct lbs_debugfs_files debugfs_files[] = { | 674 | static const struct lbs_debugfs_files debugfs_files[] = { |
725 | { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, | 675 | { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, |
726 | { "getscantable", 0444, FOPS(lbs_getscantable, | ||
727 | write_file_dummy), }, | ||
728 | { "sleepparams", 0644, FOPS(lbs_sleepparams_read, | 676 | { "sleepparams", 0644, FOPS(lbs_sleepparams_read, |
729 | lbs_sleepparams_write), }, | 677 | lbs_sleepparams_write), }, |
730 | }; | 678 | }; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 709ffcad22ad..ba5438a7ba17 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /** | 2 | /** |
2 | * This file contains declaration referring to | 3 | * This file contains declaration referring to |
3 | * functions defined in other source files | 4 | * functions defined in other source files |
@@ -12,6 +13,7 @@ | |||
12 | struct lbs_private; | 13 | struct lbs_private; |
13 | struct sk_buff; | 14 | struct sk_buff; |
14 | struct net_device; | 15 | struct net_device; |
16 | struct cmd_ds_command; | ||
15 | 17 | ||
16 | 18 | ||
17 | /* ethtool.c */ | 19 | /* ethtool.c */ |
@@ -34,11 +36,13 @@ int lbs_start_card(struct lbs_private *priv); | |||
34 | void lbs_stop_card(struct lbs_private *priv); | 36 | void lbs_stop_card(struct lbs_private *priv); |
35 | void lbs_host_to_card_done(struct lbs_private *priv); | 37 | void lbs_host_to_card_done(struct lbs_private *priv); |
36 | 38 | ||
39 | int lbs_rtap_supported(struct lbs_private *priv); | ||
40 | |||
37 | int lbs_set_mac_address(struct net_device *dev, void *addr); | 41 | int lbs_set_mac_address(struct net_device *dev, void *addr); |
38 | void lbs_set_multicast_list(struct net_device *dev); | 42 | void lbs_set_multicast_list(struct net_device *dev); |
39 | 43 | ||
40 | int lbs_suspend(struct lbs_private *priv); | 44 | int lbs_suspend(struct lbs_private *priv); |
41 | void lbs_resume(struct lbs_private *priv); | 45 | int lbs_resume(struct lbs_private *priv); |
42 | 46 | ||
43 | void lbs_queue_event(struct lbs_private *priv, u32 event); | 47 | void lbs_queue_event(struct lbs_private *priv, u32 event); |
44 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | 48 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); |
@@ -49,5 +53,9 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | |||
49 | u32 lbs_fw_index_to_data_rate(u8 index); | 53 | u32 lbs_fw_index_to_data_rate(u8 index); |
50 | u8 lbs_data_rate_to_fw_index(u32 rate); | 54 | u8 lbs_data_rate_to_fw_index(u32 rate); |
51 | 55 | ||
56 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
57 | struct cmd_ds_command *cmd, u16 cmdoption); | ||
58 | |||
59 | int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp); | ||
52 | 60 | ||
53 | #endif | 61 | #endif |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index a54880e4ad2b..4536d9c0ad87 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -7,8 +7,8 @@ | |||
7 | #define _LBS_DEV_H_ | 7 | #define _LBS_DEV_H_ |
8 | 8 | ||
9 | #include "mesh.h" | 9 | #include "mesh.h" |
10 | #include "scan.h" | 10 | #include "defs.h" |
11 | #include "assoc.h" | 11 | #include "host.h" |
12 | 12 | ||
13 | #include <linux/kfifo.h> | 13 | #include <linux/kfifo.h> |
14 | 14 | ||
@@ -29,7 +29,6 @@ struct lbs_private { | |||
29 | /* Basic networking */ | 29 | /* Basic networking */ |
30 | struct net_device *dev; | 30 | struct net_device *dev; |
31 | u32 connect_status; | 31 | u32 connect_status; |
32 | int infra_open; | ||
33 | struct work_struct mcast_work; | 32 | struct work_struct mcast_work; |
34 | u32 nr_of_multicastmacaddr; | 33 | u32 nr_of_multicastmacaddr; |
35 | u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; | 34 | u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; |
@@ -37,6 +36,9 @@ struct lbs_private { | |||
37 | /* CFG80211 */ | 36 | /* CFG80211 */ |
38 | struct wireless_dev *wdev; | 37 | struct wireless_dev *wdev; |
39 | bool wiphy_registered; | 38 | bool wiphy_registered; |
39 | struct cfg80211_scan_request *scan_req; | ||
40 | u8 assoc_bss[ETH_ALEN]; | ||
41 | u8 disassoc_reason; | ||
40 | 42 | ||
41 | /* Mesh */ | 43 | /* Mesh */ |
42 | struct net_device *mesh_dev; /* Virtual device */ | 44 | struct net_device *mesh_dev; /* Virtual device */ |
@@ -49,10 +51,6 @@ struct lbs_private { | |||
49 | u8 mesh_ssid_len; | 51 | u8 mesh_ssid_len; |
50 | #endif | 52 | #endif |
51 | 53 | ||
52 | /* Monitor mode */ | ||
53 | struct net_device *rtap_net_dev; | ||
54 | u32 monitormode; | ||
55 | |||
56 | /* Debugfs */ | 54 | /* Debugfs */ |
57 | struct dentry *debugfs_dir; | 55 | struct dentry *debugfs_dir; |
58 | struct dentry *debugfs_debug; | 56 | struct dentry *debugfs_debug; |
@@ -62,6 +60,9 @@ struct lbs_private { | |||
62 | struct dentry *regs_dir; | 60 | struct dentry *regs_dir; |
63 | struct dentry *debugfs_regs_files[6]; | 61 | struct dentry *debugfs_regs_files[6]; |
64 | 62 | ||
63 | /** 11D and domain regulatory data */ | ||
64 | struct lbs_802_11d_domain_reg domain_reg; | ||
65 | |||
65 | /* Hardware debugging */ | 66 | /* Hardware debugging */ |
66 | u32 mac_offset; | 67 | u32 mac_offset; |
67 | u32 bbp_offset; | 68 | u32 bbp_offset; |
@@ -75,6 +76,7 @@ struct lbs_private { | |||
75 | 76 | ||
76 | /* Deep sleep */ | 77 | /* Deep sleep */ |
77 | int is_deep_sleep; | 78 | int is_deep_sleep; |
79 | int deep_sleep_required; | ||
78 | int is_auto_deep_sleep_enabled; | 80 | int is_auto_deep_sleep_enabled; |
79 | int wakeup_dev_required; | 81 | int wakeup_dev_required; |
80 | int is_activity_detected; | 82 | int is_activity_detected; |
@@ -82,6 +84,11 @@ struct lbs_private { | |||
82 | wait_queue_head_t ds_awake_q; | 84 | wait_queue_head_t ds_awake_q; |
83 | struct timer_list auto_deepsleep_timer; | 85 | struct timer_list auto_deepsleep_timer; |
84 | 86 | ||
87 | /* Host sleep*/ | ||
88 | int is_host_sleep_configured; | ||
89 | int is_host_sleep_activated; | ||
90 | wait_queue_head_t host_sleep_q; | ||
91 | |||
85 | /* Hardware access */ | 92 | /* Hardware access */ |
86 | void *card; | 93 | void *card; |
87 | u8 fw_ready; | 94 | u8 fw_ready; |
@@ -127,14 +134,10 @@ struct lbs_private { | |||
127 | struct workqueue_struct *work_thread; | 134 | struct workqueue_struct *work_thread; |
128 | 135 | ||
129 | /** Encryption stuff */ | 136 | /** Encryption stuff */ |
130 | struct lbs_802_11_security secinfo; | ||
131 | struct enc_key wpa_mcast_key; | ||
132 | struct enc_key wpa_unicast_key; | ||
133 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
134 | u8 wpa_ie_len; | ||
135 | u16 wep_tx_keyidx; | ||
136 | struct enc_key wep_keys[4]; | ||
137 | u8 authtype_auto; | 137 | u8 authtype_auto; |
138 | u8 wep_tx_key; | ||
139 | u8 wep_key[4][WLAN_KEY_LEN_WEP104]; | ||
140 | u8 wep_key_len[4]; | ||
138 | 141 | ||
139 | /* Wake On LAN */ | 142 | /* Wake On LAN */ |
140 | uint32_t wol_criteria; | 143 | uint32_t wol_criteria; |
@@ -155,6 +158,7 @@ struct lbs_private { | |||
155 | /* NIC/link operation characteristics */ | 158 | /* NIC/link operation characteristics */ |
156 | u16 mac_control; | 159 | u16 mac_control; |
157 | u8 radio_on; | 160 | u8 radio_on; |
161 | u8 cur_rate; | ||
158 | u8 channel; | 162 | u8 channel; |
159 | s16 txpower_cur; | 163 | s16 txpower_cur; |
160 | s16 txpower_min; | 164 | s16 txpower_min; |
@@ -163,42 +167,6 @@ struct lbs_private { | |||
163 | /** Scanning */ | 167 | /** Scanning */ |
164 | struct delayed_work scan_work; | 168 | struct delayed_work scan_work; |
165 | int scan_channel; | 169 | int scan_channel; |
166 | /* remember which channel was scanned last, != 0 if currently scanning */ | ||
167 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
168 | u8 scan_ssid_len; | ||
169 | |||
170 | /* Associating */ | ||
171 | struct delayed_work assoc_work; | ||
172 | struct current_bss_params curbssparams; | ||
173 | u8 mode; | ||
174 | struct list_head network_list; | ||
175 | struct list_head network_free_list; | ||
176 | struct bss_descriptor *networks; | ||
177 | struct assoc_request * pending_assoc_req; | ||
178 | struct assoc_request * in_progress_assoc_req; | ||
179 | uint16_t enablehwauto; | ||
180 | |||
181 | /* ADHOC */ | ||
182 | u16 beacon_period; | ||
183 | u8 beacon_enable; | ||
184 | u8 adhoccreate; | ||
185 | |||
186 | /* WEXT */ | ||
187 | char name[DEV_NAME_LEN]; | ||
188 | u8 nodename[16]; | ||
189 | struct iw_statistics wstats; | ||
190 | u8 cur_rate; | ||
191 | #define MAX_REGION_CHANNEL_NUM 2 | ||
192 | struct region_channel region_channel[MAX_REGION_CHANNEL_NUM]; | ||
193 | |||
194 | /** Requested Signal Strength*/ | ||
195 | u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG]; | ||
196 | u16 NF[MAX_TYPE_B][MAX_TYPE_AVG]; | ||
197 | u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG]; | ||
198 | u8 rawSNR[DEFAULT_DATA_AVG_FACTOR]; | ||
199 | u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; | ||
200 | u16 nextSNRNF; | ||
201 | u16 numSNRNF; | ||
202 | }; | 170 | }; |
203 | 171 | ||
204 | extern struct cmd_confirm_sleep confirm_sleep; | 172 | extern struct cmd_confirm_sleep confirm_sleep; |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 3804a58d7f4e..50193aac679e 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
@@ -2,13 +2,8 @@ | |||
2 | #include <linux/ethtool.h> | 2 | #include <linux/ethtool.h> |
3 | #include <linux/delay.h> | 3 | #include <linux/delay.h> |
4 | 4 | ||
5 | #include "host.h" | ||
6 | #include "decl.h" | 5 | #include "decl.h" |
7 | #include "defs.h" | ||
8 | #include "dev.h" | ||
9 | #include "wext.h" | ||
10 | #include "cmd.h" | 6 | #include "cmd.h" |
11 | #include "mesh.h" | ||
12 | 7 | ||
13 | 8 | ||
14 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, | 9 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, |
@@ -69,14 +64,11 @@ static void lbs_ethtool_get_wol(struct net_device *dev, | |||
69 | { | 64 | { |
70 | struct lbs_private *priv = dev->ml_priv; | 65 | struct lbs_private *priv = dev->ml_priv; |
71 | 66 | ||
72 | if (priv->wol_criteria == 0xffffffff) { | ||
73 | /* Interface driver didn't configure wake */ | ||
74 | wol->supported = wol->wolopts = 0; | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; | 67 | wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; |
79 | 68 | ||
69 | if (priv->wol_criteria == EHS_REMOVE_WAKEUP) | ||
70 | return; | ||
71 | |||
80 | if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) | 72 | if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) |
81 | wol->wolopts |= WAKE_UCAST; | 73 | wol->wolopts |= WAKE_UCAST; |
82 | if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) | 74 | if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) |
@@ -91,23 +83,22 @@ static int lbs_ethtool_set_wol(struct net_device *dev, | |||
91 | struct ethtool_wolinfo *wol) | 83 | struct ethtool_wolinfo *wol) |
92 | { | 84 | { |
93 | struct lbs_private *priv = dev->ml_priv; | 85 | struct lbs_private *priv = dev->ml_priv; |
94 | uint32_t criteria = 0; | ||
95 | 86 | ||
96 | if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) | 87 | if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) |
97 | return -EOPNOTSUPP; | 88 | return -EOPNOTSUPP; |
98 | 89 | ||
90 | priv->wol_criteria = 0; | ||
99 | if (wol->wolopts & WAKE_UCAST) | 91 | if (wol->wolopts & WAKE_UCAST) |
100 | criteria |= EHS_WAKE_ON_UNICAST_DATA; | 92 | priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA; |
101 | if (wol->wolopts & WAKE_MCAST) | 93 | if (wol->wolopts & WAKE_MCAST) |
102 | criteria |= EHS_WAKE_ON_MULTICAST_DATA; | 94 | priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA; |
103 | if (wol->wolopts & WAKE_BCAST) | 95 | if (wol->wolopts & WAKE_BCAST) |
104 | criteria |= EHS_WAKE_ON_BROADCAST_DATA; | 96 | priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA; |
105 | if (wol->wolopts & WAKE_PHY) | 97 | if (wol->wolopts & WAKE_PHY) |
106 | criteria |= EHS_WAKE_ON_MAC_EVENT; | 98 | priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT; |
107 | if (wol->wolopts == 0) | 99 | if (wol->wolopts == 0) |
108 | criteria |= EHS_REMOVE_WAKEUP; | 100 | priv->wol_criteria |= EHS_REMOVE_WAKEUP; |
109 | 101 | return 0; | |
110 | return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); | ||
111 | } | 102 | } |
112 | 103 | ||
113 | const struct ethtool_ops lbs_ethtool_ops = { | 104 | const struct ethtool_ops lbs_ethtool_ops = { |
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 3809c0b49464..112fbf167dc8 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -389,6 +389,30 @@ struct lbs_offset_value { | |||
389 | u32 value; | 389 | u32 value; |
390 | } __attribute__ ((packed)); | 390 | } __attribute__ ((packed)); |
391 | 391 | ||
392 | #define MRVDRV_MAX_TRIPLET_802_11D 83 | ||
393 | |||
394 | #define COUNTRY_CODE_LEN 3 | ||
395 | |||
396 | struct mrvl_ie_domain_param_set { | ||
397 | struct mrvl_ie_header header; | ||
398 | |||
399 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
400 | struct ieee80211_country_ie_triplet triplet[1]; | ||
401 | } __attribute__ ((packed)); | ||
402 | |||
403 | struct cmd_ds_802_11d_domain_info { | ||
404 | __le16 action; | ||
405 | struct mrvl_ie_domain_param_set domain; | ||
406 | } __attribute__ ((packed)); | ||
407 | |||
408 | struct lbs_802_11d_domain_reg { | ||
409 | /** Country code*/ | ||
410 | u8 country_code[COUNTRY_CODE_LEN]; | ||
411 | /** No. of triplet*/ | ||
412 | u8 no_triplet; | ||
413 | struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D]; | ||
414 | } __attribute__ ((packed)); | ||
415 | |||
392 | /* | 416 | /* |
393 | * Define data structure for CMD_GET_HW_SPEC | 417 | * Define data structure for CMD_GET_HW_SPEC |
394 | * This structure defines the response for the GET_HW_SPEC command | 418 | * This structure defines the response for the GET_HW_SPEC command |
@@ -949,6 +973,9 @@ struct cmd_ds_command { | |||
949 | struct cmd_ds_bbp_reg_access bbpreg; | 973 | struct cmd_ds_bbp_reg_access bbpreg; |
950 | struct cmd_ds_rf_reg_access rfreg; | 974 | struct cmd_ds_rf_reg_access rfreg; |
951 | 975 | ||
976 | struct cmd_ds_802_11d_domain_info domaininfo; | ||
977 | struct cmd_ds_802_11d_domain_info domaininforesp; | ||
978 | |||
952 | struct cmd_ds_802_11_tpc_cfg tpccfg; | 979 | struct cmd_ds_802_11_tpc_cfg tpccfg; |
953 | struct cmd_ds_802_11_afc afc; | 980 | struct cmd_ds_802_11_afc afc; |
954 | struct cmd_ds_802_11_led_ctrl ledgpio; | 981 | struct cmd_ds_802_11_led_ctrl ledgpio; |
@@ -958,5 +985,4 @@ struct cmd_ds_command { | |||
958 | struct cmd_ds_802_11_beacon_control bcn_ctrl; | 985 | struct cmd_ds_802_11_beacon_control bcn_ctrl; |
959 | } params; | 986 | } params; |
960 | } __attribute__ ((packed)); | 987 | } __attribute__ ((packed)); |
961 | |||
962 | #endif | 988 | #endif |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 64dd345d30f5..6e71346a7550 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -1182,11 +1182,69 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1182 | lbs_deb_leave(LBS_DEB_SDIO); | 1182 | lbs_deb_leave(LBS_DEB_SDIO); |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | static int if_sdio_suspend(struct device *dev) | ||
1186 | { | ||
1187 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
1188 | int ret; | ||
1189 | struct if_sdio_card *card = sdio_get_drvdata(func); | ||
1190 | |||
1191 | mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); | ||
1192 | |||
1193 | lbs_pr_info("%s: suspend: PM flags = 0x%x\n", | ||
1194 | sdio_func_id(func), flags); | ||
1195 | |||
1196 | /* If we aren't being asked to wake on anything, we should bail out | ||
1197 | * and let the SD stack power down the card. | ||
1198 | */ | ||
1199 | if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { | ||
1200 | lbs_pr_info("Suspend without wake params -- " | ||
1201 | "powering down card."); | ||
1202 | return -ENOSYS; | ||
1203 | } | ||
1204 | |||
1205 | if (!(flags & MMC_PM_KEEP_POWER)) { | ||
1206 | lbs_pr_err("%s: cannot remain alive while host is suspended\n", | ||
1207 | sdio_func_id(func)); | ||
1208 | return -ENOSYS; | ||
1209 | } | ||
1210 | |||
1211 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
1212 | if (ret) | ||
1213 | return ret; | ||
1214 | |||
1215 | ret = lbs_suspend(card->priv); | ||
1216 | if (ret) | ||
1217 | return ret; | ||
1218 | |||
1219 | return sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); | ||
1220 | } | ||
1221 | |||
1222 | static int if_sdio_resume(struct device *dev) | ||
1223 | { | ||
1224 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
1225 | struct if_sdio_card *card = sdio_get_drvdata(func); | ||
1226 | int ret; | ||
1227 | |||
1228 | lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func)); | ||
1229 | |||
1230 | ret = lbs_resume(card->priv); | ||
1231 | |||
1232 | return ret; | ||
1233 | } | ||
1234 | |||
1235 | static const struct dev_pm_ops if_sdio_pm_ops = { | ||
1236 | .suspend = if_sdio_suspend, | ||
1237 | .resume = if_sdio_resume, | ||
1238 | }; | ||
1239 | |||
1185 | static struct sdio_driver if_sdio_driver = { | 1240 | static struct sdio_driver if_sdio_driver = { |
1186 | .name = "libertas_sdio", | 1241 | .name = "libertas_sdio", |
1187 | .id_table = if_sdio_ids, | 1242 | .id_table = if_sdio_ids, |
1188 | .probe = if_sdio_probe, | 1243 | .probe = if_sdio_probe, |
1189 | .remove = if_sdio_remove, | 1244 | .remove = if_sdio_remove, |
1245 | .drv = { | ||
1246 | .pm = &if_sdio_pm_ops, | ||
1247 | }, | ||
1190 | }; | 1248 | }; |
1191 | 1249 | ||
1192 | /*******************************************************************/ | 1250 | /*******************************************************************/ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index f41594c7ac16..3678e532874f 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -613,16 +613,14 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
613 | return; | 613 | return; |
614 | } | 614 | } |
615 | 615 | ||
616 | syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); | 616 | syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET, |
617 | sizeof(struct fwsyncheader), GFP_ATOMIC); | ||
617 | if (!syncfwheader) { | 618 | if (!syncfwheader) { |
618 | lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); | 619 | lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); |
619 | kfree_skb(skb); | 620 | kfree_skb(skb); |
620 | return; | 621 | return; |
621 | } | 622 | } |
622 | 623 | ||
623 | memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET, | ||
624 | sizeof(struct fwsyncheader)); | ||
625 | |||
626 | if (!syncfwheader->cmd) { | 624 | if (!syncfwheader->cmd) { |
627 | lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); | 625 | lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); |
628 | lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", | 626 | lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", |
@@ -1043,6 +1041,12 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) | |||
1043 | if (priv->psstate != PS_STATE_FULL_POWER) | 1041 | if (priv->psstate != PS_STATE_FULL_POWER) |
1044 | return -1; | 1042 | return -1; |
1045 | 1043 | ||
1044 | if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { | ||
1045 | lbs_pr_info("Suspend attempt without " | ||
1046 | "configuring wake params!\n"); | ||
1047 | return -ENOSYS; | ||
1048 | } | ||
1049 | |||
1046 | ret = lbs_suspend(priv); | 1050 | ret = lbs_suspend(priv); |
1047 | if (ret) | 1051 | if (ret) |
1048 | goto out; | 1052 | goto out; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index d9b8ee130c45..b519fc70f04f 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -11,20 +11,14 @@ | |||
11 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include <linux/kfifo.h> | 13 | #include <linux/kfifo.h> |
14 | #include <linux/stddef.h> | ||
15 | #include <linux/ieee80211.h> | ||
16 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
17 | #include <net/iw_handler.h> | ||
18 | #include <net/cfg80211.h> | 15 | #include <net/cfg80211.h> |
19 | 16 | ||
20 | #include "host.h" | 17 | #include "host.h" |
21 | #include "decl.h" | 18 | #include "decl.h" |
22 | #include "dev.h" | 19 | #include "dev.h" |
23 | #include "wext.h" | ||
24 | #include "cfg.h" | 20 | #include "cfg.h" |
25 | #include "debugfs.h" | 21 | #include "debugfs.h" |
26 | #include "scan.h" | ||
27 | #include "assoc.h" | ||
28 | #include "cmd.h" | 22 | #include "cmd.h" |
29 | 23 | ||
30 | #define DRIVER_RELEASE_VERSION "323.p0" | 24 | #define DRIVER_RELEASE_VERSION "323.p0" |
@@ -96,72 +90,6 @@ u8 lbs_data_rate_to_fw_index(u32 rate) | |||
96 | } | 90 | } |
97 | 91 | ||
98 | 92 | ||
99 | static int lbs_add_rtap(struct lbs_private *priv); | ||
100 | static void lbs_remove_rtap(struct lbs_private *priv); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Get function for sysfs attribute rtap | ||
105 | */ | ||
106 | static ssize_t lbs_rtap_get(struct device *dev, | ||
107 | struct device_attribute *attr, char * buf) | ||
108 | { | ||
109 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
110 | return snprintf(buf, 5, "0x%X\n", priv->monitormode); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Set function for sysfs attribute rtap | ||
115 | */ | ||
116 | static ssize_t lbs_rtap_set(struct device *dev, | ||
117 | struct device_attribute *attr, const char * buf, size_t count) | ||
118 | { | ||
119 | int monitor_mode; | ||
120 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
121 | |||
122 | sscanf(buf, "%x", &monitor_mode); | ||
123 | if (monitor_mode) { | ||
124 | if (priv->monitormode == monitor_mode) | ||
125 | return strlen(buf); | ||
126 | if (!priv->monitormode) { | ||
127 | if (priv->infra_open || lbs_mesh_open(priv)) | ||
128 | return -EBUSY; | ||
129 | if (priv->mode == IW_MODE_INFRA) | ||
130 | lbs_cmd_80211_deauthenticate(priv, | ||
131 | priv->curbssparams.bssid, | ||
132 | WLAN_REASON_DEAUTH_LEAVING); | ||
133 | else if (priv->mode == IW_MODE_ADHOC) | ||
134 | lbs_adhoc_stop(priv); | ||
135 | lbs_add_rtap(priv); | ||
136 | } | ||
137 | priv->monitormode = monitor_mode; | ||
138 | } else { | ||
139 | if (!priv->monitormode) | ||
140 | return strlen(buf); | ||
141 | priv->monitormode = 0; | ||
142 | lbs_remove_rtap(priv); | ||
143 | |||
144 | if (priv->currenttxskb) { | ||
145 | dev_kfree_skb_any(priv->currenttxskb); | ||
146 | priv->currenttxskb = NULL; | ||
147 | } | ||
148 | |||
149 | /* Wake queues, command thread, etc. */ | ||
150 | lbs_host_to_card_done(priv); | ||
151 | } | ||
152 | |||
153 | lbs_prepare_and_send_command(priv, | ||
154 | CMD_802_11_MONITOR_MODE, CMD_ACT_SET, | ||
155 | CMD_OPTION_WAITFORRSP, 0, &priv->monitormode); | ||
156 | return strlen(buf); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * lbs_rtap attribute to be exported per ethX interface | ||
161 | * through sysfs (/sys/class/net/ethX/lbs_rtap) | ||
162 | */ | ||
163 | static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); | ||
164 | |||
165 | /** | 93 | /** |
166 | * @brief This function opens the ethX interface | 94 | * @brief This function opens the ethX interface |
167 | * | 95 | * |
@@ -177,13 +105,6 @@ static int lbs_dev_open(struct net_device *dev) | |||
177 | 105 | ||
178 | spin_lock_irq(&priv->driver_lock); | 106 | spin_lock_irq(&priv->driver_lock); |
179 | 107 | ||
180 | if (priv->monitormode) { | ||
181 | ret = -EBUSY; | ||
182 | goto out; | ||
183 | } | ||
184 | |||
185 | priv->infra_open = 1; | ||
186 | |||
187 | if (priv->connect_status == LBS_CONNECTED) | 108 | if (priv->connect_status == LBS_CONNECTED) |
188 | netif_carrier_on(dev); | 109 | netif_carrier_on(dev); |
189 | else | 110 | else |
@@ -191,7 +112,6 @@ static int lbs_dev_open(struct net_device *dev) | |||
191 | 112 | ||
192 | if (!priv->tx_pending_len) | 113 | if (!priv->tx_pending_len) |
193 | netif_wake_queue(dev); | 114 | netif_wake_queue(dev); |
194 | out: | ||
195 | 115 | ||
196 | spin_unlock_irq(&priv->driver_lock); | 116 | spin_unlock_irq(&priv->driver_lock); |
197 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); | 117 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); |
@@ -211,7 +131,6 @@ static int lbs_eth_stop(struct net_device *dev) | |||
211 | lbs_deb_enter(LBS_DEB_NET); | 131 | lbs_deb_enter(LBS_DEB_NET); |
212 | 132 | ||
213 | spin_lock_irq(&priv->driver_lock); | 133 | spin_lock_irq(&priv->driver_lock); |
214 | priv->infra_open = 0; | ||
215 | netif_stop_queue(dev); | 134 | netif_stop_queue(dev); |
216 | spin_unlock_irq(&priv->driver_lock); | 135 | spin_unlock_irq(&priv->driver_lock); |
217 | 136 | ||
@@ -625,16 +544,13 @@ static int lbs_thread(void *data) | |||
625 | return 0; | 544 | return 0; |
626 | } | 545 | } |
627 | 546 | ||
628 | static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy, | 547 | static int lbs_ret_host_sleep_activate(struct lbs_private *priv, |
629 | struct cmd_header *cmd) | 548 | unsigned long dummy, |
549 | struct cmd_header *cmd) | ||
630 | { | 550 | { |
631 | lbs_deb_enter(LBS_DEB_FW); | 551 | lbs_deb_enter(LBS_DEB_FW); |
632 | 552 | priv->is_host_sleep_activated = 1; | |
633 | netif_device_detach(priv->dev); | 553 | wake_up_interruptible(&priv->host_sleep_q); |
634 | if (priv->mesh_dev) | ||
635 | netif_device_detach(priv->mesh_dev); | ||
636 | |||
637 | priv->fw_ready = 0; | ||
638 | lbs_deb_leave(LBS_DEB_FW); | 554 | lbs_deb_leave(LBS_DEB_FW); |
639 | return 0; | 555 | return 0; |
640 | } | 556 | } |
@@ -646,39 +562,65 @@ int lbs_suspend(struct lbs_private *priv) | |||
646 | 562 | ||
647 | lbs_deb_enter(LBS_DEB_FW); | 563 | lbs_deb_enter(LBS_DEB_FW); |
648 | 564 | ||
649 | if (priv->wol_criteria == 0xffffffff) { | 565 | if (priv->is_deep_sleep) { |
650 | lbs_pr_info("Suspend attempt without configuring wake params!\n"); | 566 | ret = lbs_set_deep_sleep(priv, 0); |
651 | return -EINVAL; | 567 | if (ret) { |
568 | lbs_pr_err("deep sleep cancellation failed: %d\n", ret); | ||
569 | return ret; | ||
570 | } | ||
571 | priv->deep_sleep_required = 1; | ||
652 | } | 572 | } |
653 | 573 | ||
654 | memset(&cmd, 0, sizeof(cmd)); | 574 | memset(&cmd, 0, sizeof(cmd)); |
575 | ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, | ||
576 | (struct wol_config *)NULL); | ||
577 | if (ret) { | ||
578 | lbs_pr_info("Host sleep configuration failed: %d\n", ret); | ||
579 | return ret; | ||
580 | } | ||
581 | if (priv->psstate == PS_STATE_FULL_POWER) { | ||
582 | ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, | ||
583 | sizeof(cmd), lbs_ret_host_sleep_activate, 0); | ||
584 | if (ret) | ||
585 | lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); | ||
586 | } | ||
655 | 587 | ||
656 | ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, | 588 | if (!wait_event_interruptible_timeout(priv->host_sleep_q, |
657 | sizeof(cmd), lbs_suspend_callback, 0); | 589 | priv->is_host_sleep_activated, (10 * HZ))) { |
658 | if (ret) | 590 | lbs_pr_err("host_sleep_q: timer expired\n"); |
659 | lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); | 591 | ret = -1; |
592 | } | ||
593 | netif_device_detach(priv->dev); | ||
594 | if (priv->mesh_dev) | ||
595 | netif_device_detach(priv->mesh_dev); | ||
660 | 596 | ||
661 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 597 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); |
662 | return ret; | 598 | return ret; |
663 | } | 599 | } |
664 | EXPORT_SYMBOL_GPL(lbs_suspend); | 600 | EXPORT_SYMBOL_GPL(lbs_suspend); |
665 | 601 | ||
666 | void lbs_resume(struct lbs_private *priv) | 602 | int lbs_resume(struct lbs_private *priv) |
667 | { | 603 | { |
668 | lbs_deb_enter(LBS_DEB_FW); | 604 | int ret; |
605 | uint32_t criteria = EHS_REMOVE_WAKEUP; | ||
669 | 606 | ||
670 | priv->fw_ready = 1; | 607 | lbs_deb_enter(LBS_DEB_FW); |
671 | 608 | ||
672 | /* Firmware doesn't seem to give us RX packets any more | 609 | ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); |
673 | until we send it some command. Might as well update */ | ||
674 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | ||
675 | 0, 0, NULL); | ||
676 | 610 | ||
677 | netif_device_attach(priv->dev); | 611 | netif_device_attach(priv->dev); |
678 | if (priv->mesh_dev) | 612 | if (priv->mesh_dev) |
679 | netif_device_attach(priv->mesh_dev); | 613 | netif_device_attach(priv->mesh_dev); |
680 | 614 | ||
681 | lbs_deb_leave(LBS_DEB_FW); | 615 | if (priv->deep_sleep_required) { |
616 | priv->deep_sleep_required = 0; | ||
617 | ret = lbs_set_deep_sleep(priv, 1); | ||
618 | if (ret) | ||
619 | lbs_pr_err("deep sleep activation failed: %d\n", ret); | ||
620 | } | ||
621 | |||
622 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | ||
623 | return ret; | ||
682 | } | 624 | } |
683 | EXPORT_SYMBOL_GPL(lbs_resume); | 625 | EXPORT_SYMBOL_GPL(lbs_resume); |
684 | 626 | ||
@@ -710,6 +652,9 @@ static int lbs_setup_firmware(struct lbs_private *priv) | |||
710 | priv->txpower_max = maxlevel; | 652 | priv->txpower_max = maxlevel; |
711 | } | 653 | } |
712 | 654 | ||
655 | /* Send cmd to FW to enable 11D function */ | ||
656 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1); | ||
657 | |||
713 | lbs_set_mac_control(priv); | 658 | lbs_set_mac_control(priv); |
714 | done: | 659 | done: |
715 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 660 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); |
@@ -799,45 +744,27 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv) | |||
799 | 744 | ||
800 | static int lbs_init_adapter(struct lbs_private *priv) | 745 | static int lbs_init_adapter(struct lbs_private *priv) |
801 | { | 746 | { |
802 | size_t bufsize; | 747 | int ret; |
803 | int i, ret = 0; | ||
804 | 748 | ||
805 | lbs_deb_enter(LBS_DEB_MAIN); | 749 | lbs_deb_enter(LBS_DEB_MAIN); |
806 | 750 | ||
807 | /* Allocate buffer to store the BSSID list */ | ||
808 | bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); | ||
809 | priv->networks = kzalloc(bufsize, GFP_KERNEL); | ||
810 | if (!priv->networks) { | ||
811 | lbs_pr_err("Out of memory allocating beacons\n"); | ||
812 | ret = -1; | ||
813 | goto out; | ||
814 | } | ||
815 | |||
816 | /* Initialize scan result lists */ | ||
817 | INIT_LIST_HEAD(&priv->network_free_list); | ||
818 | INIT_LIST_HEAD(&priv->network_list); | ||
819 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | ||
820 | list_add_tail(&priv->networks[i].list, | ||
821 | &priv->network_free_list); | ||
822 | } | ||
823 | |||
824 | memset(priv->current_addr, 0xff, ETH_ALEN); | 751 | memset(priv->current_addr, 0xff, ETH_ALEN); |
825 | 752 | ||
826 | priv->connect_status = LBS_DISCONNECTED; | 753 | priv->connect_status = LBS_DISCONNECTED; |
827 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
828 | priv->mode = IW_MODE_INFRA; | ||
829 | priv->channel = DEFAULT_AD_HOC_CHANNEL; | 754 | priv->channel = DEFAULT_AD_HOC_CHANNEL; |
830 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 755 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
831 | priv->radio_on = 1; | 756 | priv->radio_on = 1; |
832 | priv->enablehwauto = 1; | ||
833 | priv->psmode = LBS802_11POWERMODECAM; | 757 | priv->psmode = LBS802_11POWERMODECAM; |
834 | priv->psstate = PS_STATE_FULL_POWER; | 758 | priv->psstate = PS_STATE_FULL_POWER; |
835 | priv->is_deep_sleep = 0; | 759 | priv->is_deep_sleep = 0; |
836 | priv->is_auto_deep_sleep_enabled = 0; | 760 | priv->is_auto_deep_sleep_enabled = 0; |
761 | priv->deep_sleep_required = 0; | ||
837 | priv->wakeup_dev_required = 0; | 762 | priv->wakeup_dev_required = 0; |
838 | init_waitqueue_head(&priv->ds_awake_q); | 763 | init_waitqueue_head(&priv->ds_awake_q); |
839 | priv->authtype_auto = 1; | 764 | priv->authtype_auto = 1; |
840 | 765 | priv->is_host_sleep_configured = 0; | |
766 | priv->is_host_sleep_activated = 0; | ||
767 | init_waitqueue_head(&priv->host_sleep_q); | ||
841 | mutex_init(&priv->lock); | 768 | mutex_init(&priv->lock); |
842 | 769 | ||
843 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, | 770 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, |
@@ -881,8 +808,6 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
881 | kfifo_free(&priv->event_fifo); | 808 | kfifo_free(&priv->event_fifo); |
882 | del_timer(&priv->command_timer); | 809 | del_timer(&priv->command_timer); |
883 | del_timer(&priv->auto_deepsleep_timer); | 810 | del_timer(&priv->auto_deepsleep_timer); |
884 | kfree(priv->networks); | ||
885 | priv->networks = NULL; | ||
886 | 811 | ||
887 | lbs_deb_leave(LBS_DEB_MAIN); | 812 | lbs_deb_leave(LBS_DEB_MAIN); |
888 | } | 813 | } |
@@ -919,7 +844,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
919 | lbs_pr_err("cfg80211 init failed\n"); | 844 | lbs_pr_err("cfg80211 init failed\n"); |
920 | goto done; | 845 | goto done; |
921 | } | 846 | } |
922 | /* TODO? */ | 847 | |
923 | wdev->iftype = NL80211_IFTYPE_STATION; | 848 | wdev->iftype = NL80211_IFTYPE_STATION; |
924 | priv = wdev_priv(wdev); | 849 | priv = wdev_priv(wdev); |
925 | priv->wdev = wdev; | 850 | priv->wdev = wdev; |
@@ -929,7 +854,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
929 | goto err_wdev; | 854 | goto err_wdev; |
930 | } | 855 | } |
931 | 856 | ||
932 | //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); | ||
933 | dev = alloc_netdev(0, "wlan%d", ether_setup); | 857 | dev = alloc_netdev(0, "wlan%d", ether_setup); |
934 | if (!dev) { | 858 | if (!dev) { |
935 | dev_err(dmdev, "no memory for network device instance\n"); | 859 | dev_err(dmdev, "no memory for network device instance\n"); |
@@ -945,20 +869,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
945 | dev->netdev_ops = &lbs_netdev_ops; | 869 | dev->netdev_ops = &lbs_netdev_ops; |
946 | dev->watchdog_timeo = 5 * HZ; | 870 | dev->watchdog_timeo = 5 * HZ; |
947 | dev->ethtool_ops = &lbs_ethtool_ops; | 871 | dev->ethtool_ops = &lbs_ethtool_ops; |
948 | #ifdef WIRELESS_EXT | ||
949 | dev->wireless_handlers = &lbs_handler_def; | ||
950 | #endif | ||
951 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 872 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
952 | 873 | ||
953 | |||
954 | // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ?? | ||
955 | |||
956 | |||
957 | priv->card = card; | 874 | priv->card = card; |
958 | priv->infra_open = 0; | ||
959 | 875 | ||
960 | |||
961 | priv->rtap_net_dev = NULL; | ||
962 | strcpy(dev->name, "wlan%d"); | 876 | strcpy(dev->name, "wlan%d"); |
963 | 877 | ||
964 | lbs_deb_thread("Starting main thread...\n"); | 878 | lbs_deb_thread("Starting main thread...\n"); |
@@ -970,12 +884,11 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
970 | } | 884 | } |
971 | 885 | ||
972 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 886 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
973 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | ||
974 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | ||
975 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | 887 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); |
976 | 888 | ||
977 | priv->wol_criteria = 0xffffffff; | 889 | priv->wol_criteria = 0xffffffff; |
978 | priv->wol_gpio = 0xff; | 890 | priv->wol_gpio = 0xff; |
891 | priv->wol_gap = 20; | ||
979 | 892 | ||
980 | goto done; | 893 | goto done; |
981 | 894 | ||
@@ -1004,12 +917,10 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1004 | lbs_deb_enter(LBS_DEB_MAIN); | 917 | lbs_deb_enter(LBS_DEB_MAIN); |
1005 | 918 | ||
1006 | lbs_remove_mesh(priv); | 919 | lbs_remove_mesh(priv); |
1007 | lbs_remove_rtap(priv); | 920 | lbs_scan_deinit(priv); |
1008 | 921 | ||
1009 | dev = priv->dev; | 922 | dev = priv->dev; |
1010 | 923 | ||
1011 | cancel_delayed_work_sync(&priv->scan_work); | ||
1012 | cancel_delayed_work_sync(&priv->assoc_work); | ||
1013 | cancel_work_sync(&priv->mcast_work); | 924 | cancel_work_sync(&priv->mcast_work); |
1014 | 925 | ||
1015 | /* worker thread destruction blocks on the in-flight command which | 926 | /* worker thread destruction blocks on the in-flight command which |
@@ -1024,13 +935,15 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1024 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | 935 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); |
1025 | } | 936 | } |
1026 | 937 | ||
1027 | lbs_send_disconnect_notification(priv); | ||
1028 | |||
1029 | if (priv->is_deep_sleep) { | 938 | if (priv->is_deep_sleep) { |
1030 | priv->is_deep_sleep = 0; | 939 | priv->is_deep_sleep = 0; |
1031 | wake_up_interruptible(&priv->ds_awake_q); | 940 | wake_up_interruptible(&priv->ds_awake_q); |
1032 | } | 941 | } |
1033 | 942 | ||
943 | priv->is_host_sleep_configured = 0; | ||
944 | priv->is_host_sleep_activated = 0; | ||
945 | wake_up_interruptible(&priv->host_sleep_q); | ||
946 | |||
1034 | /* Stop the thread servicing the interrupts */ | 947 | /* Stop the thread servicing the interrupts */ |
1035 | priv->surpriseremoved = 1; | 948 | priv->surpriseremoved = 1; |
1036 | kthread_stop(priv->main_thread); | 949 | kthread_stop(priv->main_thread); |
@@ -1046,7 +959,7 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1046 | EXPORT_SYMBOL_GPL(lbs_remove_card); | 959 | EXPORT_SYMBOL_GPL(lbs_remove_card); |
1047 | 960 | ||
1048 | 961 | ||
1049 | static int lbs_rtap_supported(struct lbs_private *priv) | 962 | int lbs_rtap_supported(struct lbs_private *priv) |
1050 | { | 963 | { |
1051 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | 964 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) |
1052 | return 1; | 965 | return 1; |
@@ -1078,16 +991,6 @@ int lbs_start_card(struct lbs_private *priv) | |||
1078 | 991 | ||
1079 | lbs_init_mesh(priv); | 992 | lbs_init_mesh(priv); |
1080 | 993 | ||
1081 | /* | ||
1082 | * While rtap isn't related to mesh, only mesh-enabled | ||
1083 | * firmware implements the rtap functionality via | ||
1084 | * CMD_802_11_MONITOR_MODE. | ||
1085 | */ | ||
1086 | if (lbs_rtap_supported(priv)) { | ||
1087 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) | ||
1088 | lbs_pr_err("cannot register lbs_rtap attribute\n"); | ||
1089 | } | ||
1090 | |||
1091 | lbs_debugfs_init_one(priv, dev); | 994 | lbs_debugfs_init_one(priv, dev); |
1092 | 995 | ||
1093 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); | 996 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); |
@@ -1119,9 +1022,6 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1119 | lbs_debugfs_remove_one(priv); | 1022 | lbs_debugfs_remove_one(priv); |
1120 | lbs_deinit_mesh(priv); | 1023 | lbs_deinit_mesh(priv); |
1121 | 1024 | ||
1122 | if (lbs_rtap_supported(priv)) | ||
1123 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | ||
1124 | |||
1125 | /* Delete the timeout of the currently processing command */ | 1025 | /* Delete the timeout of the currently processing command */ |
1126 | del_timer_sync(&priv->command_timer); | 1026 | del_timer_sync(&priv->command_timer); |
1127 | del_timer_sync(&priv->auto_deepsleep_timer); | 1027 | del_timer_sync(&priv->auto_deepsleep_timer); |
@@ -1208,87 +1108,6 @@ static void __exit lbs_exit_module(void) | |||
1208 | lbs_deb_leave(LBS_DEB_MAIN); | 1108 | lbs_deb_leave(LBS_DEB_MAIN); |
1209 | } | 1109 | } |
1210 | 1110 | ||
1211 | /* | ||
1212 | * rtap interface support fuctions | ||
1213 | */ | ||
1214 | |||
1215 | static int lbs_rtap_open(struct net_device *dev) | ||
1216 | { | ||
1217 | /* Yes, _stop_ the queue. Because we don't support injection */ | ||
1218 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1219 | netif_carrier_off(dev); | ||
1220 | netif_stop_queue(dev); | ||
1221 | lbs_deb_leave(LBS_DEB_LEAVE); | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | static int lbs_rtap_stop(struct net_device *dev) | ||
1226 | { | ||
1227 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1228 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1229 | return 0; | ||
1230 | } | ||
1231 | |||
1232 | static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb, | ||
1233 | struct net_device *dev) | ||
1234 | { | ||
1235 | netif_stop_queue(dev); | ||
1236 | return NETDEV_TX_BUSY; | ||
1237 | } | ||
1238 | |||
1239 | static void lbs_remove_rtap(struct lbs_private *priv) | ||
1240 | { | ||
1241 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1242 | if (priv->rtap_net_dev == NULL) | ||
1243 | goto out; | ||
1244 | unregister_netdev(priv->rtap_net_dev); | ||
1245 | free_netdev(priv->rtap_net_dev); | ||
1246 | priv->rtap_net_dev = NULL; | ||
1247 | out: | ||
1248 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1249 | } | ||
1250 | |||
1251 | static const struct net_device_ops rtap_netdev_ops = { | ||
1252 | .ndo_open = lbs_rtap_open, | ||
1253 | .ndo_stop = lbs_rtap_stop, | ||
1254 | .ndo_start_xmit = lbs_rtap_hard_start_xmit, | ||
1255 | }; | ||
1256 | |||
1257 | static int lbs_add_rtap(struct lbs_private *priv) | ||
1258 | { | ||
1259 | int ret = 0; | ||
1260 | struct net_device *rtap_dev; | ||
1261 | |||
1262 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1263 | if (priv->rtap_net_dev) { | ||
1264 | ret = -EPERM; | ||
1265 | goto out; | ||
1266 | } | ||
1267 | |||
1268 | rtap_dev = alloc_netdev(0, "rtap%d", ether_setup); | ||
1269 | if (rtap_dev == NULL) { | ||
1270 | ret = -ENOMEM; | ||
1271 | goto out; | ||
1272 | } | ||
1273 | |||
1274 | memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN); | ||
1275 | rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
1276 | rtap_dev->netdev_ops = &rtap_netdev_ops; | ||
1277 | rtap_dev->ml_priv = priv; | ||
1278 | SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); | ||
1279 | |||
1280 | ret = register_netdev(rtap_dev); | ||
1281 | if (ret) { | ||
1282 | free_netdev(rtap_dev); | ||
1283 | goto out; | ||
1284 | } | ||
1285 | priv->rtap_net_dev = rtap_dev; | ||
1286 | |||
1287 | out: | ||
1288 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
1289 | return ret; | ||
1290 | } | ||
1291 | |||
1292 | module_init(lbs_init_module); | 1111 | module_init(lbs_init_module); |
1293 | module_exit(lbs_exit_module); | 1112 | module_exit(lbs_exit_module); |
1294 | 1113 | ||
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index e385af1f4583..bc5bc1384c35 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/if_arp.h> | 5 | #include <linux/if_arp.h> |
6 | #include <linux/kthread.h> | 6 | #include <linux/kthread.h> |
7 | #include <linux/kfifo.h> | 7 | #include <linux/kfifo.h> |
8 | #include <net/cfg80211.h> | ||
8 | 9 | ||
9 | #include "mesh.h" | 10 | #include "mesh.h" |
10 | #include "decl.h" | 11 | #include "decl.h" |
@@ -314,7 +315,7 @@ static int lbs_mesh_dev_open(struct net_device *dev) | |||
314 | 315 | ||
315 | spin_lock_irq(&priv->driver_lock); | 316 | spin_lock_irq(&priv->driver_lock); |
316 | 317 | ||
317 | if (priv->monitormode) { | 318 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
318 | ret = -EBUSY; | 319 | ret = -EBUSY; |
319 | goto out; | 320 | goto out; |
320 | } | 321 | } |
@@ -369,9 +370,6 @@ int lbs_add_mesh(struct lbs_private *priv) | |||
369 | 370 | ||
370 | SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); | 371 | SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); |
371 | 372 | ||
372 | #ifdef WIRELESS_EXT | ||
373 | mesh_dev->wireless_handlers = &mesh_handler_def; | ||
374 | #endif | ||
375 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 373 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
376 | /* Register virtual mesh interface */ | 374 | /* Register virtual mesh interface */ |
377 | ret = register_netdev(mesh_dev); | 375 | ret = register_netdev(mesh_dev); |
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index e2573303a328..84ea2481ff20 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h | |||
@@ -70,11 +70,6 @@ void lbs_persist_config_init(struct net_device *net); | |||
70 | void lbs_persist_config_remove(struct net_device *net); | 70 | void lbs_persist_config_remove(struct net_device *net); |
71 | 71 | ||
72 | 72 | ||
73 | /* WEXT handler */ | ||
74 | |||
75 | extern struct iw_handler_def mesh_handler_def; | ||
76 | |||
77 | |||
78 | /* Ethtool statistics */ | 73 | /* Ethtool statistics */ |
79 | 74 | ||
80 | struct ethtool_stats; | 75 | struct ethtool_stats; |
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 7a377f5b7662..2163df01caed 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -4,12 +4,13 @@ | |||
4 | #include <linux/etherdevice.h> | 4 | #include <linux/etherdevice.h> |
5 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | #include <net/cfg80211.h> | ||
7 | 8 | ||
9 | #include "defs.h" | ||
8 | #include "host.h" | 10 | #include "host.h" |
9 | #include "radiotap.h" | 11 | #include "radiotap.h" |
10 | #include "decl.h" | 12 | #include "decl.h" |
11 | #include "dev.h" | 13 | #include "dev.h" |
12 | #include "wext.h" | ||
13 | 14 | ||
14 | struct eth803hdr { | 15 | struct eth803hdr { |
15 | u8 dest_addr[6]; | 16 | u8 dest_addr[6]; |
@@ -39,98 +40,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, | |||
39 | struct sk_buff *skb); | 40 | struct sk_buff *skb); |
40 | 41 | ||
41 | /** | 42 | /** |
42 | * @brief This function computes the avgSNR . | ||
43 | * | ||
44 | * @param priv A pointer to struct lbs_private structure | ||
45 | * @return avgSNR | ||
46 | */ | ||
47 | static u8 lbs_getavgsnr(struct lbs_private *priv) | ||
48 | { | ||
49 | u8 i; | ||
50 | u16 temp = 0; | ||
51 | if (priv->numSNRNF == 0) | ||
52 | return 0; | ||
53 | for (i = 0; i < priv->numSNRNF; i++) | ||
54 | temp += priv->rawSNR[i]; | ||
55 | return (u8) (temp / priv->numSNRNF); | ||
56 | |||
57 | } | ||
58 | |||
59 | /** | ||
60 | * @brief This function computes the AvgNF | ||
61 | * | ||
62 | * @param priv A pointer to struct lbs_private structure | ||
63 | * @return AvgNF | ||
64 | */ | ||
65 | static u8 lbs_getavgnf(struct lbs_private *priv) | ||
66 | { | ||
67 | u8 i; | ||
68 | u16 temp = 0; | ||
69 | if (priv->numSNRNF == 0) | ||
70 | return 0; | ||
71 | for (i = 0; i < priv->numSNRNF; i++) | ||
72 | temp += priv->rawNF[i]; | ||
73 | return (u8) (temp / priv->numSNRNF); | ||
74 | |||
75 | } | ||
76 | |||
77 | /** | ||
78 | * @brief This function save the raw SNR/NF to our internel buffer | ||
79 | * | ||
80 | * @param priv A pointer to struct lbs_private structure | ||
81 | * @param prxpd A pointer to rxpd structure of received packet | ||
82 | * @return n/a | ||
83 | */ | ||
84 | static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) | ||
85 | { | ||
86 | if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR) | ||
87 | priv->numSNRNF++; | ||
88 | priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr; | ||
89 | priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf; | ||
90 | priv->nextSNRNF++; | ||
91 | if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR) | ||
92 | priv->nextSNRNF = 0; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * @brief This function computes the RSSI in received packet. | ||
97 | * | ||
98 | * @param priv A pointer to struct lbs_private structure | ||
99 | * @param prxpd A pointer to rxpd structure of received packet | ||
100 | * @return n/a | ||
101 | */ | ||
102 | static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) | ||
103 | { | ||
104 | |||
105 | lbs_deb_enter(LBS_DEB_RX); | ||
106 | |||
107 | lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf); | ||
108 | lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n", | ||
109 | priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, | ||
110 | priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); | ||
111 | |||
112 | priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr; | ||
113 | priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf; | ||
114 | lbs_save_rawSNRNF(priv, p_rx_pd); | ||
115 | |||
116 | priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE; | ||
117 | priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE; | ||
118 | lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n", | ||
119 | priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, | ||
120 | priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); | ||
121 | |||
122 | priv->RSSI[TYPE_RXPD][TYPE_NOAVG] = | ||
123 | CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG], | ||
124 | priv->NF[TYPE_RXPD][TYPE_NOAVG]); | ||
125 | |||
126 | priv->RSSI[TYPE_RXPD][TYPE_AVG] = | ||
127 | CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, | ||
128 | priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); | ||
129 | |||
130 | lbs_deb_leave(LBS_DEB_RX); | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * @brief This function processes received packet and forwards it | 43 | * @brief This function processes received packet and forwards it |
135 | * to kernel/upper layer | 44 | * to kernel/upper layer |
136 | * | 45 | * |
@@ -154,7 +63,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
154 | 63 | ||
155 | skb->ip_summed = CHECKSUM_NONE; | 64 | skb->ip_summed = CHECKSUM_NONE; |
156 | 65 | ||
157 | if (priv->monitormode) | 66 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) |
158 | return process_rxed_802_11_packet(priv, skb); | 67 | return process_rxed_802_11_packet(priv, skb); |
159 | 68 | ||
160 | p_rx_pd = (struct rxpd *) skb->data; | 69 | p_rx_pd = (struct rxpd *) skb->data; |
@@ -225,13 +134,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
225 | */ | 134 | */ |
226 | skb_pull(skb, hdrchop); | 135 | skb_pull(skb, hdrchop); |
227 | 136 | ||
228 | /* Take the data rate from the rxpd structure | 137 | priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate); |
229 | * only if the rate is auto | ||
230 | */ | ||
231 | if (priv->enablehwauto) | ||
232 | priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate); | ||
233 | |||
234 | lbs_compute_rssi(priv, p_rx_pd); | ||
235 | 138 | ||
236 | lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); | 139 | lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); |
237 | dev->stats.rx_bytes += skb->len; | 140 | dev->stats.rx_bytes += skb->len; |
@@ -352,20 +255,18 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, | |||
352 | pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr)); | 255 | pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr)); |
353 | memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr)); | 256 | memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr)); |
354 | 257 | ||
355 | /* Take the data rate from the rxpd structure | 258 | priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate); |
356 | * only if the rate is auto | ||
357 | */ | ||
358 | if (priv->enablehwauto) | ||
359 | priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate); | ||
360 | |||
361 | lbs_compute_rssi(priv, prxpd); | ||
362 | 259 | ||
363 | lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); | 260 | lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); |
364 | dev->stats.rx_bytes += skb->len; | 261 | dev->stats.rx_bytes += skb->len; |
365 | dev->stats.rx_packets++; | 262 | dev->stats.rx_packets++; |
366 | 263 | ||
367 | skb->protocol = eth_type_trans(skb, priv->rtap_net_dev); | 264 | skb->protocol = eth_type_trans(skb, priv->dev); |
368 | netif_rx(skb); | 265 | |
266 | if (in_interrupt()) | ||
267 | netif_rx(skb); | ||
268 | else | ||
269 | netif_rx_ni(skb); | ||
369 | 270 | ||
370 | ret = 0; | 271 | ret = 0; |
371 | 272 | ||
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c deleted file mode 100644 index 24cd54b3a806..000000000000 --- a/drivers/net/wireless/libertas/scan.c +++ /dev/null | |||
@@ -1,1354 +0,0 @@ | |||
1 | /** | ||
2 | * Functions implementing wlan scan IOCTL and firmware command APIs | ||
3 | * | ||
4 | * IOCTL handlers as well as command preperation and response routines | ||
5 | * for sending scan commands to the firmware. | ||
6 | */ | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/etherdevice.h> | ||
11 | #include <linux/if_arp.h> | ||
12 | #include <asm/unaligned.h> | ||
13 | #include <net/lib80211.h> | ||
14 | |||
15 | #include "host.h" | ||
16 | #include "dev.h" | ||
17 | #include "scan.h" | ||
18 | #include "assoc.h" | ||
19 | #include "wext.h" | ||
20 | #include "cmd.h" | ||
21 | |||
22 | //! Approximate amount of data needed to pass a scan result back to iwlist | ||
23 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ | ||
24 | + IEEE80211_MAX_SSID_LEN \ | ||
25 | + IW_EV_UINT_LEN \ | ||
26 | + IW_EV_FREQ_LEN \ | ||
27 | + IW_EV_QUAL_LEN \ | ||
28 | + IEEE80211_MAX_SSID_LEN \ | ||
29 | + IW_EV_PARAM_LEN \ | ||
30 | + 40) /* 40 for WPAIE */ | ||
31 | |||
32 | //! Memory needed to store a max sized channel List TLV for a firmware scan | ||
33 | #define CHAN_TLV_MAX_SIZE (sizeof(struct mrvl_ie_header) \ | ||
34 | + (MRVDRV_MAX_CHANNELS_PER_SCAN \ | ||
35 | * sizeof(struct chanscanparamset))) | ||
36 | |||
37 | //! Memory needed to store a max number/size SSID TLV for a firmware scan | ||
38 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvl_ie_ssid_param_set)) | ||
39 | |||
40 | //! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max | ||
41 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ | ||
42 | + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE) | ||
43 | |||
44 | //! The maximum number of channels the firmware can scan per command | ||
45 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 | ||
46 | |||
47 | /** | ||
48 | * @brief Number of channels to scan per firmware scan command issuance. | ||
49 | * | ||
50 | * Number restricted to prevent hitting the limit on the amount of scan data | ||
51 | * returned in a single firmware scan command. | ||
52 | */ | ||
53 | #define MRVDRV_CHANNELS_PER_SCAN_CMD 4 | ||
54 | |||
55 | //! Scan time specified in the channel TLV for each channel for passive scans | ||
56 | #define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100 | ||
57 | |||
58 | //! Scan time specified in the channel TLV for each channel for active scans | ||
59 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 | ||
60 | |||
61 | #define DEFAULT_MAX_SCAN_AGE (15 * HZ) | ||
62 | |||
63 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, | ||
64 | struct cmd_header *resp); | ||
65 | |||
66 | /*********************************************************************/ | ||
67 | /* */ | ||
68 | /* Misc helper functions */ | ||
69 | /* */ | ||
70 | /*********************************************************************/ | ||
71 | |||
72 | /** | ||
73 | * @brief Unsets the MSB on basic rates | ||
74 | * | ||
75 | * Scan through an array and unset the MSB for basic data rates. | ||
76 | * | ||
77 | * @param rates buffer of data rates | ||
78 | * @param len size of buffer | ||
79 | */ | ||
80 | static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) | ||
81 | { | ||
82 | int i; | ||
83 | |||
84 | for (i = 0; i < len; i++) | ||
85 | rates[i] &= 0x7f; | ||
86 | } | ||
87 | |||
88 | |||
89 | static inline void clear_bss_descriptor(struct bss_descriptor *bss) | ||
90 | { | ||
91 | /* Don't blow away ->list, just BSS data */ | ||
92 | memset(bss, 0, offsetof(struct bss_descriptor, list)); | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * @brief Compare two SSIDs | ||
97 | * | ||
98 | * @param ssid1 A pointer to ssid to compare | ||
99 | * @param ssid2 A pointer to ssid to compare | ||
100 | * | ||
101 | * @return 0: ssid is same, otherwise is different | ||
102 | */ | ||
103 | int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, | ||
104 | uint8_t ssid2_len) | ||
105 | { | ||
106 | if (ssid1_len != ssid2_len) | ||
107 | return -1; | ||
108 | |||
109 | return memcmp(ssid1, ssid2, ssid1_len); | ||
110 | } | ||
111 | |||
112 | static inline int is_same_network(struct bss_descriptor *src, | ||
113 | struct bss_descriptor *dst) | ||
114 | { | ||
115 | /* A network is only a duplicate if the channel, BSSID, and ESSID | ||
116 | * all match. We treat all <hidden> with the same BSSID and channel | ||
117 | * as one network */ | ||
118 | return ((src->ssid_len == dst->ssid_len) && | ||
119 | (src->channel == dst->channel) && | ||
120 | !compare_ether_addr(src->bssid, dst->bssid) && | ||
121 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); | ||
122 | } | ||
123 | |||
124 | |||
125 | |||
126 | /*********************************************************************/ | ||
127 | /* */ | ||
128 | /* Region channel support */ | ||
129 | /* */ | ||
130 | /*********************************************************************/ | ||
131 | |||
132 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ | ||
133 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ | ||
134 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ | ||
135 | #define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */ | ||
136 | #define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */ | ||
137 | |||
138 | /* Format { channel, frequency (MHz), maxtxpower } */ | ||
139 | /* band: 'B/G', region: USA FCC/Canada IC */ | ||
140 | static struct chan_freq_power channel_freq_power_US_BG[] = { | ||
141 | {1, 2412, LBS_TX_PWR_US_DEFAULT}, | ||
142 | {2, 2417, LBS_TX_PWR_US_DEFAULT}, | ||
143 | {3, 2422, LBS_TX_PWR_US_DEFAULT}, | ||
144 | {4, 2427, LBS_TX_PWR_US_DEFAULT}, | ||
145 | {5, 2432, LBS_TX_PWR_US_DEFAULT}, | ||
146 | {6, 2437, LBS_TX_PWR_US_DEFAULT}, | ||
147 | {7, 2442, LBS_TX_PWR_US_DEFAULT}, | ||
148 | {8, 2447, LBS_TX_PWR_US_DEFAULT}, | ||
149 | {9, 2452, LBS_TX_PWR_US_DEFAULT}, | ||
150 | {10, 2457, LBS_TX_PWR_US_DEFAULT}, | ||
151 | {11, 2462, LBS_TX_PWR_US_DEFAULT} | ||
152 | }; | ||
153 | |||
154 | /* band: 'B/G', region: Europe ETSI */ | ||
155 | static struct chan_freq_power channel_freq_power_EU_BG[] = { | ||
156 | {1, 2412, LBS_TX_PWR_EMEA_DEFAULT}, | ||
157 | {2, 2417, LBS_TX_PWR_EMEA_DEFAULT}, | ||
158 | {3, 2422, LBS_TX_PWR_EMEA_DEFAULT}, | ||
159 | {4, 2427, LBS_TX_PWR_EMEA_DEFAULT}, | ||
160 | {5, 2432, LBS_TX_PWR_EMEA_DEFAULT}, | ||
161 | {6, 2437, LBS_TX_PWR_EMEA_DEFAULT}, | ||
162 | {7, 2442, LBS_TX_PWR_EMEA_DEFAULT}, | ||
163 | {8, 2447, LBS_TX_PWR_EMEA_DEFAULT}, | ||
164 | {9, 2452, LBS_TX_PWR_EMEA_DEFAULT}, | ||
165 | {10, 2457, LBS_TX_PWR_EMEA_DEFAULT}, | ||
166 | {11, 2462, LBS_TX_PWR_EMEA_DEFAULT}, | ||
167 | {12, 2467, LBS_TX_PWR_EMEA_DEFAULT}, | ||
168 | {13, 2472, LBS_TX_PWR_EMEA_DEFAULT} | ||
169 | }; | ||
170 | |||
171 | /* band: 'B/G', region: Spain */ | ||
172 | static struct chan_freq_power channel_freq_power_SPN_BG[] = { | ||
173 | {10, 2457, LBS_TX_PWR_DEFAULT}, | ||
174 | {11, 2462, LBS_TX_PWR_DEFAULT} | ||
175 | }; | ||
176 | |||
177 | /* band: 'B/G', region: France */ | ||
178 | static struct chan_freq_power channel_freq_power_FR_BG[] = { | ||
179 | {10, 2457, LBS_TX_PWR_FR_DEFAULT}, | ||
180 | {11, 2462, LBS_TX_PWR_FR_DEFAULT}, | ||
181 | {12, 2467, LBS_TX_PWR_FR_DEFAULT}, | ||
182 | {13, 2472, LBS_TX_PWR_FR_DEFAULT} | ||
183 | }; | ||
184 | |||
185 | /* band: 'B/G', region: Japan */ | ||
186 | static struct chan_freq_power channel_freq_power_JPN_BG[] = { | ||
187 | {1, 2412, LBS_TX_PWR_JP_DEFAULT}, | ||
188 | {2, 2417, LBS_TX_PWR_JP_DEFAULT}, | ||
189 | {3, 2422, LBS_TX_PWR_JP_DEFAULT}, | ||
190 | {4, 2427, LBS_TX_PWR_JP_DEFAULT}, | ||
191 | {5, 2432, LBS_TX_PWR_JP_DEFAULT}, | ||
192 | {6, 2437, LBS_TX_PWR_JP_DEFAULT}, | ||
193 | {7, 2442, LBS_TX_PWR_JP_DEFAULT}, | ||
194 | {8, 2447, LBS_TX_PWR_JP_DEFAULT}, | ||
195 | {9, 2452, LBS_TX_PWR_JP_DEFAULT}, | ||
196 | {10, 2457, LBS_TX_PWR_JP_DEFAULT}, | ||
197 | {11, 2462, LBS_TX_PWR_JP_DEFAULT}, | ||
198 | {12, 2467, LBS_TX_PWR_JP_DEFAULT}, | ||
199 | {13, 2472, LBS_TX_PWR_JP_DEFAULT}, | ||
200 | {14, 2484, LBS_TX_PWR_JP_DEFAULT} | ||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * the structure for channel, frequency and power | ||
205 | */ | ||
206 | struct region_cfp_table { | ||
207 | u8 region; | ||
208 | struct chan_freq_power *cfp_BG; | ||
209 | int cfp_no_BG; | ||
210 | }; | ||
211 | |||
212 | /** | ||
213 | * the structure for the mapping between region and CFP | ||
214 | */ | ||
215 | static struct region_cfp_table region_cfp_table[] = { | ||
216 | {0x10, /*US FCC */ | ||
217 | channel_freq_power_US_BG, | ||
218 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
219 | } | ||
220 | , | ||
221 | {0x20, /*CANADA IC */ | ||
222 | channel_freq_power_US_BG, | ||
223 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
224 | } | ||
225 | , | ||
226 | {0x30, /*EU*/ channel_freq_power_EU_BG, | ||
227 | ARRAY_SIZE(channel_freq_power_EU_BG), | ||
228 | } | ||
229 | , | ||
230 | {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, | ||
231 | ARRAY_SIZE(channel_freq_power_SPN_BG), | ||
232 | } | ||
233 | , | ||
234 | {0x32, /*FRANCE*/ channel_freq_power_FR_BG, | ||
235 | ARRAY_SIZE(channel_freq_power_FR_BG), | ||
236 | } | ||
237 | , | ||
238 | {0x40, /*JAPAN*/ channel_freq_power_JPN_BG, | ||
239 | ARRAY_SIZE(channel_freq_power_JPN_BG), | ||
240 | } | ||
241 | , | ||
242 | /*Add new region here */ | ||
243 | }; | ||
244 | |||
245 | /** | ||
246 | * @brief This function finds the CFP in | ||
247 | * region_cfp_table based on region and band parameter. | ||
248 | * | ||
249 | * @param region The region code | ||
250 | * @param band The band | ||
251 | * @param cfp_no A pointer to CFP number | ||
252 | * @return A pointer to CFP | ||
253 | */ | ||
254 | static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) | ||
255 | { | ||
256 | int i, end; | ||
257 | |||
258 | lbs_deb_enter(LBS_DEB_MAIN); | ||
259 | |||
260 | end = ARRAY_SIZE(region_cfp_table); | ||
261 | |||
262 | for (i = 0; i < end ; i++) { | ||
263 | lbs_deb_main("region_cfp_table[i].region=%d\n", | ||
264 | region_cfp_table[i].region); | ||
265 | if (region_cfp_table[i].region == region) { | ||
266 | *cfp_no = region_cfp_table[i].cfp_no_BG; | ||
267 | lbs_deb_leave(LBS_DEB_MAIN); | ||
268 | return region_cfp_table[i].cfp_BG; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); | ||
273 | return NULL; | ||
274 | } | ||
275 | |||
276 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) | ||
277 | { | ||
278 | int ret = 0; | ||
279 | int i = 0; | ||
280 | |||
281 | struct chan_freq_power *cfp; | ||
282 | int cfp_no; | ||
283 | |||
284 | lbs_deb_enter(LBS_DEB_MAIN); | ||
285 | |||
286 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); | ||
287 | |||
288 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
289 | if (cfp != NULL) { | ||
290 | priv->region_channel[i].nrcfp = cfp_no; | ||
291 | priv->region_channel[i].CFP = cfp; | ||
292 | } else { | ||
293 | lbs_deb_main("wrong region code %#x in band B/G\n", | ||
294 | region); | ||
295 | ret = -1; | ||
296 | goto out; | ||
297 | } | ||
298 | priv->region_channel[i].valid = 1; | ||
299 | priv->region_channel[i].region = region; | ||
300 | priv->region_channel[i].band = band; | ||
301 | i++; | ||
302 | out: | ||
303 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | |||
308 | |||
309 | |||
310 | /*********************************************************************/ | ||
311 | /* */ | ||
312 | /* Main scanning support */ | ||
313 | /* */ | ||
314 | /*********************************************************************/ | ||
315 | |||
316 | /** | ||
317 | * @brief Create a channel list for the driver to scan based on region info | ||
318 | * | ||
319 | * Only used from lbs_scan_setup_scan_config() | ||
320 | * | ||
321 | * Use the driver region/band information to construct a comprehensive list | ||
322 | * of channels to scan. This routine is used for any scan that is not | ||
323 | * provided a specific channel list to scan. | ||
324 | * | ||
325 | * @param priv A pointer to struct lbs_private structure | ||
326 | * @param scanchanlist Output parameter: resulting channel list to scan | ||
327 | * | ||
328 | * @return void | ||
329 | */ | ||
330 | static int lbs_scan_create_channel_list(struct lbs_private *priv, | ||
331 | struct chanscanparamset *scanchanlist) | ||
332 | { | ||
333 | struct region_channel *scanregion; | ||
334 | struct chan_freq_power *cfp; | ||
335 | int rgnidx; | ||
336 | int chanidx; | ||
337 | int nextchan; | ||
338 | uint8_t scantype; | ||
339 | |||
340 | chanidx = 0; | ||
341 | |||
342 | /* Set the default scan type to the user specified type, will later | ||
343 | * be changed to passive on a per channel basis if restricted by | ||
344 | * regulatory requirements (11d or 11h) | ||
345 | */ | ||
346 | scantype = CMD_SCAN_TYPE_ACTIVE; | ||
347 | |||
348 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { | ||
349 | if (!priv->region_channel[rgnidx].valid) | ||
350 | continue; | ||
351 | scanregion = &priv->region_channel[rgnidx]; | ||
352 | |||
353 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { | ||
354 | struct chanscanparamset *chan = &scanchanlist[chanidx]; | ||
355 | |||
356 | cfp = scanregion->CFP + nextchan; | ||
357 | |||
358 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) | ||
359 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; | ||
360 | |||
361 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { | ||
362 | chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); | ||
363 | chan->chanscanmode.passivescan = 1; | ||
364 | } else { | ||
365 | chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); | ||
366 | chan->chanscanmode.passivescan = 0; | ||
367 | } | ||
368 | |||
369 | chan->channumber = cfp->channel; | ||
370 | } | ||
371 | } | ||
372 | return chanidx; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Add SSID TLV of the form: | ||
377 | * | ||
378 | * TLV-ID SSID 00 00 | ||
379 | * length 06 00 | ||
380 | * ssid 4d 4e 54 45 53 54 | ||
381 | */ | ||
382 | static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) | ||
383 | { | ||
384 | struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv; | ||
385 | |||
386 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
387 | ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); | ||
388 | memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len); | ||
389 | return sizeof(ssid_tlv->header) + priv->scan_ssid_len; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Add CHANLIST TLV of the form | ||
394 | * | ||
395 | * TLV-ID CHANLIST 01 01 | ||
396 | * length 5b 00 | ||
397 | * channel 1 00 01 00 00 00 64 00 | ||
398 | * radio type 00 | ||
399 | * channel 01 | ||
400 | * scan type 00 | ||
401 | * min scan time 00 00 | ||
402 | * max scan time 64 00 | ||
403 | * channel 2 00 02 00 00 00 64 00 | ||
404 | * channel 3 00 03 00 00 00 64 00 | ||
405 | * channel 4 00 04 00 00 00 64 00 | ||
406 | * channel 5 00 05 00 00 00 64 00 | ||
407 | * channel 6 00 06 00 00 00 64 00 | ||
408 | * channel 7 00 07 00 00 00 64 00 | ||
409 | * channel 8 00 08 00 00 00 64 00 | ||
410 | * channel 9 00 09 00 00 00 64 00 | ||
411 | * channel 10 00 0a 00 00 00 64 00 | ||
412 | * channel 11 00 0b 00 00 00 64 00 | ||
413 | * channel 12 00 0c 00 00 00 64 00 | ||
414 | * channel 13 00 0d 00 00 00 64 00 | ||
415 | * | ||
416 | */ | ||
417 | static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, | ||
418 | struct chanscanparamset *chan_list, | ||
419 | int chan_count) | ||
420 | { | ||
421 | size_t size = sizeof(struct chanscanparamset) *chan_count; | ||
422 | struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv; | ||
423 | |||
424 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); | ||
425 | memcpy(chan_tlv->chanscanparam, chan_list, size); | ||
426 | chan_tlv->header.len = cpu_to_le16(size); | ||
427 | return sizeof(chan_tlv->header) + size; | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * Add RATES TLV of the form | ||
432 | * | ||
433 | * TLV-ID RATES 01 00 | ||
434 | * length 0e 00 | ||
435 | * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c | ||
436 | * | ||
437 | * The rates are in lbs_bg_rates[], but for the 802.11b | ||
438 | * rates the high bit isn't set. | ||
439 | */ | ||
440 | static int lbs_scan_add_rates_tlv(uint8_t *tlv) | ||
441 | { | ||
442 | int i; | ||
443 | struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; | ||
444 | |||
445 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | ||
446 | tlv += sizeof(rate_tlv->header); | ||
447 | for (i = 0; i < MAX_RATES; i++) { | ||
448 | *tlv = lbs_bg_rates[i]; | ||
449 | if (*tlv == 0) | ||
450 | break; | ||
451 | /* This code makes sure that the 802.11b rates (1 MBit/s, 2 | ||
452 | MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set. | ||
453 | Note that the values are MBit/s * 2, to mark them as | ||
454 | basic rates so that the firmware likes it better */ | ||
455 | if (*tlv == 0x02 || *tlv == 0x04 || | ||
456 | *tlv == 0x0b || *tlv == 0x16) | ||
457 | *tlv |= 0x80; | ||
458 | tlv++; | ||
459 | } | ||
460 | rate_tlv->header.len = cpu_to_le16(i); | ||
461 | return sizeof(rate_tlv->header) + i; | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * Generate the CMD_802_11_SCAN command with the proper tlv | ||
466 | * for a bunch of channels. | ||
467 | */ | ||
468 | static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, | ||
469 | struct chanscanparamset *chan_list, int chan_count) | ||
470 | { | ||
471 | int ret = -ENOMEM; | ||
472 | struct cmd_ds_802_11_scan *scan_cmd; | ||
473 | uint8_t *tlv; /* pointer into our current, growing TLV storage area */ | ||
474 | |||
475 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d", | ||
476 | bsstype, chan_list ? chan_list[0].channumber : -1, | ||
477 | chan_count); | ||
478 | |||
479 | /* create the fixed part for scan command */ | ||
480 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); | ||
481 | if (scan_cmd == NULL) | ||
482 | goto out; | ||
483 | |||
484 | tlv = scan_cmd->tlvbuffer; | ||
485 | /* TODO: do we need to scan for a specific BSSID? | ||
486 | memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */ | ||
487 | scan_cmd->bsstype = bsstype; | ||
488 | |||
489 | /* add TLVs */ | ||
490 | if (priv->scan_ssid_len) | ||
491 | tlv += lbs_scan_add_ssid_tlv(priv, tlv); | ||
492 | if (chan_list && chan_count) | ||
493 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); | ||
494 | tlv += lbs_scan_add_rates_tlv(tlv); | ||
495 | |||
496 | /* This is the final data we are about to send */ | ||
497 | scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd); | ||
498 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, | ||
499 | sizeof(*scan_cmd)); | ||
500 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, | ||
501 | tlv - scan_cmd->tlvbuffer); | ||
502 | |||
503 | ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, | ||
504 | le16_to_cpu(scan_cmd->hdr.size), | ||
505 | lbs_ret_80211_scan, 0); | ||
506 | |||
507 | out: | ||
508 | kfree(scan_cmd); | ||
509 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * @brief Internal function used to start a scan based on an input config | ||
515 | * | ||
516 | * Use the input user scan configuration information when provided in | ||
517 | * order to send the appropriate scan commands to firmware to populate or | ||
518 | * update the internal driver scan table | ||
519 | * | ||
520 | * @param priv A pointer to struct lbs_private structure | ||
521 | * @param full_scan Do a full-scan (blocking) | ||
522 | * | ||
523 | * @return 0 or < 0 if error | ||
524 | */ | ||
525 | int lbs_scan_networks(struct lbs_private *priv, int full_scan) | ||
526 | { | ||
527 | int ret = -ENOMEM; | ||
528 | struct chanscanparamset *chan_list; | ||
529 | struct chanscanparamset *curr_chans; | ||
530 | int chan_count; | ||
531 | uint8_t bsstype = CMD_BSS_TYPE_ANY; | ||
532 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; | ||
533 | union iwreq_data wrqu; | ||
534 | #ifdef CONFIG_LIBERTAS_DEBUG | ||
535 | struct bss_descriptor *iter; | ||
536 | int i = 0; | ||
537 | DECLARE_SSID_BUF(ssid); | ||
538 | #endif | ||
539 | |||
540 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); | ||
541 | |||
542 | /* Cancel any partial outstanding partial scans if this scan | ||
543 | * is a full scan. | ||
544 | */ | ||
545 | if (full_scan && delayed_work_pending(&priv->scan_work)) | ||
546 | cancel_delayed_work(&priv->scan_work); | ||
547 | |||
548 | /* User-specified bsstype or channel list | ||
549 | TODO: this can be implemented if some user-space application | ||
550 | need the feature. Formerly, it was accessible from debugfs, | ||
551 | but then nowhere used. | ||
552 | if (user_cfg) { | ||
553 | if (user_cfg->bsstype) | ||
554 | bsstype = user_cfg->bsstype; | ||
555 | } */ | ||
556 | |||
557 | lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype); | ||
558 | |||
559 | /* Create list of channels to scan */ | ||
560 | chan_list = kzalloc(sizeof(struct chanscanparamset) * | ||
561 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); | ||
562 | if (!chan_list) { | ||
563 | lbs_pr_alert("SCAN: chan_list empty\n"); | ||
564 | goto out; | ||
565 | } | ||
566 | |||
567 | /* We want to scan all channels */ | ||
568 | chan_count = lbs_scan_create_channel_list(priv, chan_list); | ||
569 | |||
570 | netif_stop_queue(priv->dev); | ||
571 | if (priv->mesh_dev) | ||
572 | netif_stop_queue(priv->mesh_dev); | ||
573 | |||
574 | /* Prepare to continue an interrupted scan */ | ||
575 | lbs_deb_scan("chan_count %d, scan_channel %d\n", | ||
576 | chan_count, priv->scan_channel); | ||
577 | curr_chans = chan_list; | ||
578 | /* advance channel list by already-scanned-channels */ | ||
579 | if (priv->scan_channel > 0) { | ||
580 | curr_chans += priv->scan_channel; | ||
581 | chan_count -= priv->scan_channel; | ||
582 | } | ||
583 | |||
584 | /* Send scan command(s) | ||
585 | * numchannels contains the number of channels we should maximally scan | ||
586 | * chan_count is the total number of channels to scan | ||
587 | */ | ||
588 | |||
589 | while (chan_count) { | ||
590 | int to_scan = min(numchannels, chan_count); | ||
591 | lbs_deb_scan("scanning %d of %d channels\n", | ||
592 | to_scan, chan_count); | ||
593 | ret = lbs_do_scan(priv, bsstype, curr_chans, | ||
594 | to_scan); | ||
595 | if (ret) { | ||
596 | lbs_pr_err("SCAN_CMD failed\n"); | ||
597 | goto out2; | ||
598 | } | ||
599 | curr_chans += to_scan; | ||
600 | chan_count -= to_scan; | ||
601 | |||
602 | /* somehow schedule the next part of the scan */ | ||
603 | if (chan_count && !full_scan && | ||
604 | !priv->surpriseremoved) { | ||
605 | /* -1 marks just that we're currently scanning */ | ||
606 | if (priv->scan_channel < 0) | ||
607 | priv->scan_channel = to_scan; | ||
608 | else | ||
609 | priv->scan_channel += to_scan; | ||
610 | cancel_delayed_work(&priv->scan_work); | ||
611 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
612 | msecs_to_jiffies(300)); | ||
613 | /* skip over GIWSCAN event */ | ||
614 | goto out; | ||
615 | } | ||
616 | |||
617 | } | ||
618 | memset(&wrqu, 0, sizeof(union iwreq_data)); | ||
619 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
620 | |||
621 | #ifdef CONFIG_LIBERTAS_DEBUG | ||
622 | /* Dump the scan table */ | ||
623 | mutex_lock(&priv->lock); | ||
624 | lbs_deb_scan("scan table:\n"); | ||
625 | list_for_each_entry(iter, &priv->network_list, list) | ||
626 | lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n", | ||
627 | i++, iter->bssid, iter->rssi, | ||
628 | print_ssid(ssid, iter->ssid, iter->ssid_len)); | ||
629 | mutex_unlock(&priv->lock); | ||
630 | #endif | ||
631 | |||
632 | out2: | ||
633 | priv->scan_channel = 0; | ||
634 | |||
635 | out: | ||
636 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) | ||
637 | netif_wake_queue(priv->dev); | ||
638 | |||
639 | if (priv->mesh_dev && lbs_mesh_connected(priv) && | ||
640 | !priv->tx_pending_len) | ||
641 | netif_wake_queue(priv->mesh_dev); | ||
642 | |||
643 | kfree(chan_list); | ||
644 | |||
645 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | void lbs_scan_worker(struct work_struct *work) | ||
650 | { | ||
651 | struct lbs_private *priv = | ||
652 | container_of(work, struct lbs_private, scan_work.work); | ||
653 | |||
654 | lbs_deb_enter(LBS_DEB_SCAN); | ||
655 | lbs_scan_networks(priv, 0); | ||
656 | lbs_deb_leave(LBS_DEB_SCAN); | ||
657 | } | ||
658 | |||
659 | |||
660 | /*********************************************************************/ | ||
661 | /* */ | ||
662 | /* Result interpretation */ | ||
663 | /* */ | ||
664 | /*********************************************************************/ | ||
665 | |||
666 | /** | ||
667 | * @brief Interpret a BSS scan response returned from the firmware | ||
668 | * | ||
669 | * Parse the various fixed fields and IEs passed back for a a BSS probe | ||
670 | * response or beacon from the scan command. Record information as needed | ||
671 | * in the scan table struct bss_descriptor for that entry. | ||
672 | * | ||
673 | * @param bss Output parameter: Pointer to the BSS Entry | ||
674 | * | ||
675 | * @return 0 or -1 | ||
676 | */ | ||
677 | static int lbs_process_bss(struct bss_descriptor *bss, | ||
678 | uint8_t **pbeaconinfo, int *bytesleft) | ||
679 | { | ||
680 | struct ieee_ie_fh_param_set *fh; | ||
681 | struct ieee_ie_ds_param_set *ds; | ||
682 | struct ieee_ie_cf_param_set *cf; | ||
683 | struct ieee_ie_ibss_param_set *ibss; | ||
684 | DECLARE_SSID_BUF(ssid); | ||
685 | uint8_t *pos, *end, *p; | ||
686 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; | ||
687 | uint16_t beaconsize = 0; | ||
688 | int ret; | ||
689 | |||
690 | lbs_deb_enter(LBS_DEB_SCAN); | ||
691 | |||
692 | if (*bytesleft >= sizeof(beaconsize)) { | ||
693 | /* Extract & convert beacon size from the command buffer */ | ||
694 | beaconsize = get_unaligned_le16(*pbeaconinfo); | ||
695 | *bytesleft -= sizeof(beaconsize); | ||
696 | *pbeaconinfo += sizeof(beaconsize); | ||
697 | } | ||
698 | |||
699 | if (beaconsize == 0 || beaconsize > *bytesleft) { | ||
700 | *pbeaconinfo += *bytesleft; | ||
701 | *bytesleft = 0; | ||
702 | ret = -1; | ||
703 | goto done; | ||
704 | } | ||
705 | |||
706 | /* Initialize the current working beacon pointer for this BSS iteration */ | ||
707 | pos = *pbeaconinfo; | ||
708 | end = pos + beaconsize; | ||
709 | |||
710 | /* Advance the return beacon pointer past the current beacon */ | ||
711 | *pbeaconinfo += beaconsize; | ||
712 | *bytesleft -= beaconsize; | ||
713 | |||
714 | memcpy(bss->bssid, pos, ETH_ALEN); | ||
715 | lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid); | ||
716 | pos += ETH_ALEN; | ||
717 | |||
718 | if ((end - pos) < 12) { | ||
719 | lbs_deb_scan("process_bss: Not enough bytes left\n"); | ||
720 | ret = -1; | ||
721 | goto done; | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | * next 4 fields are RSSI, time stamp, beacon interval, | ||
726 | * and capability information | ||
727 | */ | ||
728 | |||
729 | /* RSSI is 1 byte long */ | ||
730 | bss->rssi = *pos; | ||
731 | lbs_deb_scan("process_bss: RSSI %d\n", *pos); | ||
732 | pos++; | ||
733 | |||
734 | /* time stamp is 8 bytes long */ | ||
735 | pos += 8; | ||
736 | |||
737 | /* beacon interval is 2 bytes long */ | ||
738 | bss->beaconperiod = get_unaligned_le16(pos); | ||
739 | pos += 2; | ||
740 | |||
741 | /* capability information is 2 bytes long */ | ||
742 | bss->capability = get_unaligned_le16(pos); | ||
743 | lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability); | ||
744 | pos += 2; | ||
745 | |||
746 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | ||
747 | lbs_deb_scan("process_bss: WEP enabled\n"); | ||
748 | if (bss->capability & WLAN_CAPABILITY_IBSS) | ||
749 | bss->mode = IW_MODE_ADHOC; | ||
750 | else | ||
751 | bss->mode = IW_MODE_INFRA; | ||
752 | |||
753 | /* rest of the current buffer are IE's */ | ||
754 | lbs_deb_scan("process_bss: IE len %zd\n", end - pos); | ||
755 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos); | ||
756 | |||
757 | /* process variable IE */ | ||
758 | while (pos <= end - 2) { | ||
759 | if (pos + pos[1] > end) { | ||
760 | lbs_deb_scan("process_bss: error in processing IE, " | ||
761 | "bytes left < IE length\n"); | ||
762 | break; | ||
763 | } | ||
764 | |||
765 | switch (pos[0]) { | ||
766 | case WLAN_EID_SSID: | ||
767 | bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]); | ||
768 | memcpy(bss->ssid, pos + 2, bss->ssid_len); | ||
769 | lbs_deb_scan("got SSID IE: '%s', len %u\n", | ||
770 | print_ssid(ssid, bss->ssid, bss->ssid_len), | ||
771 | bss->ssid_len); | ||
772 | break; | ||
773 | |||
774 | case WLAN_EID_SUPP_RATES: | ||
775 | n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]); | ||
776 | memcpy(bss->rates, pos + 2, n_basic_rates); | ||
777 | got_basic_rates = 1; | ||
778 | lbs_deb_scan("got RATES IE\n"); | ||
779 | break; | ||
780 | |||
781 | case WLAN_EID_FH_PARAMS: | ||
782 | fh = (struct ieee_ie_fh_param_set *) pos; | ||
783 | memcpy(&bss->phy.fh, fh, sizeof(*fh)); | ||
784 | lbs_deb_scan("got FH IE\n"); | ||
785 | break; | ||
786 | |||
787 | case WLAN_EID_DS_PARAMS: | ||
788 | ds = (struct ieee_ie_ds_param_set *) pos; | ||
789 | bss->channel = ds->channel; | ||
790 | memcpy(&bss->phy.ds, ds, sizeof(*ds)); | ||
791 | lbs_deb_scan("got DS IE, channel %d\n", bss->channel); | ||
792 | break; | ||
793 | |||
794 | case WLAN_EID_CF_PARAMS: | ||
795 | cf = (struct ieee_ie_cf_param_set *) pos; | ||
796 | memcpy(&bss->ss.cf, cf, sizeof(*cf)); | ||
797 | lbs_deb_scan("got CF IE\n"); | ||
798 | break; | ||
799 | |||
800 | case WLAN_EID_IBSS_PARAMS: | ||
801 | ibss = (struct ieee_ie_ibss_param_set *) pos; | ||
802 | bss->atimwindow = ibss->atimwindow; | ||
803 | memcpy(&bss->ss.ibss, ibss, sizeof(*ibss)); | ||
804 | lbs_deb_scan("got IBSS IE\n"); | ||
805 | break; | ||
806 | |||
807 | case WLAN_EID_EXT_SUPP_RATES: | ||
808 | /* only process extended supported rate if data rate is | ||
809 | * already found. Data rate IE should come before | ||
810 | * extended supported rate IE | ||
811 | */ | ||
812 | lbs_deb_scan("got RATESEX IE\n"); | ||
813 | if (!got_basic_rates) { | ||
814 | lbs_deb_scan("... but ignoring it\n"); | ||
815 | break; | ||
816 | } | ||
817 | |||
818 | n_ex_rates = pos[1]; | ||
819 | if (n_basic_rates + n_ex_rates > MAX_RATES) | ||
820 | n_ex_rates = MAX_RATES - n_basic_rates; | ||
821 | |||
822 | p = bss->rates + n_basic_rates; | ||
823 | memcpy(p, pos + 2, n_ex_rates); | ||
824 | break; | ||
825 | |||
826 | case WLAN_EID_GENERIC: | ||
827 | if (pos[1] >= 4 && | ||
828 | pos[2] == 0x00 && pos[3] == 0x50 && | ||
829 | pos[4] == 0xf2 && pos[5] == 0x01) { | ||
830 | bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN); | ||
831 | memcpy(bss->wpa_ie, pos, bss->wpa_ie_len); | ||
832 | lbs_deb_scan("got WPA IE\n"); | ||
833 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, | ||
834 | bss->wpa_ie_len); | ||
835 | } else if (pos[1] >= MARVELL_MESH_IE_LENGTH && | ||
836 | pos[2] == 0x00 && pos[3] == 0x50 && | ||
837 | pos[4] == 0x43 && pos[5] == 0x04) { | ||
838 | lbs_deb_scan("got mesh IE\n"); | ||
839 | bss->mesh = 1; | ||
840 | } else { | ||
841 | lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", | ||
842 | pos[2], pos[3], | ||
843 | pos[4], pos[5], | ||
844 | pos[1]); | ||
845 | } | ||
846 | break; | ||
847 | |||
848 | case WLAN_EID_RSN: | ||
849 | lbs_deb_scan("got RSN IE\n"); | ||
850 | bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN); | ||
851 | memcpy(bss->rsn_ie, pos, bss->rsn_ie_len); | ||
852 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", | ||
853 | bss->rsn_ie, bss->rsn_ie_len); | ||
854 | break; | ||
855 | |||
856 | default: | ||
857 | lbs_deb_scan("got IE 0x%04x, len %d\n", | ||
858 | pos[0], pos[1]); | ||
859 | break; | ||
860 | } | ||
861 | |||
862 | pos += pos[1] + 2; | ||
863 | } | ||
864 | |||
865 | /* Timestamp */ | ||
866 | bss->last_scanned = jiffies; | ||
867 | lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates)); | ||
868 | |||
869 | ret = 0; | ||
870 | |||
871 | done: | ||
872 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | /** | ||
877 | * @brief Send a scan command for all available channels filtered on a spec | ||
878 | * | ||
879 | * Used in association code and from debugfs | ||
880 | * | ||
881 | * @param priv A pointer to struct lbs_private structure | ||
882 | * @param ssid A pointer to the SSID to scan for | ||
883 | * @param ssid_len Length of the SSID | ||
884 | * | ||
885 | * @return 0-success, otherwise fail | ||
886 | */ | ||
887 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, | ||
888 | uint8_t ssid_len) | ||
889 | { | ||
890 | DECLARE_SSID_BUF(ssid_buf); | ||
891 | int ret = 0; | ||
892 | |||
893 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", | ||
894 | print_ssid(ssid_buf, ssid, ssid_len)); | ||
895 | |||
896 | if (!ssid_len) | ||
897 | goto out; | ||
898 | |||
899 | memcpy(priv->scan_ssid, ssid, ssid_len); | ||
900 | priv->scan_ssid_len = ssid_len; | ||
901 | |||
902 | lbs_scan_networks(priv, 1); | ||
903 | if (priv->surpriseremoved) { | ||
904 | ret = -1; | ||
905 | goto out; | ||
906 | } | ||
907 | |||
908 | out: | ||
909 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
910 | return ret; | ||
911 | } | ||
912 | |||
913 | |||
914 | |||
915 | |||
916 | /*********************************************************************/ | ||
917 | /* */ | ||
918 | /* Support for Wireless Extensions */ | ||
919 | /* */ | ||
920 | /*********************************************************************/ | ||
921 | |||
922 | |||
923 | #define MAX_CUSTOM_LEN 64 | ||
924 | |||
925 | static inline char *lbs_translate_scan(struct lbs_private *priv, | ||
926 | struct iw_request_info *info, | ||
927 | char *start, char *stop, | ||
928 | struct bss_descriptor *bss) | ||
929 | { | ||
930 | struct chan_freq_power *cfp; | ||
931 | char *current_val; /* For rates */ | ||
932 | struct iw_event iwe; /* Temporary buffer */ | ||
933 | int j; | ||
934 | #define PERFECT_RSSI ((uint8_t)50) | ||
935 | #define WORST_RSSI ((uint8_t)0) | ||
936 | #define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI)) | ||
937 | uint8_t rssi; | ||
938 | |||
939 | lbs_deb_enter(LBS_DEB_SCAN); | ||
940 | |||
941 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel); | ||
942 | if (!cfp) { | ||
943 | lbs_deb_scan("Invalid channel number %d\n", bss->channel); | ||
944 | start = NULL; | ||
945 | goto out; | ||
946 | } | ||
947 | |||
948 | /* First entry *MUST* be the BSSID */ | ||
949 | iwe.cmd = SIOCGIWAP; | ||
950 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
951 | memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); | ||
952 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); | ||
953 | |||
954 | /* SSID */ | ||
955 | iwe.cmd = SIOCGIWESSID; | ||
956 | iwe.u.data.flags = 1; | ||
957 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN); | ||
958 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); | ||
959 | |||
960 | /* Mode */ | ||
961 | iwe.cmd = SIOCGIWMODE; | ||
962 | iwe.u.mode = bss->mode; | ||
963 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); | ||
964 | |||
965 | /* Frequency */ | ||
966 | iwe.cmd = SIOCGIWFREQ; | ||
967 | iwe.u.freq.m = (long)cfp->freq * 100000; | ||
968 | iwe.u.freq.e = 1; | ||
969 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); | ||
970 | |||
971 | /* Add quality statistics */ | ||
972 | iwe.cmd = IWEVQUAL; | ||
973 | iwe.u.qual.updated = IW_QUAL_ALL_UPDATED; | ||
974 | iwe.u.qual.level = SCAN_RSSI(bss->rssi); | ||
975 | |||
976 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; | ||
977 | iwe.u.qual.qual = | ||
978 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * | ||
979 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / | ||
980 | (RSSI_DIFF * RSSI_DIFF); | ||
981 | if (iwe.u.qual.qual > 100) | ||
982 | iwe.u.qual.qual = 100; | ||
983 | |||
984 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { | ||
985 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; | ||
986 | } else { | ||
987 | iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
988 | } | ||
989 | |||
990 | /* Locally created ad-hoc BSSs won't have beacons if this is the | ||
991 | * only station in the adhoc network; so get signal strength | ||
992 | * from receive statistics. | ||
993 | */ | ||
994 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate | ||
995 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | ||
996 | priv->curbssparams.ssid_len, | ||
997 | bss->ssid, bss->ssid_len)) { | ||
998 | int snr, nf; | ||
999 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | ||
1000 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | ||
1001 | iwe.u.qual.level = CAL_RSSI(snr, nf); | ||
1002 | } | ||
1003 | start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); | ||
1004 | |||
1005 | /* Add encryption capability */ | ||
1006 | iwe.cmd = SIOCGIWENCODE; | ||
1007 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) { | ||
1008 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
1009 | } else { | ||
1010 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
1011 | } | ||
1012 | iwe.u.data.length = 0; | ||
1013 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); | ||
1014 | |||
1015 | current_val = start + iwe_stream_lcp_len(info); | ||
1016 | |||
1017 | iwe.cmd = SIOCGIWRATE; | ||
1018 | iwe.u.bitrate.fixed = 0; | ||
1019 | iwe.u.bitrate.disabled = 0; | ||
1020 | iwe.u.bitrate.value = 0; | ||
1021 | |||
1022 | for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) { | ||
1023 | /* Bit rate given in 500 kb/s units */ | ||
1024 | iwe.u.bitrate.value = bss->rates[j] * 500000; | ||
1025 | current_val = iwe_stream_add_value(info, start, current_val, | ||
1026 | stop, &iwe, IW_EV_PARAM_LEN); | ||
1027 | } | ||
1028 | if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate | ||
1029 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | ||
1030 | priv->curbssparams.ssid_len, | ||
1031 | bss->ssid, bss->ssid_len)) { | ||
1032 | iwe.u.bitrate.value = 22 * 500000; | ||
1033 | current_val = iwe_stream_add_value(info, start, current_val, | ||
1034 | stop, &iwe, IW_EV_PARAM_LEN); | ||
1035 | } | ||
1036 | /* Check if we added any event */ | ||
1037 | if ((current_val - start) > iwe_stream_lcp_len(info)) | ||
1038 | start = current_val; | ||
1039 | |||
1040 | memset(&iwe, 0, sizeof(iwe)); | ||
1041 | if (bss->wpa_ie_len) { | ||
1042 | char buf[MAX_WPA_IE_LEN]; | ||
1043 | memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); | ||
1044 | iwe.cmd = IWEVGENIE; | ||
1045 | iwe.u.data.length = bss->wpa_ie_len; | ||
1046 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); | ||
1047 | } | ||
1048 | |||
1049 | memset(&iwe, 0, sizeof(iwe)); | ||
1050 | if (bss->rsn_ie_len) { | ||
1051 | char buf[MAX_WPA_IE_LEN]; | ||
1052 | memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); | ||
1053 | iwe.cmd = IWEVGENIE; | ||
1054 | iwe.u.data.length = bss->rsn_ie_len; | ||
1055 | start = iwe_stream_add_point(info, start, stop, &iwe, buf); | ||
1056 | } | ||
1057 | |||
1058 | if (bss->mesh) { | ||
1059 | char custom[MAX_CUSTOM_LEN]; | ||
1060 | char *p = custom; | ||
1061 | |||
1062 | iwe.cmd = IWEVCUSTOM; | ||
1063 | p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); | ||
1064 | iwe.u.data.length = p - custom; | ||
1065 | if (iwe.u.data.length) | ||
1066 | start = iwe_stream_add_point(info, start, stop, | ||
1067 | &iwe, custom); | ||
1068 | } | ||
1069 | |||
1070 | out: | ||
1071 | lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start); | ||
1072 | return start; | ||
1073 | } | ||
1074 | |||
1075 | |||
1076 | /** | ||
1077 | * @brief Handle Scan Network ioctl | ||
1078 | * | ||
1079 | * @param dev A pointer to net_device structure | ||
1080 | * @param info A pointer to iw_request_info structure | ||
1081 | * @param vwrq A pointer to iw_param structure | ||
1082 | * @param extra A pointer to extra data buf | ||
1083 | * | ||
1084 | * @return 0 --success, otherwise fail | ||
1085 | */ | ||
1086 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | ||
1087 | union iwreq_data *wrqu, char *extra) | ||
1088 | { | ||
1089 | DECLARE_SSID_BUF(ssid); | ||
1090 | struct lbs_private *priv = dev->ml_priv; | ||
1091 | int ret = 0; | ||
1092 | |||
1093 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1094 | |||
1095 | if (!priv->radio_on) { | ||
1096 | ret = -EINVAL; | ||
1097 | goto out; | ||
1098 | } | ||
1099 | |||
1100 | if (!netif_running(dev)) { | ||
1101 | ret = -ENETDOWN; | ||
1102 | goto out; | ||
1103 | } | ||
1104 | |||
1105 | /* mac80211 does this: | ||
1106 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1107 | if (sdata->type != IEEE80211_IF_TYPE_xxx) { | ||
1108 | ret = -EOPNOTSUPP; | ||
1109 | goto out; | ||
1110 | } | ||
1111 | */ | ||
1112 | |||
1113 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | ||
1114 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | ||
1115 | struct iw_scan_req *req = (struct iw_scan_req *)extra; | ||
1116 | priv->scan_ssid_len = req->essid_len; | ||
1117 | memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); | ||
1118 | lbs_deb_wext("set_scan, essid '%s'\n", | ||
1119 | print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len)); | ||
1120 | } else { | ||
1121 | priv->scan_ssid_len = 0; | ||
1122 | } | ||
1123 | |||
1124 | if (!delayed_work_pending(&priv->scan_work)) | ||
1125 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
1126 | msecs_to_jiffies(50)); | ||
1127 | /* set marker that currently a scan is taking place */ | ||
1128 | priv->scan_channel = -1; | ||
1129 | |||
1130 | if (priv->surpriseremoved) | ||
1131 | ret = -EIO; | ||
1132 | |||
1133 | out: | ||
1134 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | /** | ||
1140 | * @brief Handle Retrieve scan table ioctl | ||
1141 | * | ||
1142 | * @param dev A pointer to net_device structure | ||
1143 | * @param info A pointer to iw_request_info structure | ||
1144 | * @param dwrq A pointer to iw_point structure | ||
1145 | * @param extra A pointer to extra data buf | ||
1146 | * | ||
1147 | * @return 0 --success, otherwise fail | ||
1148 | */ | ||
1149 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | ||
1150 | struct iw_point *dwrq, char *extra) | ||
1151 | { | ||
1152 | #define SCAN_ITEM_SIZE 128 | ||
1153 | struct lbs_private *priv = dev->ml_priv; | ||
1154 | int err = 0; | ||
1155 | char *ev = extra; | ||
1156 | char *stop = ev + dwrq->length; | ||
1157 | struct bss_descriptor *iter_bss; | ||
1158 | struct bss_descriptor *safe; | ||
1159 | |||
1160 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1161 | |||
1162 | /* iwlist should wait until the current scan is finished */ | ||
1163 | if (priv->scan_channel) | ||
1164 | return -EAGAIN; | ||
1165 | |||
1166 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | ||
1167 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { | ||
1168 | err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | ||
1169 | CMD_OPTION_WAITFORRSP, 0, NULL); | ||
1170 | if (err) | ||
1171 | goto out; | ||
1172 | } | ||
1173 | |||
1174 | mutex_lock(&priv->lock); | ||
1175 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | ||
1176 | char *next_ev; | ||
1177 | unsigned long stale_time; | ||
1178 | |||
1179 | if (stop - ev < SCAN_ITEM_SIZE) { | ||
1180 | err = -E2BIG; | ||
1181 | break; | ||
1182 | } | ||
1183 | |||
1184 | /* For mesh device, list only mesh networks */ | ||
1185 | if (dev == priv->mesh_dev && !iter_bss->mesh) | ||
1186 | continue; | ||
1187 | |||
1188 | /* Prune old an old scan result */ | ||
1189 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; | ||
1190 | if (time_after(jiffies, stale_time)) { | ||
1191 | list_move_tail(&iter_bss->list, &priv->network_free_list); | ||
1192 | clear_bss_descriptor(iter_bss); | ||
1193 | continue; | ||
1194 | } | ||
1195 | |||
1196 | /* Translate to WE format this entry */ | ||
1197 | next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss); | ||
1198 | if (next_ev == NULL) | ||
1199 | continue; | ||
1200 | ev = next_ev; | ||
1201 | } | ||
1202 | mutex_unlock(&priv->lock); | ||
1203 | |||
1204 | dwrq->length = (ev - extra); | ||
1205 | dwrq->flags = 0; | ||
1206 | out: | ||
1207 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); | ||
1208 | return err; | ||
1209 | } | ||
1210 | |||
1211 | |||
1212 | |||
1213 | |||
1214 | /*********************************************************************/ | ||
1215 | /* */ | ||
1216 | /* Command execution */ | ||
1217 | /* */ | ||
1218 | /*********************************************************************/ | ||
1219 | |||
1220 | |||
1221 | /** | ||
1222 | * @brief This function handles the command response of scan | ||
1223 | * | ||
1224 | * Called from handle_cmd_response() in cmdrespc. | ||
1225 | * | ||
1226 | * The response buffer for the scan command has the following | ||
1227 | * memory layout: | ||
1228 | * | ||
1229 | * .-----------------------------------------------------------. | ||
1230 | * | header (4 * sizeof(u16)): Standard command response hdr | | ||
1231 | * .-----------------------------------------------------------. | ||
1232 | * | bufsize (u16) : sizeof the BSS Description data | | ||
1233 | * .-----------------------------------------------------------. | ||
1234 | * | NumOfSet (u8) : Number of BSS Descs returned | | ||
1235 | * .-----------------------------------------------------------. | ||
1236 | * | BSSDescription data (variable, size given in bufsize) | | ||
1237 | * .-----------------------------------------------------------. | ||
1238 | * | TLV data (variable, size calculated using header->size, | | ||
1239 | * | bufsize and sizeof the fixed fields above) | | ||
1240 | * .-----------------------------------------------------------. | ||
1241 | * | ||
1242 | * @param priv A pointer to struct lbs_private structure | ||
1243 | * @param resp A pointer to cmd_ds_command | ||
1244 | * | ||
1245 | * @return 0 or -1 | ||
1246 | */ | ||
1247 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, | ||
1248 | struct cmd_header *resp) | ||
1249 | { | ||
1250 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; | ||
1251 | struct bss_descriptor *iter_bss; | ||
1252 | struct bss_descriptor *safe; | ||
1253 | uint8_t *bssinfo; | ||
1254 | uint16_t scanrespsize; | ||
1255 | int bytesleft; | ||
1256 | int idx; | ||
1257 | int tlvbufsize; | ||
1258 | int ret; | ||
1259 | |||
1260 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1261 | |||
1262 | /* Prune old entries from scan table */ | ||
1263 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | ||
1264 | unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; | ||
1265 | if (time_before(jiffies, stale_time)) | ||
1266 | continue; | ||
1267 | list_move_tail (&iter_bss->list, &priv->network_free_list); | ||
1268 | clear_bss_descriptor(iter_bss); | ||
1269 | } | ||
1270 | |||
1271 | if (scanresp->nr_sets > MAX_NETWORK_COUNT) { | ||
1272 | lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n", | ||
1273 | scanresp->nr_sets, MAX_NETWORK_COUNT); | ||
1274 | ret = -1; | ||
1275 | goto done; | ||
1276 | } | ||
1277 | |||
1278 | bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize); | ||
1279 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); | ||
1280 | |||
1281 | scanrespsize = le16_to_cpu(resp->size); | ||
1282 | lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets); | ||
1283 | |||
1284 | bssinfo = scanresp->bssdesc_and_tlvbuffer; | ||
1285 | |||
1286 | /* The size of the TLV buffer is equal to the entire command response | ||
1287 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the | ||
1288 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command | ||
1289 | * response header (sizeof(struct cmd_header)) | ||
1290 | */ | ||
1291 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) | ||
1292 | + sizeof(scanresp->nr_sets) | ||
1293 | + sizeof(struct cmd_header)); | ||
1294 | |||
1295 | /* | ||
1296 | * Process each scan response returned (scanresp->nr_sets). Save | ||
1297 | * the information in the newbssentry and then insert into the | ||
1298 | * driver scan table either as an update to an existing entry | ||
1299 | * or as an addition at the end of the table | ||
1300 | */ | ||
1301 | for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) { | ||
1302 | struct bss_descriptor new; | ||
1303 | struct bss_descriptor *found = NULL; | ||
1304 | struct bss_descriptor *oldest = NULL; | ||
1305 | |||
1306 | /* Process the data fields and IEs returned for this BSS */ | ||
1307 | memset(&new, 0, sizeof (struct bss_descriptor)); | ||
1308 | if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) { | ||
1309 | /* error parsing the scan response, skipped */ | ||
1310 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); | ||
1311 | continue; | ||
1312 | } | ||
1313 | |||
1314 | /* Try to find this bss in the scan table */ | ||
1315 | list_for_each_entry (iter_bss, &priv->network_list, list) { | ||
1316 | if (is_same_network(iter_bss, &new)) { | ||
1317 | found = iter_bss; | ||
1318 | break; | ||
1319 | } | ||
1320 | |||
1321 | if ((oldest == NULL) || | ||
1322 | (iter_bss->last_scanned < oldest->last_scanned)) | ||
1323 | oldest = iter_bss; | ||
1324 | } | ||
1325 | |||
1326 | if (found) { | ||
1327 | /* found, clear it */ | ||
1328 | clear_bss_descriptor(found); | ||
1329 | } else if (!list_empty(&priv->network_free_list)) { | ||
1330 | /* Pull one from the free list */ | ||
1331 | found = list_entry(priv->network_free_list.next, | ||
1332 | struct bss_descriptor, list); | ||
1333 | list_move_tail(&found->list, &priv->network_list); | ||
1334 | } else if (oldest) { | ||
1335 | /* If there are no more slots, expire the oldest */ | ||
1336 | found = oldest; | ||
1337 | clear_bss_descriptor(found); | ||
1338 | list_move_tail(&found->list, &priv->network_list); | ||
1339 | } else { | ||
1340 | continue; | ||
1341 | } | ||
1342 | |||
1343 | lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid); | ||
1344 | |||
1345 | /* Copy the locally created newbssentry to the scan table */ | ||
1346 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); | ||
1347 | } | ||
1348 | |||
1349 | ret = 0; | ||
1350 | |||
1351 | done: | ||
1352 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
1353 | return ret; | ||
1354 | } | ||
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h deleted file mode 100644 index 8fb1706d7526..000000000000 --- a/drivers/net/wireless/libertas/scan.h +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | /** | ||
2 | * Interface for the wlan network scan routines | ||
3 | * | ||
4 | * Driver interface functions and type declarations for the scan module | ||
5 | * implemented in scan.c. | ||
6 | */ | ||
7 | #ifndef _LBS_SCAN_H | ||
8 | #define _LBS_SCAN_H | ||
9 | |||
10 | #include <net/iw_handler.h> | ||
11 | |||
12 | struct lbs_private; | ||
13 | |||
14 | #define MAX_NETWORK_COUNT 128 | ||
15 | |||
16 | /** Chan-freq-TxPower mapping table*/ | ||
17 | struct chan_freq_power { | ||
18 | /** channel Number */ | ||
19 | u16 channel; | ||
20 | /** frequency of this channel */ | ||
21 | u32 freq; | ||
22 | /** Max allowed Tx power level */ | ||
23 | u16 maxtxpower; | ||
24 | /** TRUE:channel unsupported; FLASE:supported*/ | ||
25 | u8 unsupported; | ||
26 | }; | ||
27 | |||
28 | /** region-band mapping table*/ | ||
29 | struct region_channel { | ||
30 | /** TRUE if this entry is valid */ | ||
31 | u8 valid; | ||
32 | /** region code for US, Japan ... */ | ||
33 | u8 region; | ||
34 | /** band B/G/A, used for BAND_CONFIG cmd */ | ||
35 | u8 band; | ||
36 | /** Actual No. of elements in the array below */ | ||
37 | u8 nrcfp; | ||
38 | /** chan-freq-txpower mapping table*/ | ||
39 | struct chan_freq_power *CFP; | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * @brief Maximum number of channels that can be sent in a setuserscan ioctl | ||
44 | */ | ||
45 | #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 | ||
46 | |||
47 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); | ||
48 | |||
49 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); | ||
50 | |||
51 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | ||
52 | u8 ssid_len); | ||
53 | |||
54 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | ||
55 | struct iw_point *dwrq, char *extra); | ||
56 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | ||
57 | union iwreq_data *wrqu, char *extra); | ||
58 | |||
59 | int lbs_scan_networks(struct lbs_private *priv, int full_scan); | ||
60 | |||
61 | void lbs_scan_worker(struct work_struct *work); | ||
62 | |||
63 | #endif | ||
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index a9bf658659eb..411a3bbf035e 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -4,13 +4,13 @@ | |||
4 | #include <linux/netdevice.h> | 4 | #include <linux/netdevice.h> |
5 | #include <linux/etherdevice.h> | 5 | #include <linux/etherdevice.h> |
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | #include <net/cfg80211.h> | ||
7 | 8 | ||
8 | #include "host.h" | 9 | #include "host.h" |
9 | #include "radiotap.h" | 10 | #include "radiotap.h" |
10 | #include "decl.h" | 11 | #include "decl.h" |
11 | #include "defs.h" | 12 | #include "defs.h" |
12 | #include "dev.h" | 13 | #include "dev.h" |
13 | #include "wext.h" | ||
14 | 14 | ||
15 | /** | 15 | /** |
16 | * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE | 16 | * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE |
@@ -111,7 +111,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
111 | p802x_hdr = skb->data; | 111 | p802x_hdr = skb->data; |
112 | pkt_len = skb->len; | 112 | pkt_len = skb->len; |
113 | 113 | ||
114 | if (dev == priv->rtap_net_dev) { | 114 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
115 | struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data; | 115 | struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data; |
116 | 116 | ||
117 | /* set txpd fields from the radiotap header */ | 117 | /* set txpd fields from the radiotap header */ |
@@ -147,7 +147,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
147 | dev->stats.tx_packets++; | 147 | dev->stats.tx_packets++; |
148 | dev->stats.tx_bytes += skb->len; | 148 | dev->stats.tx_bytes += skb->len; |
149 | 149 | ||
150 | if (priv->monitormode) { | 150 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
151 | /* Keep the skb to echo it back once Tx feedback is | 151 | /* Keep the skb to echo it back once Tx feedback is |
152 | received from FW */ | 152 | received from FW */ |
153 | skb_orphan(skb); | 153 | skb_orphan(skb); |
@@ -158,6 +158,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
158 | free: | 158 | free: |
159 | dev_kfree_skb_any(skb); | 159 | dev_kfree_skb_any(skb); |
160 | } | 160 | } |
161 | |||
161 | unlock: | 162 | unlock: |
162 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 163 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
163 | wake_up(&priv->waitq); | 164 | wake_up(&priv->waitq); |
@@ -179,7 +180,8 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) | |||
179 | { | 180 | { |
180 | struct tx_radiotap_hdr *radiotap_hdr; | 181 | struct tx_radiotap_hdr *radiotap_hdr; |
181 | 182 | ||
182 | if (!priv->monitormode || priv->currenttxskb == NULL) | 183 | if (!priv->wdev->iftype == NL80211_IFTYPE_MONITOR || |
184 | priv->currenttxskb == NULL) | ||
183 | return; | 185 | return; |
184 | 186 | ||
185 | radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; | 187 | radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; |
@@ -188,7 +190,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) | |||
188 | (1 + priv->txretrycount - try_count) : 0; | 190 | (1 + priv->txretrycount - try_count) : 0; |
189 | 191 | ||
190 | priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, | 192 | priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, |
191 | priv->rtap_net_dev); | 193 | priv->dev); |
192 | netif_rx(priv->currenttxskb); | 194 | netif_rx(priv->currenttxskb); |
193 | 195 | ||
194 | priv->currenttxskb = NULL; | 196 | priv->currenttxskb = NULL; |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c deleted file mode 100644 index f96a96031a50..000000000000 --- a/drivers/net/wireless/libertas/wext.c +++ /dev/null | |||
@@ -1,2353 +0,0 @@ | |||
1 | /** | ||
2 | * This file contains ioctl functions | ||
3 | */ | ||
4 | #include <linux/ctype.h> | ||
5 | #include <linux/slab.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <linux/if.h> | ||
8 | #include <linux/if_arp.h> | ||
9 | #include <linux/wireless.h> | ||
10 | #include <linux/bitops.h> | ||
11 | |||
12 | #include <net/lib80211.h> | ||
13 | #include <net/iw_handler.h> | ||
14 | |||
15 | #include "host.h" | ||
16 | #include "radiotap.h" | ||
17 | #include "decl.h" | ||
18 | #include "defs.h" | ||
19 | #include "dev.h" | ||
20 | #include "wext.h" | ||
21 | #include "scan.h" | ||
22 | #include "assoc.h" | ||
23 | #include "cmd.h" | ||
24 | |||
25 | |||
26 | static inline void lbs_postpone_association_work(struct lbs_private *priv) | ||
27 | { | ||
28 | if (priv->surpriseremoved) | ||
29 | return; | ||
30 | cancel_delayed_work(&priv->assoc_work); | ||
31 | queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2); | ||
32 | } | ||
33 | |||
34 | static inline void lbs_do_association_work(struct lbs_private *priv) | ||
35 | { | ||
36 | if (priv->surpriseremoved) | ||
37 | return; | ||
38 | cancel_delayed_work(&priv->assoc_work); | ||
39 | queue_delayed_work(priv->work_thread, &priv->assoc_work, 0); | ||
40 | } | ||
41 | |||
42 | static inline void lbs_cancel_association_work(struct lbs_private *priv) | ||
43 | { | ||
44 | cancel_delayed_work(&priv->assoc_work); | ||
45 | kfree(priv->pending_assoc_req); | ||
46 | priv->pending_assoc_req = NULL; | ||
47 | } | ||
48 | |||
49 | void lbs_send_disconnect_notification(struct lbs_private *priv) | ||
50 | { | ||
51 | union iwreq_data wrqu; | ||
52 | |||
53 | memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); | ||
54 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
55 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
56 | } | ||
57 | |||
58 | static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) | ||
59 | { | ||
60 | union iwreq_data iwrq; | ||
61 | u8 buf[50]; | ||
62 | |||
63 | lbs_deb_enter(LBS_DEB_WEXT); | ||
64 | |||
65 | memset(&iwrq, 0, sizeof(union iwreq_data)); | ||
66 | memset(buf, 0, sizeof(buf)); | ||
67 | |||
68 | snprintf(buf, sizeof(buf) - 1, "%s", str); | ||
69 | |||
70 | iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; | ||
71 | |||
72 | /* Send Event to upper layer */ | ||
73 | lbs_deb_wext("event indication string %s\n", (char *)buf); | ||
74 | lbs_deb_wext("event indication length %d\n", iwrq.data.length); | ||
75 | lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); | ||
76 | |||
77 | wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); | ||
78 | |||
79 | lbs_deb_leave(LBS_DEB_WEXT); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * @brief This function handles MIC failure event. | ||
84 | * | ||
85 | * @param priv A pointer to struct lbs_private structure | ||
86 | * @para event the event id | ||
87 | * @return n/a | ||
88 | */ | ||
89 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event) | ||
90 | { | ||
91 | char buf[50]; | ||
92 | |||
93 | lbs_deb_enter(LBS_DEB_CMD); | ||
94 | memset(buf, 0, sizeof(buf)); | ||
95 | |||
96 | sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); | ||
97 | |||
98 | if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) | ||
99 | strcat(buf, "unicast "); | ||
100 | else | ||
101 | strcat(buf, "multicast "); | ||
102 | |||
103 | lbs_send_iwevcustom_event(priv, buf); | ||
104 | lbs_deb_leave(LBS_DEB_CMD); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * @brief Find the channel frequency power info with specific channel | ||
109 | * | ||
110 | * @param priv A pointer to struct lbs_private structure | ||
111 | * @param band it can be BAND_A, BAND_G or BAND_B | ||
112 | * @param channel the channel for looking | ||
113 | * @return A pointer to struct chan_freq_power structure or NULL if not find. | ||
114 | */ | ||
115 | struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | ||
116 | struct lbs_private *priv, | ||
117 | u8 band, | ||
118 | u16 channel) | ||
119 | { | ||
120 | struct chan_freq_power *cfp = NULL; | ||
121 | struct region_channel *rc; | ||
122 | int i, j; | ||
123 | |||
124 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { | ||
125 | rc = &priv->region_channel[j]; | ||
126 | |||
127 | if (!rc->valid || !rc->CFP) | ||
128 | continue; | ||
129 | if (rc->band != band) | ||
130 | continue; | ||
131 | for (i = 0; i < rc->nrcfp; i++) { | ||
132 | if (rc->CFP[i].channel == channel) { | ||
133 | cfp = &rc->CFP[i]; | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | if (!cfp && channel) | ||
140 | lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find " | ||
141 | "cfp by band %d / channel %d\n", band, channel); | ||
142 | |||
143 | return cfp; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * @brief Find the channel frequency power info with specific frequency | ||
148 | * | ||
149 | * @param priv A pointer to struct lbs_private structure | ||
150 | * @param band it can be BAND_A, BAND_G or BAND_B | ||
151 | * @param freq the frequency for looking | ||
152 | * @return A pointer to struct chan_freq_power structure or NULL if not find. | ||
153 | */ | ||
154 | static struct chan_freq_power *find_cfp_by_band_and_freq( | ||
155 | struct lbs_private *priv, | ||
156 | u8 band, | ||
157 | u32 freq) | ||
158 | { | ||
159 | struct chan_freq_power *cfp = NULL; | ||
160 | struct region_channel *rc; | ||
161 | int i, j; | ||
162 | |||
163 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { | ||
164 | rc = &priv->region_channel[j]; | ||
165 | |||
166 | if (!rc->valid || !rc->CFP) | ||
167 | continue; | ||
168 | if (rc->band != band) | ||
169 | continue; | ||
170 | for (i = 0; i < rc->nrcfp; i++) { | ||
171 | if (rc->CFP[i].freq == freq) { | ||
172 | cfp = &rc->CFP[i]; | ||
173 | break; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | if (!cfp && freq) | ||
179 | lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by " | ||
180 | "band %d / freq %d\n", band, freq); | ||
181 | |||
182 | return cfp; | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * @brief Copy active data rates based on adapter mode and status | ||
187 | * | ||
188 | * @param priv A pointer to struct lbs_private structure | ||
189 | * @param rate The buf to return the active rates | ||
190 | */ | ||
191 | static void copy_active_data_rates(struct lbs_private *priv, u8 *rates) | ||
192 | { | ||
193 | lbs_deb_enter(LBS_DEB_WEXT); | ||
194 | |||
195 | if ((priv->connect_status != LBS_CONNECTED) && | ||
196 | !lbs_mesh_connected(priv)) | ||
197 | memcpy(rates, lbs_bg_rates, MAX_RATES); | ||
198 | else | ||
199 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); | ||
200 | |||
201 | lbs_deb_leave(LBS_DEB_WEXT); | ||
202 | } | ||
203 | |||
204 | static int lbs_get_name(struct net_device *dev, struct iw_request_info *info, | ||
205 | char *cwrq, char *extra) | ||
206 | { | ||
207 | |||
208 | lbs_deb_enter(LBS_DEB_WEXT); | ||
209 | |||
210 | /* We could add support for 802.11n here as needed. Jean II */ | ||
211 | snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g"); | ||
212 | |||
213 | lbs_deb_leave(LBS_DEB_WEXT); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | ||
218 | struct iw_freq *fwrq, char *extra) | ||
219 | { | ||
220 | struct lbs_private *priv = dev->ml_priv; | ||
221 | struct chan_freq_power *cfp; | ||
222 | |||
223 | lbs_deb_enter(LBS_DEB_WEXT); | ||
224 | |||
225 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, | ||
226 | priv->channel); | ||
227 | |||
228 | if (!cfp) { | ||
229 | if (priv->channel) | ||
230 | lbs_deb_wext("invalid channel %d\n", | ||
231 | priv->channel); | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | fwrq->m = (long)cfp->freq * 100000; | ||
236 | fwrq->e = 1; | ||
237 | |||
238 | lbs_deb_wext("freq %u\n", fwrq->m); | ||
239 | lbs_deb_leave(LBS_DEB_WEXT); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, | ||
244 | struct sockaddr *awrq, char *extra) | ||
245 | { | ||
246 | struct lbs_private *priv = dev->ml_priv; | ||
247 | |||
248 | lbs_deb_enter(LBS_DEB_WEXT); | ||
249 | |||
250 | if (priv->connect_status == LBS_CONNECTED) { | ||
251 | memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN); | ||
252 | } else { | ||
253 | memset(awrq->sa_data, 0, ETH_ALEN); | ||
254 | } | ||
255 | awrq->sa_family = ARPHRD_ETHER; | ||
256 | |||
257 | lbs_deb_leave(LBS_DEB_WEXT); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, | ||
262 | struct iw_point *dwrq, char *extra) | ||
263 | { | ||
264 | struct lbs_private *priv = dev->ml_priv; | ||
265 | |||
266 | lbs_deb_enter(LBS_DEB_WEXT); | ||
267 | |||
268 | /* | ||
269 | * Check the size of the string | ||
270 | */ | ||
271 | |||
272 | if (dwrq->length > 16) { | ||
273 | return -E2BIG; | ||
274 | } | ||
275 | |||
276 | mutex_lock(&priv->lock); | ||
277 | memset(priv->nodename, 0, sizeof(priv->nodename)); | ||
278 | memcpy(priv->nodename, extra, dwrq->length); | ||
279 | mutex_unlock(&priv->lock); | ||
280 | |||
281 | lbs_deb_leave(LBS_DEB_WEXT); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | ||
286 | struct iw_point *dwrq, char *extra) | ||
287 | { | ||
288 | struct lbs_private *priv = dev->ml_priv; | ||
289 | |||
290 | lbs_deb_enter(LBS_DEB_WEXT); | ||
291 | |||
292 | dwrq->length = strlen(priv->nodename); | ||
293 | memcpy(extra, priv->nodename, dwrq->length); | ||
294 | extra[dwrq->length] = '\0'; | ||
295 | |||
296 | dwrq->flags = 1; /* active */ | ||
297 | |||
298 | lbs_deb_leave(LBS_DEB_WEXT); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | #ifdef CONFIG_LIBERTAS_MESH | ||
303 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | ||
304 | struct iw_point *dwrq, char *extra) | ||
305 | { | ||
306 | struct lbs_private *priv = dev->ml_priv; | ||
307 | |||
308 | lbs_deb_enter(LBS_DEB_WEXT); | ||
309 | |||
310 | /* Use nickname to indicate that mesh is on */ | ||
311 | |||
312 | if (lbs_mesh_connected(priv)) { | ||
313 | strncpy(extra, "Mesh", 12); | ||
314 | extra[12] = '\0'; | ||
315 | dwrq->length = strlen(extra); | ||
316 | } | ||
317 | |||
318 | else { | ||
319 | extra[0] = '\0'; | ||
320 | dwrq->length = 0; | ||
321 | } | ||
322 | |||
323 | lbs_deb_leave(LBS_DEB_WEXT); | ||
324 | return 0; | ||
325 | } | ||
326 | #endif | ||
327 | |||
328 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | ||
329 | struct iw_param *vwrq, char *extra) | ||
330 | { | ||
331 | int ret = 0; | ||
332 | struct lbs_private *priv = dev->ml_priv; | ||
333 | u32 val = vwrq->value; | ||
334 | |||
335 | lbs_deb_enter(LBS_DEB_WEXT); | ||
336 | |||
337 | if (vwrq->disabled) | ||
338 | val = MRVDRV_RTS_MAX_VALUE; | ||
339 | |||
340 | if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */ | ||
341 | return -EINVAL; | ||
342 | |||
343 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val); | ||
344 | |||
345 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, | ||
350 | struct iw_param *vwrq, char *extra) | ||
351 | { | ||
352 | struct lbs_private *priv = dev->ml_priv; | ||
353 | int ret = 0; | ||
354 | u16 val = 0; | ||
355 | |||
356 | lbs_deb_enter(LBS_DEB_WEXT); | ||
357 | |||
358 | ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val); | ||
359 | if (ret) | ||
360 | goto out; | ||
361 | |||
362 | vwrq->value = val; | ||
363 | vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */ | ||
364 | vwrq->fixed = 1; | ||
365 | |||
366 | out: | ||
367 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, | ||
372 | struct iw_param *vwrq, char *extra) | ||
373 | { | ||
374 | struct lbs_private *priv = dev->ml_priv; | ||
375 | int ret = 0; | ||
376 | u32 val = vwrq->value; | ||
377 | |||
378 | lbs_deb_enter(LBS_DEB_WEXT); | ||
379 | |||
380 | if (vwrq->disabled) | ||
381 | val = MRVDRV_FRAG_MAX_VALUE; | ||
382 | |||
383 | if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE) | ||
384 | return -EINVAL; | ||
385 | |||
386 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val); | ||
387 | |||
388 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
389 | return ret; | ||
390 | } | ||
391 | |||
392 | static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, | ||
393 | struct iw_param *vwrq, char *extra) | ||
394 | { | ||
395 | struct lbs_private *priv = dev->ml_priv; | ||
396 | int ret = 0; | ||
397 | u16 val = 0; | ||
398 | |||
399 | lbs_deb_enter(LBS_DEB_WEXT); | ||
400 | |||
401 | ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val); | ||
402 | if (ret) | ||
403 | goto out; | ||
404 | |||
405 | vwrq->value = val; | ||
406 | vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE) | ||
407 | || (val > MRVDRV_FRAG_MAX_VALUE)); | ||
408 | vwrq->fixed = 1; | ||
409 | |||
410 | out: | ||
411 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | static int lbs_get_mode(struct net_device *dev, | ||
416 | struct iw_request_info *info, u32 * uwrq, char *extra) | ||
417 | { | ||
418 | struct lbs_private *priv = dev->ml_priv; | ||
419 | |||
420 | lbs_deb_enter(LBS_DEB_WEXT); | ||
421 | |||
422 | *uwrq = priv->mode; | ||
423 | |||
424 | lbs_deb_leave(LBS_DEB_WEXT); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | #ifdef CONFIG_LIBERTAS_MESH | ||
429 | static int mesh_wlan_get_mode(struct net_device *dev, | ||
430 | struct iw_request_info *info, u32 * uwrq, | ||
431 | char *extra) | ||
432 | { | ||
433 | lbs_deb_enter(LBS_DEB_WEXT); | ||
434 | |||
435 | *uwrq = IW_MODE_REPEAT; | ||
436 | |||
437 | lbs_deb_leave(LBS_DEB_WEXT); | ||
438 | return 0; | ||
439 | } | ||
440 | #endif | ||
441 | |||
442 | static int lbs_get_txpow(struct net_device *dev, | ||
443 | struct iw_request_info *info, | ||
444 | struct iw_param *vwrq, char *extra) | ||
445 | { | ||
446 | struct lbs_private *priv = dev->ml_priv; | ||
447 | s16 curlevel = 0; | ||
448 | int ret = 0; | ||
449 | |||
450 | lbs_deb_enter(LBS_DEB_WEXT); | ||
451 | |||
452 | if (!priv->radio_on) { | ||
453 | lbs_deb_wext("tx power off\n"); | ||
454 | vwrq->value = 0; | ||
455 | vwrq->disabled = 1; | ||
456 | goto out; | ||
457 | } | ||
458 | |||
459 | ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL); | ||
460 | if (ret) | ||
461 | goto out; | ||
462 | |||
463 | lbs_deb_wext("tx power level %d dbm\n", curlevel); | ||
464 | priv->txpower_cur = curlevel; | ||
465 | |||
466 | vwrq->value = curlevel; | ||
467 | vwrq->fixed = 1; | ||
468 | vwrq->disabled = 0; | ||
469 | vwrq->flags = IW_TXPOW_DBM; | ||
470 | |||
471 | out: | ||
472 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
473 | return ret; | ||
474 | } | ||
475 | |||
476 | static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, | ||
477 | struct iw_param *vwrq, char *extra) | ||
478 | { | ||
479 | struct lbs_private *priv = dev->ml_priv; | ||
480 | int ret = 0; | ||
481 | u16 slimit = 0, llimit = 0; | ||
482 | |||
483 | lbs_deb_enter(LBS_DEB_WEXT); | ||
484 | |||
485 | if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) | ||
486 | return -EOPNOTSUPP; | ||
487 | |||
488 | /* The MAC has a 4-bit Total_Tx_Count register | ||
489 | Total_Tx_Count = 1 + Tx_Retry_Count */ | ||
490 | #define TX_RETRY_MIN 0 | ||
491 | #define TX_RETRY_MAX 14 | ||
492 | if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX) | ||
493 | return -EINVAL; | ||
494 | |||
495 | /* Add 1 to convert retry count to try count */ | ||
496 | if (vwrq->flags & IW_RETRY_SHORT) | ||
497 | slimit = (u16) (vwrq->value + 1); | ||
498 | else if (vwrq->flags & IW_RETRY_LONG) | ||
499 | llimit = (u16) (vwrq->value + 1); | ||
500 | else | ||
501 | slimit = llimit = (u16) (vwrq->value + 1); /* set both */ | ||
502 | |||
503 | if (llimit) { | ||
504 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, | ||
505 | llimit); | ||
506 | if (ret) | ||
507 | goto out; | ||
508 | } | ||
509 | |||
510 | if (slimit) { | ||
511 | /* txretrycount follows the short retry limit */ | ||
512 | priv->txretrycount = slimit; | ||
513 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, | ||
514 | slimit); | ||
515 | if (ret) | ||
516 | goto out; | ||
517 | } | ||
518 | |||
519 | out: | ||
520 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, | ||
525 | struct iw_param *vwrq, char *extra) | ||
526 | { | ||
527 | struct lbs_private *priv = dev->ml_priv; | ||
528 | int ret = 0; | ||
529 | u16 val = 0; | ||
530 | |||
531 | lbs_deb_enter(LBS_DEB_WEXT); | ||
532 | |||
533 | vwrq->disabled = 0; | ||
534 | |||
535 | if (vwrq->flags & IW_RETRY_LONG) { | ||
536 | ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val); | ||
537 | if (ret) | ||
538 | goto out; | ||
539 | |||
540 | /* Subtract 1 to convert try count to retry count */ | ||
541 | vwrq->value = val - 1; | ||
542 | vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; | ||
543 | } else { | ||
544 | ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val); | ||
545 | if (ret) | ||
546 | goto out; | ||
547 | |||
548 | /* txretry count follows the short retry limit */ | ||
549 | priv->txretrycount = val; | ||
550 | /* Subtract 1 to convert try count to retry count */ | ||
551 | vwrq->value = val - 1; | ||
552 | vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; | ||
553 | } | ||
554 | |||
555 | out: | ||
556 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
557 | return ret; | ||
558 | } | ||
559 | |||
560 | static inline void sort_channels(struct iw_freq *freq, int num) | ||
561 | { | ||
562 | int i, j; | ||
563 | struct iw_freq temp; | ||
564 | |||
565 | for (i = 0; i < num; i++) | ||
566 | for (j = i + 1; j < num; j++) | ||
567 | if (freq[i].i > freq[j].i) { | ||
568 | temp.i = freq[i].i; | ||
569 | temp.m = freq[i].m; | ||
570 | |||
571 | freq[i].i = freq[j].i; | ||
572 | freq[i].m = freq[j].m; | ||
573 | |||
574 | freq[j].i = temp.i; | ||
575 | freq[j].m = temp.m; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | /* data rate listing | ||
580 | MULTI_BANDS: | ||
581 | abg a b b/g | ||
582 | Infra G(12) A(8) B(4) G(12) | ||
583 | Adhoc A+B(12) A(8) B(4) B(4) | ||
584 | |||
585 | non-MULTI_BANDS: | ||
586 | b b/g | ||
587 | Infra B(4) G(12) | ||
588 | Adhoc B(4) B(4) | ||
589 | */ | ||
590 | /** | ||
591 | * @brief Get Range Info | ||
592 | * | ||
593 | * @param dev A pointer to net_device structure | ||
594 | * @param info A pointer to iw_request_info structure | ||
595 | * @param vwrq A pointer to iw_param structure | ||
596 | * @param extra A pointer to extra data buf | ||
597 | * @return 0 --success, otherwise fail | ||
598 | */ | ||
599 | static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | ||
600 | struct iw_point *dwrq, char *extra) | ||
601 | { | ||
602 | int i, j; | ||
603 | struct lbs_private *priv = dev->ml_priv; | ||
604 | struct iw_range *range = (struct iw_range *)extra; | ||
605 | struct chan_freq_power *cfp; | ||
606 | u8 rates[MAX_RATES + 1]; | ||
607 | |||
608 | lbs_deb_enter(LBS_DEB_WEXT); | ||
609 | |||
610 | dwrq->length = sizeof(struct iw_range); | ||
611 | memset(range, 0, sizeof(struct iw_range)); | ||
612 | |||
613 | range->min_nwid = 0; | ||
614 | range->max_nwid = 0; | ||
615 | |||
616 | memset(rates, 0, sizeof(rates)); | ||
617 | copy_active_data_rates(priv, rates); | ||
618 | range->num_bitrates = strnlen(rates, IW_MAX_BITRATES); | ||
619 | for (i = 0; i < range->num_bitrates; i++) | ||
620 | range->bitrate[i] = rates[i] * 500000; | ||
621 | range->num_bitrates = i; | ||
622 | lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES, | ||
623 | range->num_bitrates); | ||
624 | |||
625 | range->num_frequency = 0; | ||
626 | |||
627 | range->scan_capa = IW_SCAN_CAPA_ESSID; | ||
628 | |||
629 | for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | ||
630 | && (j < ARRAY_SIZE(priv->region_channel)); j++) { | ||
631 | cfp = priv->region_channel[j].CFP; | ||
632 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | ||
633 | && priv->region_channel[j].valid | ||
634 | && cfp | ||
635 | && (i < priv->region_channel[j].nrcfp); i++) { | ||
636 | range->freq[range->num_frequency].i = | ||
637 | (long)cfp->channel; | ||
638 | range->freq[range->num_frequency].m = | ||
639 | (long)cfp->freq * 100000; | ||
640 | range->freq[range->num_frequency].e = 1; | ||
641 | cfp++; | ||
642 | range->num_frequency++; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", | ||
647 | IW_MAX_FREQUENCIES, range->num_frequency); | ||
648 | |||
649 | range->num_channels = range->num_frequency; | ||
650 | |||
651 | sort_channels(&range->freq[0], range->num_frequency); | ||
652 | |||
653 | /* | ||
654 | * Set an indication of the max TCP throughput in bit/s that we can | ||
655 | * expect using this interface | ||
656 | */ | ||
657 | if (i > 2) | ||
658 | range->throughput = 5000 * 1000; | ||
659 | else | ||
660 | range->throughput = 1500 * 1000; | ||
661 | |||
662 | range->min_rts = MRVDRV_RTS_MIN_VALUE; | ||
663 | range->max_rts = MRVDRV_RTS_MAX_VALUE; | ||
664 | range->min_frag = MRVDRV_FRAG_MIN_VALUE; | ||
665 | range->max_frag = MRVDRV_FRAG_MAX_VALUE; | ||
666 | |||
667 | range->encoding_size[0] = 5; | ||
668 | range->encoding_size[1] = 13; | ||
669 | range->num_encoding_sizes = 2; | ||
670 | range->max_encoding_tokens = 4; | ||
671 | |||
672 | /* | ||
673 | * Right now we support only "iwconfig ethX power on|off" | ||
674 | */ | ||
675 | range->pm_capa = IW_POWER_ON; | ||
676 | |||
677 | /* | ||
678 | * Minimum version we recommend | ||
679 | */ | ||
680 | range->we_version_source = 15; | ||
681 | |||
682 | /* | ||
683 | * Version we are compiled with | ||
684 | */ | ||
685 | range->we_version_compiled = WIRELESS_EXT; | ||
686 | |||
687 | range->retry_capa = IW_RETRY_LIMIT; | ||
688 | range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX; | ||
689 | |||
690 | range->min_retry = TX_RETRY_MIN; | ||
691 | range->max_retry = TX_RETRY_MAX; | ||
692 | |||
693 | /* | ||
694 | * Set the qual, level and noise range values | ||
695 | */ | ||
696 | range->max_qual.qual = 100; | ||
697 | range->max_qual.level = 0; | ||
698 | range->max_qual.noise = 0; | ||
699 | range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; | ||
700 | |||
701 | range->avg_qual.qual = 70; | ||
702 | /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ | ||
703 | range->avg_qual.level = 0; | ||
704 | range->avg_qual.noise = 0; | ||
705 | range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; | ||
706 | |||
707 | range->sensitivity = 0; | ||
708 | |||
709 | /* Setup the supported power level ranges */ | ||
710 | memset(range->txpower, 0, sizeof(range->txpower)); | ||
711 | range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE; | ||
712 | range->txpower[0] = priv->txpower_min; | ||
713 | range->txpower[1] = priv->txpower_max; | ||
714 | range->num_txpower = 2; | ||
715 | |||
716 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | | ||
717 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | | ||
718 | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); | ||
719 | range->event_capa[1] = IW_EVENT_CAPA_K_1; | ||
720 | |||
721 | if (priv->fwcapinfo & FW_CAPINFO_WPA) { | ||
722 | range->enc_capa = IW_ENC_CAPA_WPA | ||
723 | | IW_ENC_CAPA_WPA2 | ||
724 | | IW_ENC_CAPA_CIPHER_TKIP | ||
725 | | IW_ENC_CAPA_CIPHER_CCMP; | ||
726 | } | ||
727 | |||
728 | lbs_deb_leave(LBS_DEB_WEXT); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | ||
733 | struct iw_param *vwrq, char *extra) | ||
734 | { | ||
735 | struct lbs_private *priv = dev->ml_priv; | ||
736 | int ret = 0; | ||
737 | |||
738 | lbs_deb_enter(LBS_DEB_WEXT); | ||
739 | |||
740 | if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { | ||
741 | if (vwrq->disabled) | ||
742 | return 0; | ||
743 | else | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | /* PS is currently supported only in Infrastructure mode | ||
748 | * Remove this check if it is to be supported in IBSS mode also | ||
749 | */ | ||
750 | |||
751 | if (vwrq->disabled) { | ||
752 | priv->psmode = LBS802_11POWERMODECAM; | ||
753 | if (priv->psstate != PS_STATE_FULL_POWER) { | ||
754 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | ||
755 | } | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { | ||
761 | lbs_deb_wext( | ||
762 | "setting power timeout is not supported\n"); | ||
763 | return -EINVAL; | ||
764 | } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { | ||
765 | vwrq->value = vwrq->value / 1000; | ||
766 | if (!priv->enter_deep_sleep) { | ||
767 | lbs_pr_err("deep sleep feature is not implemented " | ||
768 | "for this interface driver\n"); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | if (priv->connect_status == LBS_CONNECTED) { | ||
773 | if ((priv->is_auto_deep_sleep_enabled) && | ||
774 | (vwrq->value == -1000)) { | ||
775 | lbs_exit_auto_deep_sleep(priv); | ||
776 | return 0; | ||
777 | } else { | ||
778 | lbs_pr_err("can't use deep sleep cmd in " | ||
779 | "connected state\n"); | ||
780 | return -EINVAL; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | if ((vwrq->value < 0) && (vwrq->value != -1000)) { | ||
785 | lbs_pr_err("unknown option\n"); | ||
786 | return -EINVAL; | ||
787 | } | ||
788 | |||
789 | if (vwrq->value > 0) { | ||
790 | if (!priv->is_auto_deep_sleep_enabled) { | ||
791 | priv->is_activity_detected = 0; | ||
792 | priv->auto_deep_sleep_timeout = vwrq->value; | ||
793 | lbs_enter_auto_deep_sleep(priv); | ||
794 | } else { | ||
795 | priv->auto_deep_sleep_timeout = vwrq->value; | ||
796 | lbs_deb_debugfs("auto deep sleep: " | ||
797 | "already enabled\n"); | ||
798 | } | ||
799 | return 0; | ||
800 | } else { | ||
801 | if (priv->is_auto_deep_sleep_enabled) { | ||
802 | lbs_exit_auto_deep_sleep(priv); | ||
803 | /* Try to exit deep sleep if auto */ | ||
804 | /*deep sleep disabled */ | ||
805 | ret = lbs_set_deep_sleep(priv, 0); | ||
806 | } | ||
807 | if (vwrq->value == 0) | ||
808 | ret = lbs_set_deep_sleep(priv, 1); | ||
809 | else if (vwrq->value == -1000) | ||
810 | ret = lbs_set_deep_sleep(priv, 0); | ||
811 | return ret; | ||
812 | } | ||
813 | } | ||
814 | |||
815 | if (priv->psmode != LBS802_11POWERMODECAM) { | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | priv->psmode = LBS802_11POWERMODEMAX_PSP; | ||
820 | |||
821 | if (priv->connect_status == LBS_CONNECTED) { | ||
822 | lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP); | ||
823 | } | ||
824 | |||
825 | lbs_deb_leave(LBS_DEB_WEXT); | ||
826 | |||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, | ||
831 | struct iw_param *vwrq, char *extra) | ||
832 | { | ||
833 | struct lbs_private *priv = dev->ml_priv; | ||
834 | |||
835 | lbs_deb_enter(LBS_DEB_WEXT); | ||
836 | |||
837 | vwrq->value = 0; | ||
838 | vwrq->flags = 0; | ||
839 | vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM | ||
840 | || priv->connect_status == LBS_DISCONNECTED; | ||
841 | |||
842 | lbs_deb_leave(LBS_DEB_WEXT); | ||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | ||
847 | { | ||
848 | enum { | ||
849 | POOR = 30, | ||
850 | FAIR = 60, | ||
851 | GOOD = 80, | ||
852 | VERY_GOOD = 90, | ||
853 | EXCELLENT = 95, | ||
854 | PERFECT = 100 | ||
855 | }; | ||
856 | struct lbs_private *priv = dev->ml_priv; | ||
857 | u32 rssi_qual; | ||
858 | u32 tx_qual; | ||
859 | u32 quality = 0; | ||
860 | int ret, stats_valid = 0; | ||
861 | u8 rssi; | ||
862 | u32 tx_retries; | ||
863 | struct cmd_ds_802_11_get_log log; | ||
864 | |||
865 | lbs_deb_enter(LBS_DEB_WEXT); | ||
866 | |||
867 | priv->wstats.status = priv->mode; | ||
868 | |||
869 | /* If we're not associated, all quality values are meaningless */ | ||
870 | if ((priv->connect_status != LBS_CONNECTED) && | ||
871 | !lbs_mesh_connected(priv)) | ||
872 | goto out; | ||
873 | |||
874 | /* Quality by RSSI */ | ||
875 | priv->wstats.qual.level = | ||
876 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], | ||
877 | priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
878 | |||
879 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { | ||
880 | priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; | ||
881 | } else { | ||
882 | priv->wstats.qual.noise = | ||
883 | CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
884 | } | ||
885 | |||
886 | lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level); | ||
887 | lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise); | ||
888 | |||
889 | rssi = priv->wstats.qual.level - priv->wstats.qual.noise; | ||
890 | if (rssi < 15) | ||
891 | rssi_qual = rssi * POOR / 10; | ||
892 | else if (rssi < 20) | ||
893 | rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR; | ||
894 | else if (rssi < 30) | ||
895 | rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR; | ||
896 | else if (rssi < 40) | ||
897 | rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) / | ||
898 | 10 + GOOD; | ||
899 | else | ||
900 | rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) / | ||
901 | 10 + VERY_GOOD; | ||
902 | quality = rssi_qual; | ||
903 | |||
904 | /* Quality by TX errors */ | ||
905 | priv->wstats.discard.retries = dev->stats.tx_errors; | ||
906 | |||
907 | memset(&log, 0, sizeof(log)); | ||
908 | log.hdr.size = cpu_to_le16(sizeof(log)); | ||
909 | ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); | ||
910 | if (ret) | ||
911 | goto out; | ||
912 | |||
913 | tx_retries = le32_to_cpu(log.retry); | ||
914 | |||
915 | if (tx_retries > 75) | ||
916 | tx_qual = (90 - tx_retries) * POOR / 15; | ||
917 | else if (tx_retries > 70) | ||
918 | tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR; | ||
919 | else if (tx_retries > 65) | ||
920 | tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; | ||
921 | else if (tx_retries > 50) | ||
922 | tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / | ||
923 | 15 + GOOD; | ||
924 | else | ||
925 | tx_qual = (50 - tx_retries) * | ||
926 | (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; | ||
927 | quality = min(quality, tx_qual); | ||
928 | |||
929 | priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable); | ||
930 | priv->wstats.discard.retries = tx_retries; | ||
931 | priv->wstats.discard.misc = le32_to_cpu(log.ackfailure); | ||
932 | |||
933 | /* Calculate quality */ | ||
934 | priv->wstats.qual.qual = min_t(u8, quality, 100); | ||
935 | priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; | ||
936 | stats_valid = 1; | ||
937 | |||
938 | /* update stats asynchronously for future calls */ | ||
939 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | ||
940 | 0, 0, NULL); | ||
941 | if (ret) | ||
942 | lbs_pr_err("RSSI command failed\n"); | ||
943 | out: | ||
944 | if (!stats_valid) { | ||
945 | priv->wstats.miss.beacon = 0; | ||
946 | priv->wstats.discard.retries = 0; | ||
947 | priv->wstats.qual.qual = 0; | ||
948 | priv->wstats.qual.level = 0; | ||
949 | priv->wstats.qual.noise = 0; | ||
950 | priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED; | ||
951 | priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID | | ||
952 | IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; | ||
953 | } | ||
954 | |||
955 | lbs_deb_leave(LBS_DEB_WEXT); | ||
956 | return &priv->wstats; | ||
957 | |||
958 | |||
959 | } | ||
960 | |||
961 | static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, | ||
962 | struct iw_freq *fwrq, char *extra) | ||
963 | { | ||
964 | int ret = -EINVAL; | ||
965 | struct lbs_private *priv = dev->ml_priv; | ||
966 | struct chan_freq_power *cfp; | ||
967 | struct assoc_request * assoc_req; | ||
968 | |||
969 | lbs_deb_enter(LBS_DEB_WEXT); | ||
970 | |||
971 | mutex_lock(&priv->lock); | ||
972 | assoc_req = lbs_get_association_request(priv); | ||
973 | if (!assoc_req) { | ||
974 | ret = -ENOMEM; | ||
975 | goto out; | ||
976 | } | ||
977 | |||
978 | /* If setting by frequency, convert to a channel */ | ||
979 | if (fwrq->e == 1) { | ||
980 | long f = fwrq->m / 100000; | ||
981 | |||
982 | cfp = find_cfp_by_band_and_freq(priv, 0, f); | ||
983 | if (!cfp) { | ||
984 | lbs_deb_wext("invalid freq %ld\n", f); | ||
985 | goto out; | ||
986 | } | ||
987 | |||
988 | fwrq->e = 0; | ||
989 | fwrq->m = (int) cfp->channel; | ||
990 | } | ||
991 | |||
992 | /* Setting by channel number */ | ||
993 | if (fwrq->m > 1000 || fwrq->e > 0) { | ||
994 | goto out; | ||
995 | } | ||
996 | |||
997 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m); | ||
998 | if (!cfp) { | ||
999 | goto out; | ||
1000 | } | ||
1001 | |||
1002 | assoc_req->channel = fwrq->m; | ||
1003 | ret = 0; | ||
1004 | |||
1005 | out: | ||
1006 | if (ret == 0) { | ||
1007 | set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags); | ||
1008 | lbs_postpone_association_work(priv); | ||
1009 | } else { | ||
1010 | lbs_cancel_association_work(priv); | ||
1011 | } | ||
1012 | mutex_unlock(&priv->lock); | ||
1013 | |||
1014 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1015 | return ret; | ||
1016 | } | ||
1017 | |||
1018 | #ifdef CONFIG_LIBERTAS_MESH | ||
1019 | static int lbs_mesh_set_freq(struct net_device *dev, | ||
1020 | struct iw_request_info *info, | ||
1021 | struct iw_freq *fwrq, char *extra) | ||
1022 | { | ||
1023 | struct lbs_private *priv = dev->ml_priv; | ||
1024 | struct chan_freq_power *cfp; | ||
1025 | int ret = -EINVAL; | ||
1026 | |||
1027 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1028 | |||
1029 | /* If setting by frequency, convert to a channel */ | ||
1030 | if (fwrq->e == 1) { | ||
1031 | long f = fwrq->m / 100000; | ||
1032 | |||
1033 | cfp = find_cfp_by_band_and_freq(priv, 0, f); | ||
1034 | if (!cfp) { | ||
1035 | lbs_deb_wext("invalid freq %ld\n", f); | ||
1036 | goto out; | ||
1037 | } | ||
1038 | |||
1039 | fwrq->e = 0; | ||
1040 | fwrq->m = (int) cfp->channel; | ||
1041 | } | ||
1042 | |||
1043 | /* Setting by channel number */ | ||
1044 | if (fwrq->m > 1000 || fwrq->e > 0) { | ||
1045 | goto out; | ||
1046 | } | ||
1047 | |||
1048 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m); | ||
1049 | if (!cfp) { | ||
1050 | goto out; | ||
1051 | } | ||
1052 | |||
1053 | if (fwrq->m != priv->channel) { | ||
1054 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); | ||
1055 | if (priv->mode == IW_MODE_INFRA) | ||
1056 | lbs_cmd_80211_deauthenticate(priv, | ||
1057 | priv->curbssparams.bssid, | ||
1058 | WLAN_REASON_DEAUTH_LEAVING); | ||
1059 | else if (priv->mode == IW_MODE_ADHOC) | ||
1060 | lbs_adhoc_stop(priv); | ||
1061 | } | ||
1062 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m); | ||
1063 | lbs_update_channel(priv); | ||
1064 | ret = 0; | ||
1065 | |||
1066 | out: | ||
1067 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1068 | return ret; | ||
1069 | } | ||
1070 | #endif | ||
1071 | |||
1072 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | ||
1073 | struct iw_param *vwrq, char *extra) | ||
1074 | { | ||
1075 | struct lbs_private *priv = dev->ml_priv; | ||
1076 | u8 new_rate = 0; | ||
1077 | int ret = -EINVAL; | ||
1078 | u8 rates[MAX_RATES + 1]; | ||
1079 | |||
1080 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1081 | |||
1082 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); | ||
1083 | lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); | ||
1084 | |||
1085 | if (vwrq->fixed && vwrq->value == -1) | ||
1086 | goto out; | ||
1087 | |||
1088 | /* Auto rate? */ | ||
1089 | priv->enablehwauto = !vwrq->fixed; | ||
1090 | |||
1091 | if (vwrq->value == -1) | ||
1092 | priv->cur_rate = 0; | ||
1093 | else { | ||
1094 | if (vwrq->value % 100000) | ||
1095 | goto out; | ||
1096 | |||
1097 | new_rate = vwrq->value / 500000; | ||
1098 | priv->cur_rate = new_rate; | ||
1099 | /* the rest is only needed for lbs_set_data_rate() */ | ||
1100 | memset(rates, 0, sizeof(rates)); | ||
1101 | copy_active_data_rates(priv, rates); | ||
1102 | if (!memchr(rates, new_rate, sizeof(rates))) { | ||
1103 | lbs_pr_alert("fixed data rate 0x%X out of range\n", | ||
1104 | new_rate); | ||
1105 | goto out; | ||
1106 | } | ||
1107 | if (priv->fwrelease < 0x09000000) { | ||
1108 | ret = lbs_set_power_adapt_cfg(priv, 0, | ||
1109 | POW_ADAPT_DEFAULT_P0, | ||
1110 | POW_ADAPT_DEFAULT_P1, | ||
1111 | POW_ADAPT_DEFAULT_P2); | ||
1112 | if (ret) | ||
1113 | goto out; | ||
1114 | } | ||
1115 | ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, | ||
1116 | TPC_DEFAULT_P2, 1); | ||
1117 | if (ret) | ||
1118 | goto out; | ||
1119 | } | ||
1120 | |||
1121 | /* Try the newer command first (Firmware Spec 5.1 and above) */ | ||
1122 | ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET); | ||
1123 | |||
1124 | /* Fallback to older version */ | ||
1125 | if (ret) | ||
1126 | ret = lbs_set_data_rate(priv, new_rate); | ||
1127 | |||
1128 | out: | ||
1129 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1130 | return ret; | ||
1131 | } | ||
1132 | |||
1133 | static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, | ||
1134 | struct iw_param *vwrq, char *extra) | ||
1135 | { | ||
1136 | struct lbs_private *priv = dev->ml_priv; | ||
1137 | |||
1138 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1139 | |||
1140 | if (priv->connect_status == LBS_CONNECTED) { | ||
1141 | vwrq->value = priv->cur_rate * 500000; | ||
1142 | |||
1143 | if (priv->enablehwauto) | ||
1144 | vwrq->fixed = 0; | ||
1145 | else | ||
1146 | vwrq->fixed = 1; | ||
1147 | |||
1148 | } else { | ||
1149 | vwrq->fixed = 0; | ||
1150 | vwrq->value = 0; | ||
1151 | } | ||
1152 | |||
1153 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | static int lbs_set_mode(struct net_device *dev, | ||
1158 | struct iw_request_info *info, u32 * uwrq, char *extra) | ||
1159 | { | ||
1160 | int ret = 0; | ||
1161 | struct lbs_private *priv = dev->ml_priv; | ||
1162 | struct assoc_request * assoc_req; | ||
1163 | |||
1164 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1165 | |||
1166 | if ( (*uwrq != IW_MODE_ADHOC) | ||
1167 | && (*uwrq != IW_MODE_INFRA) | ||
1168 | && (*uwrq != IW_MODE_AUTO)) { | ||
1169 | lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq); | ||
1170 | ret = -EINVAL; | ||
1171 | goto out; | ||
1172 | } | ||
1173 | |||
1174 | mutex_lock(&priv->lock); | ||
1175 | assoc_req = lbs_get_association_request(priv); | ||
1176 | if (!assoc_req) { | ||
1177 | ret = -ENOMEM; | ||
1178 | lbs_cancel_association_work(priv); | ||
1179 | } else { | ||
1180 | assoc_req->mode = *uwrq; | ||
1181 | set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); | ||
1182 | lbs_postpone_association_work(priv); | ||
1183 | lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq); | ||
1184 | } | ||
1185 | mutex_unlock(&priv->lock); | ||
1186 | |||
1187 | out: | ||
1188 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1189 | return ret; | ||
1190 | } | ||
1191 | |||
1192 | |||
1193 | /** | ||
1194 | * @brief Get Encryption key | ||
1195 | * | ||
1196 | * @param dev A pointer to net_device structure | ||
1197 | * @param info A pointer to iw_request_info structure | ||
1198 | * @param vwrq A pointer to iw_param structure | ||
1199 | * @param extra A pointer to extra data buf | ||
1200 | * @return 0 --success, otherwise fail | ||
1201 | */ | ||
1202 | static int lbs_get_encode(struct net_device *dev, | ||
1203 | struct iw_request_info *info, | ||
1204 | struct iw_point *dwrq, u8 * extra) | ||
1205 | { | ||
1206 | struct lbs_private *priv = dev->ml_priv; | ||
1207 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | ||
1208 | |||
1209 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1210 | |||
1211 | lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n", | ||
1212 | dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx); | ||
1213 | |||
1214 | dwrq->flags = 0; | ||
1215 | |||
1216 | /* Authentication method */ | ||
1217 | switch (priv->secinfo.auth_mode) { | ||
1218 | case IW_AUTH_ALG_OPEN_SYSTEM: | ||
1219 | dwrq->flags = IW_ENCODE_OPEN; | ||
1220 | break; | ||
1221 | |||
1222 | case IW_AUTH_ALG_SHARED_KEY: | ||
1223 | case IW_AUTH_ALG_LEAP: | ||
1224 | dwrq->flags = IW_ENCODE_RESTRICTED; | ||
1225 | break; | ||
1226 | default: | ||
1227 | dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN; | ||
1228 | break; | ||
1229 | } | ||
1230 | |||
1231 | memset(extra, 0, 16); | ||
1232 | |||
1233 | mutex_lock(&priv->lock); | ||
1234 | |||
1235 | /* Default to returning current transmit key */ | ||
1236 | if (index < 0) | ||
1237 | index = priv->wep_tx_keyidx; | ||
1238 | |||
1239 | if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) { | ||
1240 | memcpy(extra, priv->wep_keys[index].key, | ||
1241 | priv->wep_keys[index].len); | ||
1242 | dwrq->length = priv->wep_keys[index].len; | ||
1243 | |||
1244 | dwrq->flags |= (index + 1); | ||
1245 | /* Return WEP enabled */ | ||
1246 | dwrq->flags &= ~IW_ENCODE_DISABLED; | ||
1247 | } else if ((priv->secinfo.WPAenabled) | ||
1248 | || (priv->secinfo.WPA2enabled)) { | ||
1249 | /* return WPA enabled */ | ||
1250 | dwrq->flags &= ~IW_ENCODE_DISABLED; | ||
1251 | dwrq->flags |= IW_ENCODE_NOKEY; | ||
1252 | } else { | ||
1253 | dwrq->flags |= IW_ENCODE_DISABLED; | ||
1254 | } | ||
1255 | |||
1256 | mutex_unlock(&priv->lock); | ||
1257 | |||
1258 | lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n", | ||
1259 | extra[0], extra[1], extra[2], | ||
1260 | extra[3], extra[4], extra[5], dwrq->length); | ||
1261 | |||
1262 | lbs_deb_wext("return flags 0x%x\n", dwrq->flags); | ||
1263 | |||
1264 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | /** | ||
1269 | * @brief Set Encryption key (internal) | ||
1270 | * | ||
1271 | * @param priv A pointer to private card structure | ||
1272 | * @param key_material A pointer to key material | ||
1273 | * @param key_length length of key material | ||
1274 | * @param index key index to set | ||
1275 | * @param set_tx_key Force set TX key (1 = yes, 0 = no) | ||
1276 | * @return 0 --success, otherwise fail | ||
1277 | */ | ||
1278 | static int lbs_set_wep_key(struct assoc_request *assoc_req, | ||
1279 | const char *key_material, | ||
1280 | u16 key_length, | ||
1281 | u16 index, | ||
1282 | int set_tx_key) | ||
1283 | { | ||
1284 | int ret = 0; | ||
1285 | struct enc_key *pkey; | ||
1286 | |||
1287 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1288 | |||
1289 | /* Paranoid validation of key index */ | ||
1290 | if (index > 3) { | ||
1291 | ret = -EINVAL; | ||
1292 | goto out; | ||
1293 | } | ||
1294 | |||
1295 | /* validate max key length */ | ||
1296 | if (key_length > KEY_LEN_WEP_104) { | ||
1297 | ret = -EINVAL; | ||
1298 | goto out; | ||
1299 | } | ||
1300 | |||
1301 | pkey = &assoc_req->wep_keys[index]; | ||
1302 | |||
1303 | if (key_length > 0) { | ||
1304 | memset(pkey, 0, sizeof(struct enc_key)); | ||
1305 | pkey->type = KEY_TYPE_ID_WEP; | ||
1306 | |||
1307 | /* Standardize the key length */ | ||
1308 | pkey->len = (key_length > KEY_LEN_WEP_40) ? | ||
1309 | KEY_LEN_WEP_104 : KEY_LEN_WEP_40; | ||
1310 | memcpy(pkey->key, key_material, key_length); | ||
1311 | } | ||
1312 | |||
1313 | if (set_tx_key) { | ||
1314 | /* Ensure the chosen key is valid */ | ||
1315 | if (!pkey->len) { | ||
1316 | lbs_deb_wext("key not set, so cannot enable it\n"); | ||
1317 | ret = -EINVAL; | ||
1318 | goto out; | ||
1319 | } | ||
1320 | assoc_req->wep_tx_keyidx = index; | ||
1321 | } | ||
1322 | |||
1323 | assoc_req->secinfo.wep_enabled = 1; | ||
1324 | |||
1325 | out: | ||
1326 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1327 | return ret; | ||
1328 | } | ||
1329 | |||
1330 | static int validate_key_index(u16 def_index, u16 raw_index, | ||
1331 | u16 *out_index, u16 *is_default) | ||
1332 | { | ||
1333 | if (!out_index || !is_default) | ||
1334 | return -EINVAL; | ||
1335 | |||
1336 | /* Verify index if present, otherwise use default TX key index */ | ||
1337 | if (raw_index > 0) { | ||
1338 | if (raw_index > 4) | ||
1339 | return -EINVAL; | ||
1340 | *out_index = raw_index - 1; | ||
1341 | } else { | ||
1342 | *out_index = def_index; | ||
1343 | *is_default = 1; | ||
1344 | } | ||
1345 | return 0; | ||
1346 | } | ||
1347 | |||
1348 | static void disable_wep(struct assoc_request *assoc_req) | ||
1349 | { | ||
1350 | int i; | ||
1351 | |||
1352 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1353 | |||
1354 | /* Set Open System auth mode */ | ||
1355 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1356 | |||
1357 | /* Clear WEP keys and mark WEP as disabled */ | ||
1358 | assoc_req->secinfo.wep_enabled = 0; | ||
1359 | for (i = 0; i < 4; i++) | ||
1360 | assoc_req->wep_keys[i].len = 0; | ||
1361 | |||
1362 | set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); | ||
1363 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); | ||
1364 | |||
1365 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1366 | } | ||
1367 | |||
1368 | static void disable_wpa(struct assoc_request *assoc_req) | ||
1369 | { | ||
1370 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1371 | |||
1372 | memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key)); | ||
1373 | assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST; | ||
1374 | set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); | ||
1375 | |||
1376 | memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key)); | ||
1377 | assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST; | ||
1378 | set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); | ||
1379 | |||
1380 | assoc_req->secinfo.WPAenabled = 0; | ||
1381 | assoc_req->secinfo.WPA2enabled = 0; | ||
1382 | set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); | ||
1383 | |||
1384 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1385 | } | ||
1386 | |||
1387 | /** | ||
1388 | * @brief Set Encryption key | ||
1389 | * | ||
1390 | * @param dev A pointer to net_device structure | ||
1391 | * @param info A pointer to iw_request_info structure | ||
1392 | * @param vwrq A pointer to iw_param structure | ||
1393 | * @param extra A pointer to extra data buf | ||
1394 | * @return 0 --success, otherwise fail | ||
1395 | */ | ||
1396 | static int lbs_set_encode(struct net_device *dev, | ||
1397 | struct iw_request_info *info, | ||
1398 | struct iw_point *dwrq, char *extra) | ||
1399 | { | ||
1400 | int ret = 0; | ||
1401 | struct lbs_private *priv = dev->ml_priv; | ||
1402 | struct assoc_request * assoc_req; | ||
1403 | u16 is_default = 0, index = 0, set_tx_key = 0; | ||
1404 | |||
1405 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1406 | |||
1407 | mutex_lock(&priv->lock); | ||
1408 | assoc_req = lbs_get_association_request(priv); | ||
1409 | if (!assoc_req) { | ||
1410 | ret = -ENOMEM; | ||
1411 | goto out; | ||
1412 | } | ||
1413 | |||
1414 | if (dwrq->flags & IW_ENCODE_DISABLED) { | ||
1415 | disable_wep (assoc_req); | ||
1416 | disable_wpa (assoc_req); | ||
1417 | goto out; | ||
1418 | } | ||
1419 | |||
1420 | ret = validate_key_index(assoc_req->wep_tx_keyidx, | ||
1421 | (dwrq->flags & IW_ENCODE_INDEX), | ||
1422 | &index, &is_default); | ||
1423 | if (ret) { | ||
1424 | ret = -EINVAL; | ||
1425 | goto out; | ||
1426 | } | ||
1427 | |||
1428 | /* If WEP isn't enabled, or if there is no key data but a valid | ||
1429 | * index, set the TX key. | ||
1430 | */ | ||
1431 | if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default)) | ||
1432 | set_tx_key = 1; | ||
1433 | |||
1434 | ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key); | ||
1435 | if (ret) | ||
1436 | goto out; | ||
1437 | |||
1438 | if (dwrq->length) | ||
1439 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); | ||
1440 | if (set_tx_key) | ||
1441 | set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); | ||
1442 | |||
1443 | if (dwrq->flags & IW_ENCODE_RESTRICTED) { | ||
1444 | priv->authtype_auto = 0; | ||
1445 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | ||
1446 | } else if (dwrq->flags & IW_ENCODE_OPEN) { | ||
1447 | priv->authtype_auto = 0; | ||
1448 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1449 | } | ||
1450 | |||
1451 | out: | ||
1452 | if (ret == 0) { | ||
1453 | set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); | ||
1454 | lbs_postpone_association_work(priv); | ||
1455 | } else { | ||
1456 | lbs_cancel_association_work(priv); | ||
1457 | } | ||
1458 | mutex_unlock(&priv->lock); | ||
1459 | |||
1460 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1461 | return ret; | ||
1462 | } | ||
1463 | |||
1464 | /** | ||
1465 | * @brief Get Extended Encryption key (WPA/802.1x and WEP) | ||
1466 | * | ||
1467 | * @param dev A pointer to net_device structure | ||
1468 | * @param info A pointer to iw_request_info structure | ||
1469 | * @param vwrq A pointer to iw_param structure | ||
1470 | * @param extra A pointer to extra data buf | ||
1471 | * @return 0 on success, otherwise failure | ||
1472 | */ | ||
1473 | static int lbs_get_encodeext(struct net_device *dev, | ||
1474 | struct iw_request_info *info, | ||
1475 | struct iw_point *dwrq, | ||
1476 | char *extra) | ||
1477 | { | ||
1478 | int ret = -EINVAL; | ||
1479 | struct lbs_private *priv = dev->ml_priv; | ||
1480 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
1481 | int index, max_key_len; | ||
1482 | |||
1483 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1484 | |||
1485 | max_key_len = dwrq->length - sizeof(*ext); | ||
1486 | if (max_key_len < 0) | ||
1487 | goto out; | ||
1488 | |||
1489 | index = dwrq->flags & IW_ENCODE_INDEX; | ||
1490 | if (index) { | ||
1491 | if (index < 1 || index > 4) | ||
1492 | goto out; | ||
1493 | index--; | ||
1494 | } else { | ||
1495 | index = priv->wep_tx_keyidx; | ||
1496 | } | ||
1497 | |||
1498 | if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && | ||
1499 | ext->alg != IW_ENCODE_ALG_WEP) { | ||
1500 | if (index != 0 || priv->mode != IW_MODE_INFRA) | ||
1501 | goto out; | ||
1502 | } | ||
1503 | |||
1504 | dwrq->flags = index + 1; | ||
1505 | memset(ext, 0, sizeof(*ext)); | ||
1506 | |||
1507 | if ( !priv->secinfo.wep_enabled | ||
1508 | && !priv->secinfo.WPAenabled | ||
1509 | && !priv->secinfo.WPA2enabled) { | ||
1510 | ext->alg = IW_ENCODE_ALG_NONE; | ||
1511 | ext->key_len = 0; | ||
1512 | dwrq->flags |= IW_ENCODE_DISABLED; | ||
1513 | } else { | ||
1514 | u8 *key = NULL; | ||
1515 | |||
1516 | if ( priv->secinfo.wep_enabled | ||
1517 | && !priv->secinfo.WPAenabled | ||
1518 | && !priv->secinfo.WPA2enabled) { | ||
1519 | /* WEP */ | ||
1520 | ext->alg = IW_ENCODE_ALG_WEP; | ||
1521 | ext->key_len = priv->wep_keys[index].len; | ||
1522 | key = &priv->wep_keys[index].key[0]; | ||
1523 | } else if ( !priv->secinfo.wep_enabled | ||
1524 | && (priv->secinfo.WPAenabled || | ||
1525 | priv->secinfo.WPA2enabled)) { | ||
1526 | /* WPA */ | ||
1527 | struct enc_key * pkey = NULL; | ||
1528 | |||
1529 | if ( priv->wpa_mcast_key.len | ||
1530 | && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED)) | ||
1531 | pkey = &priv->wpa_mcast_key; | ||
1532 | else if ( priv->wpa_unicast_key.len | ||
1533 | && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED)) | ||
1534 | pkey = &priv->wpa_unicast_key; | ||
1535 | |||
1536 | if (pkey) { | ||
1537 | if (pkey->type == KEY_TYPE_ID_AES) { | ||
1538 | ext->alg = IW_ENCODE_ALG_CCMP; | ||
1539 | } else { | ||
1540 | ext->alg = IW_ENCODE_ALG_TKIP; | ||
1541 | } | ||
1542 | ext->key_len = pkey->len; | ||
1543 | key = &pkey->key[0]; | ||
1544 | } else { | ||
1545 | ext->alg = IW_ENCODE_ALG_TKIP; | ||
1546 | ext->key_len = 0; | ||
1547 | } | ||
1548 | } else { | ||
1549 | goto out; | ||
1550 | } | ||
1551 | |||
1552 | if (ext->key_len > max_key_len) { | ||
1553 | ret = -E2BIG; | ||
1554 | goto out; | ||
1555 | } | ||
1556 | |||
1557 | if (ext->key_len) | ||
1558 | memcpy(ext->key, key, ext->key_len); | ||
1559 | else | ||
1560 | dwrq->flags |= IW_ENCODE_NOKEY; | ||
1561 | dwrq->flags |= IW_ENCODE_ENABLED; | ||
1562 | } | ||
1563 | ret = 0; | ||
1564 | |||
1565 | out: | ||
1566 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1567 | return ret; | ||
1568 | } | ||
1569 | |||
1570 | /** | ||
1571 | * @brief Set Encryption key Extended (WPA/802.1x and WEP) | ||
1572 | * | ||
1573 | * @param dev A pointer to net_device structure | ||
1574 | * @param info A pointer to iw_request_info structure | ||
1575 | * @param vwrq A pointer to iw_param structure | ||
1576 | * @param extra A pointer to extra data buf | ||
1577 | * @return 0 --success, otherwise fail | ||
1578 | */ | ||
1579 | static int lbs_set_encodeext(struct net_device *dev, | ||
1580 | struct iw_request_info *info, | ||
1581 | struct iw_point *dwrq, | ||
1582 | char *extra) | ||
1583 | { | ||
1584 | int ret = 0; | ||
1585 | struct lbs_private *priv = dev->ml_priv; | ||
1586 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
1587 | int alg = ext->alg; | ||
1588 | struct assoc_request * assoc_req; | ||
1589 | |||
1590 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1591 | |||
1592 | mutex_lock(&priv->lock); | ||
1593 | assoc_req = lbs_get_association_request(priv); | ||
1594 | if (!assoc_req) { | ||
1595 | ret = -ENOMEM; | ||
1596 | goto out; | ||
1597 | } | ||
1598 | |||
1599 | if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) { | ||
1600 | disable_wep (assoc_req); | ||
1601 | disable_wpa (assoc_req); | ||
1602 | } else if (alg == IW_ENCODE_ALG_WEP) { | ||
1603 | u16 is_default = 0, index, set_tx_key = 0; | ||
1604 | |||
1605 | ret = validate_key_index(assoc_req->wep_tx_keyidx, | ||
1606 | (dwrq->flags & IW_ENCODE_INDEX), | ||
1607 | &index, &is_default); | ||
1608 | if (ret) | ||
1609 | goto out; | ||
1610 | |||
1611 | /* If WEP isn't enabled, or if there is no key data but a valid | ||
1612 | * index, or if the set-TX-key flag was passed, set the TX key. | ||
1613 | */ | ||
1614 | if ( !assoc_req->secinfo.wep_enabled | ||
1615 | || (dwrq->length == 0 && !is_default) | ||
1616 | || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) | ||
1617 | set_tx_key = 1; | ||
1618 | |||
1619 | /* Copy key to driver */ | ||
1620 | ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index, | ||
1621 | set_tx_key); | ||
1622 | if (ret) | ||
1623 | goto out; | ||
1624 | |||
1625 | if (dwrq->flags & IW_ENCODE_RESTRICTED) { | ||
1626 | priv->authtype_auto = 0; | ||
1627 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | ||
1628 | } else if (dwrq->flags & IW_ENCODE_OPEN) { | ||
1629 | priv->authtype_auto = 0; | ||
1630 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1631 | } | ||
1632 | |||
1633 | /* Mark the various WEP bits as modified */ | ||
1634 | set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); | ||
1635 | if (dwrq->length) | ||
1636 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); | ||
1637 | if (set_tx_key) | ||
1638 | set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); | ||
1639 | } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { | ||
1640 | struct enc_key * pkey; | ||
1641 | |||
1642 | /* validate key length */ | ||
1643 | if (((alg == IW_ENCODE_ALG_TKIP) | ||
1644 | && (ext->key_len != KEY_LEN_WPA_TKIP)) | ||
1645 | || ((alg == IW_ENCODE_ALG_CCMP) | ||
1646 | && (ext->key_len != KEY_LEN_WPA_AES))) { | ||
1647 | lbs_deb_wext("invalid size %d for key of alg " | ||
1648 | "type %d\n", | ||
1649 | ext->key_len, | ||
1650 | alg); | ||
1651 | ret = -EINVAL; | ||
1652 | goto out; | ||
1653 | } | ||
1654 | |||
1655 | if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { | ||
1656 | pkey = &assoc_req->wpa_mcast_key; | ||
1657 | set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); | ||
1658 | } else { | ||
1659 | pkey = &assoc_req->wpa_unicast_key; | ||
1660 | set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); | ||
1661 | } | ||
1662 | |||
1663 | memset(pkey, 0, sizeof (struct enc_key)); | ||
1664 | memcpy(pkey->key, ext->key, ext->key_len); | ||
1665 | pkey->len = ext->key_len; | ||
1666 | if (pkey->len) | ||
1667 | pkey->flags |= KEY_INFO_WPA_ENABLED; | ||
1668 | |||
1669 | /* Do this after zeroing key structure */ | ||
1670 | if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { | ||
1671 | pkey->flags |= KEY_INFO_WPA_MCAST; | ||
1672 | } else { | ||
1673 | pkey->flags |= KEY_INFO_WPA_UNICAST; | ||
1674 | } | ||
1675 | |||
1676 | if (alg == IW_ENCODE_ALG_TKIP) { | ||
1677 | pkey->type = KEY_TYPE_ID_TKIP; | ||
1678 | } else if (alg == IW_ENCODE_ALG_CCMP) { | ||
1679 | pkey->type = KEY_TYPE_ID_AES; | ||
1680 | } | ||
1681 | |||
1682 | /* If WPA isn't enabled yet, do that now */ | ||
1683 | if ( assoc_req->secinfo.WPAenabled == 0 | ||
1684 | && assoc_req->secinfo.WPA2enabled == 0) { | ||
1685 | assoc_req->secinfo.WPAenabled = 1; | ||
1686 | assoc_req->secinfo.WPA2enabled = 1; | ||
1687 | set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); | ||
1688 | } | ||
1689 | |||
1690 | /* Only disable wep if necessary: can't waste time here. */ | ||
1691 | if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE) | ||
1692 | disable_wep(assoc_req); | ||
1693 | } | ||
1694 | |||
1695 | out: | ||
1696 | if (ret == 0) { | ||
1697 | /* 802.1x and WPA rekeying must happen as quickly as possible, | ||
1698 | * especially during the 4-way handshake; thus if in | ||
1699 | * infrastructure mode, and either (a) 802.1x is enabled or | ||
1700 | * (b) WPA is being used, set the key right away. | ||
1701 | */ | ||
1702 | if (assoc_req->mode == IW_MODE_INFRA && | ||
1703 | ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) || | ||
1704 | (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) || | ||
1705 | assoc_req->secinfo.WPAenabled || | ||
1706 | assoc_req->secinfo.WPA2enabled)) { | ||
1707 | lbs_do_association_work(priv); | ||
1708 | } else | ||
1709 | lbs_postpone_association_work(priv); | ||
1710 | } else { | ||
1711 | lbs_cancel_association_work(priv); | ||
1712 | } | ||
1713 | mutex_unlock(&priv->lock); | ||
1714 | |||
1715 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1716 | return ret; | ||
1717 | } | ||
1718 | |||
1719 | |||
1720 | static int lbs_set_genie(struct net_device *dev, | ||
1721 | struct iw_request_info *info, | ||
1722 | struct iw_point *dwrq, | ||
1723 | char *extra) | ||
1724 | { | ||
1725 | struct lbs_private *priv = dev->ml_priv; | ||
1726 | int ret = 0; | ||
1727 | struct assoc_request * assoc_req; | ||
1728 | |||
1729 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1730 | |||
1731 | mutex_lock(&priv->lock); | ||
1732 | assoc_req = lbs_get_association_request(priv); | ||
1733 | if (!assoc_req) { | ||
1734 | ret = -ENOMEM; | ||
1735 | goto out; | ||
1736 | } | ||
1737 | |||
1738 | if (dwrq->length > MAX_WPA_IE_LEN || | ||
1739 | (dwrq->length && extra == NULL)) { | ||
1740 | ret = -EINVAL; | ||
1741 | goto out; | ||
1742 | } | ||
1743 | |||
1744 | if (dwrq->length) { | ||
1745 | memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length); | ||
1746 | assoc_req->wpa_ie_len = dwrq->length; | ||
1747 | } else { | ||
1748 | memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie)); | ||
1749 | assoc_req->wpa_ie_len = 0; | ||
1750 | } | ||
1751 | |||
1752 | out: | ||
1753 | if (ret == 0) { | ||
1754 | set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags); | ||
1755 | lbs_postpone_association_work(priv); | ||
1756 | } else { | ||
1757 | lbs_cancel_association_work(priv); | ||
1758 | } | ||
1759 | mutex_unlock(&priv->lock); | ||
1760 | |||
1761 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1762 | return ret; | ||
1763 | } | ||
1764 | |||
1765 | static int lbs_get_genie(struct net_device *dev, | ||
1766 | struct iw_request_info *info, | ||
1767 | struct iw_point *dwrq, | ||
1768 | char *extra) | ||
1769 | { | ||
1770 | int ret = 0; | ||
1771 | struct lbs_private *priv = dev->ml_priv; | ||
1772 | |||
1773 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1774 | |||
1775 | if (priv->wpa_ie_len == 0) { | ||
1776 | dwrq->length = 0; | ||
1777 | goto out; | ||
1778 | } | ||
1779 | |||
1780 | if (dwrq->length < priv->wpa_ie_len) { | ||
1781 | ret = -E2BIG; | ||
1782 | goto out; | ||
1783 | } | ||
1784 | |||
1785 | dwrq->length = priv->wpa_ie_len; | ||
1786 | memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len); | ||
1787 | |||
1788 | out: | ||
1789 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1790 | return ret; | ||
1791 | } | ||
1792 | |||
1793 | |||
1794 | static int lbs_set_auth(struct net_device *dev, | ||
1795 | struct iw_request_info *info, | ||
1796 | struct iw_param *dwrq, | ||
1797 | char *extra) | ||
1798 | { | ||
1799 | struct lbs_private *priv = dev->ml_priv; | ||
1800 | struct assoc_request * assoc_req; | ||
1801 | int ret = 0; | ||
1802 | int updated = 0; | ||
1803 | |||
1804 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1805 | |||
1806 | mutex_lock(&priv->lock); | ||
1807 | assoc_req = lbs_get_association_request(priv); | ||
1808 | if (!assoc_req) { | ||
1809 | ret = -ENOMEM; | ||
1810 | goto out; | ||
1811 | } | ||
1812 | |||
1813 | switch (dwrq->flags & IW_AUTH_INDEX) { | ||
1814 | case IW_AUTH_PRIVACY_INVOKED: | ||
1815 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
1816 | case IW_AUTH_TKIP_COUNTERMEASURES: | ||
1817 | case IW_AUTH_CIPHER_PAIRWISE: | ||
1818 | case IW_AUTH_CIPHER_GROUP: | ||
1819 | case IW_AUTH_DROP_UNENCRYPTED: | ||
1820 | /* | ||
1821 | * libertas does not use these parameters | ||
1822 | */ | ||
1823 | break; | ||
1824 | |||
1825 | case IW_AUTH_KEY_MGMT: | ||
1826 | assoc_req->secinfo.key_mgmt = dwrq->value; | ||
1827 | updated = 1; | ||
1828 | break; | ||
1829 | |||
1830 | case IW_AUTH_WPA_VERSION: | ||
1831 | if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { | ||
1832 | assoc_req->secinfo.WPAenabled = 0; | ||
1833 | assoc_req->secinfo.WPA2enabled = 0; | ||
1834 | disable_wpa (assoc_req); | ||
1835 | } | ||
1836 | if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) { | ||
1837 | assoc_req->secinfo.WPAenabled = 1; | ||
1838 | assoc_req->secinfo.wep_enabled = 0; | ||
1839 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1840 | } | ||
1841 | if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) { | ||
1842 | assoc_req->secinfo.WPA2enabled = 1; | ||
1843 | assoc_req->secinfo.wep_enabled = 0; | ||
1844 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1845 | } | ||
1846 | updated = 1; | ||
1847 | break; | ||
1848 | |||
1849 | case IW_AUTH_80211_AUTH_ALG: | ||
1850 | if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) { | ||
1851 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; | ||
1852 | } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) { | ||
1853 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1854 | } else if (dwrq->value & IW_AUTH_ALG_LEAP) { | ||
1855 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP; | ||
1856 | } else { | ||
1857 | ret = -EINVAL; | ||
1858 | } | ||
1859 | updated = 1; | ||
1860 | break; | ||
1861 | |||
1862 | case IW_AUTH_WPA_ENABLED: | ||
1863 | if (dwrq->value) { | ||
1864 | if (!assoc_req->secinfo.WPAenabled && | ||
1865 | !assoc_req->secinfo.WPA2enabled) { | ||
1866 | assoc_req->secinfo.WPAenabled = 1; | ||
1867 | assoc_req->secinfo.WPA2enabled = 1; | ||
1868 | assoc_req->secinfo.wep_enabled = 0; | ||
1869 | assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1870 | } | ||
1871 | } else { | ||
1872 | assoc_req->secinfo.WPAenabled = 0; | ||
1873 | assoc_req->secinfo.WPA2enabled = 0; | ||
1874 | disable_wpa (assoc_req); | ||
1875 | } | ||
1876 | updated = 1; | ||
1877 | break; | ||
1878 | |||
1879 | default: | ||
1880 | ret = -EOPNOTSUPP; | ||
1881 | break; | ||
1882 | } | ||
1883 | |||
1884 | out: | ||
1885 | if (ret == 0) { | ||
1886 | if (updated) | ||
1887 | set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); | ||
1888 | lbs_postpone_association_work(priv); | ||
1889 | } else if (ret != -EOPNOTSUPP) { | ||
1890 | lbs_cancel_association_work(priv); | ||
1891 | } | ||
1892 | mutex_unlock(&priv->lock); | ||
1893 | |||
1894 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1895 | return ret; | ||
1896 | } | ||
1897 | |||
1898 | static int lbs_get_auth(struct net_device *dev, | ||
1899 | struct iw_request_info *info, | ||
1900 | struct iw_param *dwrq, | ||
1901 | char *extra) | ||
1902 | { | ||
1903 | int ret = 0; | ||
1904 | struct lbs_private *priv = dev->ml_priv; | ||
1905 | |||
1906 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1907 | |||
1908 | switch (dwrq->flags & IW_AUTH_INDEX) { | ||
1909 | case IW_AUTH_KEY_MGMT: | ||
1910 | dwrq->value = priv->secinfo.key_mgmt; | ||
1911 | break; | ||
1912 | |||
1913 | case IW_AUTH_WPA_VERSION: | ||
1914 | dwrq->value = 0; | ||
1915 | if (priv->secinfo.WPAenabled) | ||
1916 | dwrq->value |= IW_AUTH_WPA_VERSION_WPA; | ||
1917 | if (priv->secinfo.WPA2enabled) | ||
1918 | dwrq->value |= IW_AUTH_WPA_VERSION_WPA2; | ||
1919 | if (!dwrq->value) | ||
1920 | dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED; | ||
1921 | break; | ||
1922 | |||
1923 | case IW_AUTH_80211_AUTH_ALG: | ||
1924 | dwrq->value = priv->secinfo.auth_mode; | ||
1925 | break; | ||
1926 | |||
1927 | case IW_AUTH_WPA_ENABLED: | ||
1928 | if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled) | ||
1929 | dwrq->value = 1; | ||
1930 | break; | ||
1931 | |||
1932 | default: | ||
1933 | ret = -EOPNOTSUPP; | ||
1934 | } | ||
1935 | |||
1936 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
1937 | return ret; | ||
1938 | } | ||
1939 | |||
1940 | |||
1941 | static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, | ||
1942 | struct iw_param *vwrq, char *extra) | ||
1943 | { | ||
1944 | int ret = 0; | ||
1945 | struct lbs_private *priv = dev->ml_priv; | ||
1946 | s16 dbm = (s16) vwrq->value; | ||
1947 | |||
1948 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1949 | |||
1950 | if (vwrq->disabled) { | ||
1951 | lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); | ||
1952 | goto out; | ||
1953 | } | ||
1954 | |||
1955 | if (vwrq->fixed == 0) { | ||
1956 | /* User requests automatic tx power control, however there are | ||
1957 | * many auto tx settings. For now use firmware defaults until | ||
1958 | * we come up with a good way to expose these to the user. */ | ||
1959 | if (priv->fwrelease < 0x09000000) { | ||
1960 | ret = lbs_set_power_adapt_cfg(priv, 1, | ||
1961 | POW_ADAPT_DEFAULT_P0, | ||
1962 | POW_ADAPT_DEFAULT_P1, | ||
1963 | POW_ADAPT_DEFAULT_P2); | ||
1964 | if (ret) | ||
1965 | goto out; | ||
1966 | } | ||
1967 | ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, | ||
1968 | TPC_DEFAULT_P2, 1); | ||
1969 | if (ret) | ||
1970 | goto out; | ||
1971 | dbm = priv->txpower_max; | ||
1972 | } else { | ||
1973 | /* Userspace check in iwrange if it should use dBm or mW, | ||
1974 | * therefore this should never happen... Jean II */ | ||
1975 | if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { | ||
1976 | ret = -EOPNOTSUPP; | ||
1977 | goto out; | ||
1978 | } | ||
1979 | |||
1980 | /* Validate requested power level against firmware allowed | ||
1981 | * levels */ | ||
1982 | if (priv->txpower_min && (dbm < priv->txpower_min)) { | ||
1983 | ret = -EINVAL; | ||
1984 | goto out; | ||
1985 | } | ||
1986 | |||
1987 | if (priv->txpower_max && (dbm > priv->txpower_max)) { | ||
1988 | ret = -EINVAL; | ||
1989 | goto out; | ||
1990 | } | ||
1991 | if (priv->fwrelease < 0x09000000) { | ||
1992 | ret = lbs_set_power_adapt_cfg(priv, 0, | ||
1993 | POW_ADAPT_DEFAULT_P0, | ||
1994 | POW_ADAPT_DEFAULT_P1, | ||
1995 | POW_ADAPT_DEFAULT_P2); | ||
1996 | if (ret) | ||
1997 | goto out; | ||
1998 | } | ||
1999 | ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, | ||
2000 | TPC_DEFAULT_P2, 1); | ||
2001 | if (ret) | ||
2002 | goto out; | ||
2003 | } | ||
2004 | |||
2005 | /* If the radio was off, turn it on */ | ||
2006 | if (!priv->radio_on) { | ||
2007 | ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1); | ||
2008 | if (ret) | ||
2009 | goto out; | ||
2010 | } | ||
2011 | |||
2012 | lbs_deb_wext("txpower set %d dBm\n", dbm); | ||
2013 | |||
2014 | ret = lbs_set_tx_power(priv, dbm); | ||
2015 | |||
2016 | out: | ||
2017 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
2018 | return ret; | ||
2019 | } | ||
2020 | |||
2021 | static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, | ||
2022 | struct iw_point *dwrq, char *extra) | ||
2023 | { | ||
2024 | struct lbs_private *priv = dev->ml_priv; | ||
2025 | |||
2026 | lbs_deb_enter(LBS_DEB_WEXT); | ||
2027 | |||
2028 | /* | ||
2029 | * Note : if dwrq->flags != 0, we should get the relevant SSID from | ||
2030 | * the SSID list... | ||
2031 | */ | ||
2032 | |||
2033 | /* | ||
2034 | * Get the current SSID | ||
2035 | */ | ||
2036 | if (priv->connect_status == LBS_CONNECTED) { | ||
2037 | memcpy(extra, priv->curbssparams.ssid, | ||
2038 | priv->curbssparams.ssid_len); | ||
2039 | } else { | ||
2040 | memset(extra, 0, 32); | ||
2041 | } | ||
2042 | /* | ||
2043 | * If none, we may want to get the one that was set | ||
2044 | */ | ||
2045 | |||
2046 | dwrq->length = priv->curbssparams.ssid_len; | ||
2047 | |||
2048 | dwrq->flags = 1; /* active */ | ||
2049 | |||
2050 | lbs_deb_leave(LBS_DEB_WEXT); | ||
2051 | return 0; | ||
2052 | } | ||
2053 | |||
2054 | static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | ||
2055 | struct iw_point *dwrq, char *extra) | ||
2056 | { | ||
2057 | struct lbs_private *priv = dev->ml_priv; | ||
2058 | int ret = 0; | ||
2059 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
2060 | u8 ssid_len = 0; | ||
2061 | struct assoc_request * assoc_req; | ||
2062 | int in_ssid_len = dwrq->length; | ||
2063 | DECLARE_SSID_BUF(ssid_buf); | ||
2064 | |||
2065 | lbs_deb_enter(LBS_DEB_WEXT); | ||
2066 | |||
2067 | if (!priv->radio_on) { | ||
2068 | ret = -EINVAL; | ||
2069 | goto out; | ||
2070 | } | ||
2071 | |||
2072 | /* Check the size of the string */ | ||
2073 | if (in_ssid_len > IEEE80211_MAX_SSID_LEN) { | ||
2074 | ret = -E2BIG; | ||
2075 | goto out; | ||
2076 | } | ||
2077 | |||
2078 | memset(&ssid, 0, sizeof(ssid)); | ||
2079 | |||
2080 | if (!dwrq->flags || !in_ssid_len) { | ||
2081 | /* "any" SSID requested; leave SSID blank */ | ||
2082 | } else { | ||
2083 | /* Specific SSID requested */ | ||
2084 | memcpy(&ssid, extra, in_ssid_len); | ||
2085 | ssid_len = in_ssid_len; | ||
2086 | } | ||
2087 | |||
2088 | if (!ssid_len) { | ||
2089 | lbs_deb_wext("requested any SSID\n"); | ||
2090 | } else { | ||
2091 | lbs_deb_wext("requested SSID '%s'\n", | ||
2092 | print_ssid(ssid_buf, ssid, ssid_len)); | ||
2093 | } | ||
2094 | |||
2095 | out: | ||
2096 | mutex_lock(&priv->lock); | ||
2097 | if (ret == 0) { | ||
2098 | /* Get or create the current association request */ | ||
2099 | assoc_req = lbs_get_association_request(priv); | ||
2100 | if (!assoc_req) { | ||
2101 | ret = -ENOMEM; | ||
2102 | } else { | ||
2103 | /* Copy the SSID to the association request */ | ||
2104 | memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN); | ||
2105 | assoc_req->ssid_len = ssid_len; | ||
2106 | set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); | ||
2107 | lbs_postpone_association_work(priv); | ||
2108 | } | ||
2109 | } | ||
2110 | |||
2111 | /* Cancel the association request if there was an error */ | ||
2112 | if (ret != 0) { | ||
2113 | lbs_cancel_association_work(priv); | ||
2114 | } | ||
2115 | |||
2116 | mutex_unlock(&priv->lock); | ||
2117 | |||
2118 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
2119 | return ret; | ||
2120 | } | ||
2121 | |||
2122 | #ifdef CONFIG_LIBERTAS_MESH | ||
2123 | static int lbs_mesh_get_essid(struct net_device *dev, | ||
2124 | struct iw_request_info *info, | ||
2125 | struct iw_point *dwrq, char *extra) | ||
2126 | { | ||
2127 | struct lbs_private *priv = dev->ml_priv; | ||
2128 | |||
2129 | lbs_deb_enter(LBS_DEB_WEXT); | ||
2130 | |||
2131 | memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len); | ||
2132 | |||
2133 | dwrq->length = priv->mesh_ssid_len; | ||
2134 | |||
2135 | dwrq->flags = 1; /* active */ | ||
2136 | |||
2137 | lbs_deb_leave(LBS_DEB_WEXT); | ||
2138 | return 0; | ||
2139 | } | ||
2140 | |||
2141 | static int lbs_mesh_set_essid(struct net_device *dev, | ||
2142 | struct iw_request_info *info, | ||
2143 | struct iw_point *dwrq, char *extra) | ||
2144 | { | ||
2145 | struct lbs_private *priv = dev->ml_priv; | ||
2146 | int ret = 0; | ||
2147 | |||
2148 | lbs_deb_enter(LBS_DEB_WEXT); | ||
2149 | |||
2150 | if (!priv->radio_on) { | ||
2151 | ret = -EINVAL; | ||
2152 | goto out; | ||
2153 | } | ||
2154 | |||
2155 | /* Check the size of the string */ | ||
2156 | if (dwrq->length > IEEE80211_MAX_SSID_LEN) { | ||
2157 | ret = -E2BIG; | ||
2158 | goto out; | ||
2159 | } | ||
2160 | |||
2161 | if (!dwrq->flags || !dwrq->length) { | ||
2162 | ret = -EINVAL; | ||
2163 | goto out; | ||
2164 | } else { | ||
2165 | /* Specific SSID requested */ | ||
2166 | memcpy(priv->mesh_ssid, extra, dwrq->length); | ||
2167 | priv->mesh_ssid_len = dwrq->length; | ||
2168 | } | ||
2169 | |||
2170 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
2171 | priv->channel); | ||
2172 | out: | ||
2173 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
2174 | return ret; | ||
2175 | } | ||
2176 | #endif | ||
2177 | |||
2178 | /** | ||
2179 | * @brief Connect to the AP or Ad-hoc Network with specific bssid | ||
2180 | * | ||
2181 | * @param dev A pointer to net_device structure | ||
2182 | * @param info A pointer to iw_request_info structure | ||
2183 | * @param awrq A pointer to iw_param structure | ||
2184 | * @param extra A pointer to extra data buf | ||
2185 | * @return 0 --success, otherwise fail | ||
2186 | */ | ||
2187 | static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, | ||
2188 | struct sockaddr *awrq, char *extra) | ||
2189 | { | ||
2190 | struct lbs_private *priv = dev->ml_priv; | ||
2191 | struct assoc_request * assoc_req; | ||
2192 | int ret = 0; | ||
2193 | |||
2194 | lbs_deb_enter(LBS_DEB_WEXT); | ||
2195 | |||
2196 | if (!priv->radio_on) | ||
2197 | return -EINVAL; | ||
2198 | |||
2199 | if (awrq->sa_family != ARPHRD_ETHER) | ||
2200 | return -EINVAL; | ||
2201 | |||
2202 | lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data); | ||
2203 | |||
2204 | mutex_lock(&priv->lock); | ||
2205 | |||
2206 | /* Get or create the current association request */ | ||
2207 | assoc_req = lbs_get_association_request(priv); | ||
2208 | if (!assoc_req) { | ||
2209 | lbs_cancel_association_work(priv); | ||
2210 | ret = -ENOMEM; | ||
2211 | } else { | ||
2212 | /* Copy the BSSID to the association request */ | ||
2213 | memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN); | ||
2214 | set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags); | ||
2215 | lbs_postpone_association_work(priv); | ||
2216 | } | ||
2217 | |||
2218 | mutex_unlock(&priv->lock); | ||
2219 | |||
2220 | return ret; | ||
2221 | } | ||
2222 | |||
2223 | /* | ||
2224 | * iwconfig settable callbacks | ||
2225 | */ | ||
2226 | static const iw_handler lbs_handler[] = { | ||
2227 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | ||
2228 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ | ||
2229 | (iw_handler) NULL, /* SIOCSIWNWID */ | ||
2230 | (iw_handler) NULL, /* SIOCGIWNWID */ | ||
2231 | (iw_handler) lbs_set_freq, /* SIOCSIWFREQ */ | ||
2232 | (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */ | ||
2233 | (iw_handler) lbs_set_mode, /* SIOCSIWMODE */ | ||
2234 | (iw_handler) lbs_get_mode, /* SIOCGIWMODE */ | ||
2235 | (iw_handler) NULL, /* SIOCSIWSENS */ | ||
2236 | (iw_handler) NULL, /* SIOCGIWSENS */ | ||
2237 | (iw_handler) NULL, /* SIOCSIWRANGE */ | ||
2238 | (iw_handler) lbs_get_range, /* SIOCGIWRANGE */ | ||
2239 | (iw_handler) NULL, /* SIOCSIWPRIV */ | ||
2240 | (iw_handler) NULL, /* SIOCGIWPRIV */ | ||
2241 | (iw_handler) NULL, /* SIOCSIWSTATS */ | ||
2242 | (iw_handler) NULL, /* SIOCGIWSTATS */ | ||
2243 | iw_handler_set_spy, /* SIOCSIWSPY */ | ||
2244 | iw_handler_get_spy, /* SIOCGIWSPY */ | ||
2245 | iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ | ||
2246 | iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ | ||
2247 | (iw_handler) lbs_set_wap, /* SIOCSIWAP */ | ||
2248 | (iw_handler) lbs_get_wap, /* SIOCGIWAP */ | ||
2249 | (iw_handler) NULL, /* SIOCSIWMLME */ | ||
2250 | (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ | ||
2251 | (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */ | ||
2252 | (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */ | ||
2253 | (iw_handler) lbs_set_essid, /* SIOCSIWESSID */ | ||
2254 | (iw_handler) lbs_get_essid, /* SIOCGIWESSID */ | ||
2255 | (iw_handler) lbs_set_nick, /* SIOCSIWNICKN */ | ||
2256 | (iw_handler) lbs_get_nick, /* SIOCGIWNICKN */ | ||
2257 | (iw_handler) NULL, /* -- hole -- */ | ||
2258 | (iw_handler) NULL, /* -- hole -- */ | ||
2259 | (iw_handler) lbs_set_rate, /* SIOCSIWRATE */ | ||
2260 | (iw_handler) lbs_get_rate, /* SIOCGIWRATE */ | ||
2261 | (iw_handler) lbs_set_rts, /* SIOCSIWRTS */ | ||
2262 | (iw_handler) lbs_get_rts, /* SIOCGIWRTS */ | ||
2263 | (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */ | ||
2264 | (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */ | ||
2265 | (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */ | ||
2266 | (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */ | ||
2267 | (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */ | ||
2268 | (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */ | ||
2269 | (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */ | ||
2270 | (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */ | ||
2271 | (iw_handler) lbs_set_power, /* SIOCSIWPOWER */ | ||
2272 | (iw_handler) lbs_get_power, /* SIOCGIWPOWER */ | ||
2273 | (iw_handler) NULL, /* -- hole -- */ | ||
2274 | (iw_handler) NULL, /* -- hole -- */ | ||
2275 | (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */ | ||
2276 | (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */ | ||
2277 | (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */ | ||
2278 | (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */ | ||
2279 | (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */ | ||
2280 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | ||
2281 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | ||
2282 | }; | ||
2283 | struct iw_handler_def lbs_handler_def = { | ||
2284 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2285 | .standard = (iw_handler *) lbs_handler, | ||
2286 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2287 | }; | ||
2288 | |||
2289 | #ifdef CONFIG_LIBERTAS_MESH | ||
2290 | static const iw_handler mesh_wlan_handler[] = { | ||
2291 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | ||
2292 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ | ||
2293 | (iw_handler) NULL, /* SIOCSIWNWID */ | ||
2294 | (iw_handler) NULL, /* SIOCGIWNWID */ | ||
2295 | (iw_handler) lbs_mesh_set_freq, /* SIOCSIWFREQ */ | ||
2296 | (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */ | ||
2297 | (iw_handler) NULL, /* SIOCSIWMODE */ | ||
2298 | (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */ | ||
2299 | (iw_handler) NULL, /* SIOCSIWSENS */ | ||
2300 | (iw_handler) NULL, /* SIOCGIWSENS */ | ||
2301 | (iw_handler) NULL, /* SIOCSIWRANGE */ | ||
2302 | (iw_handler) lbs_get_range, /* SIOCGIWRANGE */ | ||
2303 | (iw_handler) NULL, /* SIOCSIWPRIV */ | ||
2304 | (iw_handler) NULL, /* SIOCGIWPRIV */ | ||
2305 | (iw_handler) NULL, /* SIOCSIWSTATS */ | ||
2306 | (iw_handler) NULL, /* SIOCGIWSTATS */ | ||
2307 | iw_handler_set_spy, /* SIOCSIWSPY */ | ||
2308 | iw_handler_get_spy, /* SIOCGIWSPY */ | ||
2309 | iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ | ||
2310 | iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ | ||
2311 | (iw_handler) NULL, /* SIOCSIWAP */ | ||
2312 | (iw_handler) NULL, /* SIOCGIWAP */ | ||
2313 | (iw_handler) NULL, /* SIOCSIWMLME */ | ||
2314 | (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ | ||
2315 | (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */ | ||
2316 | (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */ | ||
2317 | (iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */ | ||
2318 | (iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */ | ||
2319 | (iw_handler) NULL, /* SIOCSIWNICKN */ | ||
2320 | (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */ | ||
2321 | (iw_handler) NULL, /* -- hole -- */ | ||
2322 | (iw_handler) NULL, /* -- hole -- */ | ||
2323 | (iw_handler) lbs_set_rate, /* SIOCSIWRATE */ | ||
2324 | (iw_handler) lbs_get_rate, /* SIOCGIWRATE */ | ||
2325 | (iw_handler) lbs_set_rts, /* SIOCSIWRTS */ | ||
2326 | (iw_handler) lbs_get_rts, /* SIOCGIWRTS */ | ||
2327 | (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */ | ||
2328 | (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */ | ||
2329 | (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */ | ||
2330 | (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */ | ||
2331 | (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */ | ||
2332 | (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */ | ||
2333 | (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */ | ||
2334 | (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */ | ||
2335 | (iw_handler) lbs_set_power, /* SIOCSIWPOWER */ | ||
2336 | (iw_handler) lbs_get_power, /* SIOCGIWPOWER */ | ||
2337 | (iw_handler) NULL, /* -- hole -- */ | ||
2338 | (iw_handler) NULL, /* -- hole -- */ | ||
2339 | (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */ | ||
2340 | (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */ | ||
2341 | (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */ | ||
2342 | (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */ | ||
2343 | (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */ | ||
2344 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | ||
2345 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | ||
2346 | }; | ||
2347 | |||
2348 | struct iw_handler_def mesh_handler_def = { | ||
2349 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), | ||
2350 | .standard = (iw_handler *) mesh_wlan_handler, | ||
2351 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2352 | }; | ||
2353 | #endif | ||
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h deleted file mode 100644 index f3f19fe8c6c6..000000000000 --- a/drivers/net/wireless/libertas/wext.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /** | ||
2 | * This file contains definition for IOCTL call. | ||
3 | */ | ||
4 | #ifndef _LBS_WEXT_H_ | ||
5 | #define _LBS_WEXT_H_ | ||
6 | |||
7 | void lbs_send_disconnect_notification(struct lbs_private *priv); | ||
8 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); | ||
9 | |||
10 | struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | ||
11 | struct lbs_private *priv, | ||
12 | u8 band, | ||
13 | u16 channel); | ||
14 | |||
15 | extern struct iw_handler_def lbs_handler_def; | ||
16 | |||
17 | #endif | ||
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index c445500ffc61..b172f5d87a3b 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -538,7 +538,8 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
538 | return; | 538 | return; |
539 | } | 539 | } |
540 | 540 | ||
541 | syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); | 541 | syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), |
542 | GFP_ATOMIC); | ||
542 | if (!syncfwheader) { | 543 | if (!syncfwheader) { |
543 | lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); | 544 | lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); |
544 | kfree_skb(skb); | 545 | kfree_skb(skb); |
@@ -546,8 +547,6 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
546 | return; | 547 | return; |
547 | } | 548 | } |
548 | 549 | ||
549 | memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader)); | ||
550 | |||
551 | if (!syncfwheader->cmd) { | 550 | if (!syncfwheader->cmd) { |
552 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); | 551 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); |
553 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", | 552 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 6f8cb3ee6fed..af50895e4bb0 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1291,6 +1291,11 @@ static int __init init_mac80211_hwsim(void) | |||
1291 | hw->wiphy->n_addresses = 2; | 1291 | hw->wiphy->n_addresses = 2; |
1292 | hw->wiphy->addresses = data->addresses; | 1292 | hw->wiphy->addresses = data->addresses; |
1293 | 1293 | ||
1294 | if (fake_hw_scan) { | ||
1295 | hw->wiphy->max_scan_ssids = 255; | ||
1296 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
1297 | } | ||
1298 | |||
1294 | hw->channel_change_time = 1; | 1299 | hw->channel_change_time = 1; |
1295 | hw->queues = 4; | 1300 | hw->queues = 4; |
1296 | hw->wiphy->interface_modes = | 1301 | hw->wiphy->interface_modes = |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 808adb909095..cd37b2ac5356 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -109,7 +109,7 @@ struct mwl8k_rx_queue { | |||
109 | dma_addr_t rxd_dma; | 109 | dma_addr_t rxd_dma; |
110 | struct { | 110 | struct { |
111 | struct sk_buff *skb; | 111 | struct sk_buff *skb; |
112 | DECLARE_PCI_UNMAP_ADDR(dma) | 112 | DEFINE_DMA_UNMAP_ADDR(dma); |
113 | } *buf; | 113 | } *buf; |
114 | }; | 114 | }; |
115 | 115 | ||
@@ -963,7 +963,7 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) | |||
963 | if (rxq->tail == MWL8K_RX_DESCS) | 963 | if (rxq->tail == MWL8K_RX_DESCS) |
964 | rxq->tail = 0; | 964 | rxq->tail = 0; |
965 | rxq->buf[rx].skb = skb; | 965 | rxq->buf[rx].skb = skb; |
966 | pci_unmap_addr_set(&rxq->buf[rx], dma, addr); | 966 | dma_unmap_addr_set(&rxq->buf[rx], dma, addr); |
967 | 967 | ||
968 | rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size); | 968 | rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size); |
969 | priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ); | 969 | priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ); |
@@ -984,9 +984,9 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) | |||
984 | for (i = 0; i < MWL8K_RX_DESCS; i++) { | 984 | for (i = 0; i < MWL8K_RX_DESCS; i++) { |
985 | if (rxq->buf[i].skb != NULL) { | 985 | if (rxq->buf[i].skb != NULL) { |
986 | pci_unmap_single(priv->pdev, | 986 | pci_unmap_single(priv->pdev, |
987 | pci_unmap_addr(&rxq->buf[i], dma), | 987 | dma_unmap_addr(&rxq->buf[i], dma), |
988 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); | 988 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); |
989 | pci_unmap_addr_set(&rxq->buf[i], dma, 0); | 989 | dma_unmap_addr_set(&rxq->buf[i], dma, 0); |
990 | 990 | ||
991 | kfree_skb(rxq->buf[i].skb); | 991 | kfree_skb(rxq->buf[i].skb); |
992 | rxq->buf[i].skb = NULL; | 992 | rxq->buf[i].skb = NULL; |
@@ -1060,9 +1060,9 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1060 | rxq->buf[rxq->head].skb = NULL; | 1060 | rxq->buf[rxq->head].skb = NULL; |
1061 | 1061 | ||
1062 | pci_unmap_single(priv->pdev, | 1062 | pci_unmap_single(priv->pdev, |
1063 | pci_unmap_addr(&rxq->buf[rxq->head], dma), | 1063 | dma_unmap_addr(&rxq->buf[rxq->head], dma), |
1064 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); | 1064 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); |
1065 | pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); | 1065 | dma_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); |
1066 | 1066 | ||
1067 | rxq->head++; | 1067 | rxq->head++; |
1068 | if (rxq->head == MWL8K_RX_DESCS) | 1068 | if (rxq->head == MWL8K_RX_DESCS) |
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index 6da85e75fce0..f750f49bbd4e 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c | |||
@@ -68,7 +68,7 @@ struct dblock { | |||
68 | } __attribute__ ((packed)); | 68 | } __attribute__ ((packed)); |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * Plug Data References are located in in the image after the last data | 71 | * Plug Data References are located in the image after the last data |
72 | * block. They refer to areas in the adapter memory where the plug data | 72 | * block. They refer to areas in the adapter memory where the plug data |
73 | * items with matching ID should be written. | 73 | * items with matching ID should be written. |
74 | */ | 74 | */ |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 78f089baa8c9..020da76c9558 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
@@ -356,12 +356,10 @@ static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv, | |||
356 | { | 356 | { |
357 | struct request_context *ctx; | 357 | struct request_context *ctx; |
358 | 358 | ||
359 | ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); | 359 | ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC); |
360 | if (!ctx) | 360 | if (!ctx) |
361 | return NULL; | 361 | return NULL; |
362 | 362 | ||
363 | memset(ctx, 0, sizeof(*ctx)); | ||
364 | |||
365 | ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC); | 363 | ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC); |
366 | if (!ctx->buf) { | 364 | if (!ctx->buf) { |
367 | kfree(ctx); | 365 | kfree(ctx); |
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 5775124e2aee..a63108c6df7d 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
@@ -993,11 +993,9 @@ static int orinoco_ioctl_set_genie(struct net_device *dev, | |||
993 | return -EINVAL; | 993 | return -EINVAL; |
994 | 994 | ||
995 | if (wrqu->data.length) { | 995 | if (wrqu->data.length) { |
996 | buf = kmalloc(wrqu->data.length, GFP_KERNEL); | 996 | buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); |
997 | if (buf == NULL) | 997 | if (buf == NULL) |
998 | return -ENOMEM; | 998 | return -ENOMEM; |
999 | |||
1000 | memcpy(buf, extra, wrqu->data.length); | ||
1001 | } else | 999 | } else |
1002 | buf = NULL; | 1000 | buf = NULL; |
1003 | 1001 | ||
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 187e263b045a..e51650ed49f2 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
@@ -599,13 +599,13 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
599 | } | 599 | } |
600 | break; | 600 | break; |
601 | case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: | 601 | case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: |
602 | priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); | 602 | priv->iq_autocal = kmemdup(entry->data, data_len, |
603 | GFP_KERNEL); | ||
603 | if (!priv->iq_autocal) { | 604 | if (!priv->iq_autocal) { |
604 | err = -ENOMEM; | 605 | err = -ENOMEM; |
605 | goto err; | 606 | goto err; |
606 | } | 607 | } |
607 | 608 | ||
608 | memcpy(priv->iq_autocal, entry->data, data_len); | ||
609 | priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); | 609 | priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); |
610 | break; | 610 | break; |
611 | case PDR_DEFAULT_COUNTRY: | 611 | case PDR_DEFAULT_COUNTRY: |
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index c8f09da1f84d..087bf0698a5a 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
@@ -697,9 +697,7 @@ static int __devexit p54spi_remove(struct spi_device *spi) | |||
697 | 697 | ||
698 | static struct spi_driver p54spi_driver = { | 698 | static struct spi_driver p54spi_driver = { |
699 | .driver = { | 699 | .driver = { |
700 | /* use cx3110x name because board-n800.c uses that for the | 700 | .name = "p54spi", |
701 | * SPI port */ | ||
702 | .name = "cx3110x", | ||
703 | .bus = &spi_bus_type, | 701 | .bus = &spi_bus_type, |
704 | .owner = THIS_MODULE, | 702 | .owner = THIS_MODULE, |
705 | }, | 703 | }, |
@@ -733,3 +731,4 @@ module_exit(p54spi_exit); | |||
733 | MODULE_LICENSE("GPL"); | 731 | MODULE_LICENSE("GPL"); |
734 | MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); | 732 | MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); |
735 | MODULE_ALIAS("spi:cx3110x"); | 733 | MODULE_ALIAS("spi:cx3110x"); |
734 | MODULE_ALIAS("spi:p54spi"); | ||
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 73073259f508..ad595958b7df 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -69,7 +69,8 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
69 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ | 69 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ |
70 | {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ | 70 | {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ |
71 | {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ | 71 | {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ |
72 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ | 72 | /* {USB_DEVICE(0x0cde, 0x0006)}, * Medion MD40900 already listed above, |
73 | * just noting it here for clarity */ | ||
73 | {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ | 74 | {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ |
74 | {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ | 75 | {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ |
75 | {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ | 76 | {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ |
@@ -434,10 +435,9 @@ static int p54u_firmware_reset_3887(struct ieee80211_hw *dev) | |||
434 | u8 *buf; | 435 | u8 *buf; |
435 | int ret; | 436 | int ret; |
436 | 437 | ||
437 | buf = kmalloc(4, GFP_KERNEL); | 438 | buf = kmemdup(p54u_romboot_3887, 4, GFP_KERNEL); |
438 | if (!buf) | 439 | if (!buf) |
439 | return -ENOMEM; | 440 | return -ENOMEM; |
440 | memcpy(buf, p54u_romboot_3887, 4); | ||
441 | ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, | 441 | ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, |
442 | buf, 4); | 442 | buf, 4); |
443 | kfree(buf); | 443 | kfree(buf); |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 8d1190c0f062..236e37526d07 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -2751,14 +2751,9 @@ prism54_hostapd(struct net_device *ndev, struct iw_point *p) | |||
2751 | p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) | 2751 | p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) |
2752 | return -EINVAL; | 2752 | return -EINVAL; |
2753 | 2753 | ||
2754 | param = kmalloc(p->length, GFP_KERNEL); | 2754 | param = memdup_user(p->pointer, p->length); |
2755 | if (param == NULL) | 2755 | if (IS_ERR(param)) |
2756 | return -ENOMEM; | 2756 | return PTR_ERR(param); |
2757 | |||
2758 | if (copy_from_user(param, p->pointer, p->length)) { | ||
2759 | kfree(param); | ||
2760 | return -EFAULT; | ||
2761 | } | ||
2762 | 2757 | ||
2763 | switch (param->cmd) { | 2758 | switch (param->cmd) { |
2764 | case PRISM2_SET_ENCRYPTION: | 2759 | case PRISM2_SET_ENCRYPTION: |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 4bd61ee627c0..5e26edb57d82 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -520,8 +520,9 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, | |||
520 | 520 | ||
521 | static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); | 521 | static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); |
522 | 522 | ||
523 | static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, | 523 | static int rndis_set_tx_power(struct wiphy *wiphy, |
524 | int dbm); | 524 | enum nl80211_tx_power_setting type, |
525 | int mbm); | ||
525 | static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm); | 526 | static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm); |
526 | 527 | ||
527 | static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, | 528 | static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, |
@@ -1856,20 +1857,25 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1856 | return 0; | 1857 | return 0; |
1857 | } | 1858 | } |
1858 | 1859 | ||
1859 | static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, | 1860 | static int rndis_set_tx_power(struct wiphy *wiphy, |
1860 | int dbm) | 1861 | enum nl80211_tx_power_setting type, |
1862 | int mbm) | ||
1861 | { | 1863 | { |
1862 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 1864 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
1863 | struct usbnet *usbdev = priv->usbdev; | 1865 | struct usbnet *usbdev = priv->usbdev; |
1864 | 1866 | ||
1865 | netdev_dbg(usbdev->net, "%s(): type:0x%x dbm:%i\n", | 1867 | netdev_dbg(usbdev->net, "%s(): type:0x%x mbm:%i\n", |
1866 | __func__, type, dbm); | 1868 | __func__, type, mbm); |
1869 | |||
1870 | if (mbm < 0 || (mbm % 100)) | ||
1871 | return -ENOTSUPP; | ||
1867 | 1872 | ||
1868 | /* Device doesn't support changing txpower after initialization, only | 1873 | /* Device doesn't support changing txpower after initialization, only |
1869 | * turn off/on radio. Support 'auto' mode and setting same dBm that is | 1874 | * turn off/on radio. Support 'auto' mode and setting same dBm that is |
1870 | * currently used. | 1875 | * currently used. |
1871 | */ | 1876 | */ |
1872 | if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) { | 1877 | if (type == NL80211_TX_POWER_AUTOMATIC || |
1878 | MBM_TO_DBM(mbm) == get_bcm4320_power_dbm(priv)) { | ||
1873 | if (!priv->radio_on) | 1879 | if (!priv->radio_on) |
1874 | disassociate(usbdev, true); /* turn on radio */ | 1880 | disassociate(usbdev, true); /* turn on radio */ |
1875 | 1881 | ||
@@ -2495,8 +2501,7 @@ static int rndis_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | |||
2495 | static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | 2501 | static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) |
2496 | { | 2502 | { |
2497 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2503 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2498 | struct ndis_80211_assoc_info *info; | 2504 | struct ndis_80211_assoc_info *info = NULL; |
2499 | u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32]; | ||
2500 | u8 bssid[ETH_ALEN]; | 2505 | u8 bssid[ETH_ALEN]; |
2501 | int resp_ie_len, req_ie_len; | 2506 | int resp_ie_len, req_ie_len; |
2502 | u8 *req_ie, *resp_ie; | 2507 | u8 *req_ie, *resp_ie; |
@@ -2515,23 +2520,43 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2515 | resp_ie = NULL; | 2520 | resp_ie = NULL; |
2516 | 2521 | ||
2517 | if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { | 2522 | if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { |
2518 | memset(assoc_buf, 0, sizeof(assoc_buf)); | 2523 | info = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL); |
2519 | info = (void *)assoc_buf; | 2524 | if (!info) { |
2525 | /* No memory? Try resume work later */ | ||
2526 | set_bit(WORK_LINK_UP, &priv->work_pending); | ||
2527 | queue_work(priv->workqueue, &priv->work); | ||
2528 | return; | ||
2529 | } | ||
2520 | 2530 | ||
2521 | /* Get association info IEs from device and send them back to | 2531 | /* Get association info IEs from device. */ |
2522 | * userspace. */ | 2532 | ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); |
2523 | ret = get_association_info(usbdev, info, sizeof(assoc_buf)); | ||
2524 | if (!ret) { | 2533 | if (!ret) { |
2525 | req_ie_len = le32_to_cpu(info->req_ie_length); | 2534 | req_ie_len = le32_to_cpu(info->req_ie_length); |
2526 | if (req_ie_len > 0) { | 2535 | if (req_ie_len > 0) { |
2527 | offset = le32_to_cpu(info->offset_req_ies); | 2536 | offset = le32_to_cpu(info->offset_req_ies); |
2537 | |||
2538 | if (offset > CONTROL_BUFFER_SIZE) | ||
2539 | offset = CONTROL_BUFFER_SIZE; | ||
2540 | |||
2528 | req_ie = (u8 *)info + offset; | 2541 | req_ie = (u8 *)info + offset; |
2542 | |||
2543 | if (offset + req_ie_len > CONTROL_BUFFER_SIZE) | ||
2544 | req_ie_len = | ||
2545 | CONTROL_BUFFER_SIZE - offset; | ||
2529 | } | 2546 | } |
2530 | 2547 | ||
2531 | resp_ie_len = le32_to_cpu(info->resp_ie_length); | 2548 | resp_ie_len = le32_to_cpu(info->resp_ie_length); |
2532 | if (resp_ie_len > 0) { | 2549 | if (resp_ie_len > 0) { |
2533 | offset = le32_to_cpu(info->offset_resp_ies); | 2550 | offset = le32_to_cpu(info->offset_resp_ies); |
2551 | |||
2552 | if (offset > CONTROL_BUFFER_SIZE) | ||
2553 | offset = CONTROL_BUFFER_SIZE; | ||
2554 | |||
2534 | resp_ie = (u8 *)info + offset; | 2555 | resp_ie = (u8 *)info + offset; |
2556 | |||
2557 | if (offset + resp_ie_len > CONTROL_BUFFER_SIZE) | ||
2558 | resp_ie_len = | ||
2559 | CONTROL_BUFFER_SIZE - offset; | ||
2535 | } | 2560 | } |
2536 | } | 2561 | } |
2537 | } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) | 2562 | } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) |
@@ -2563,6 +2588,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2563 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 2588 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
2564 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); | 2589 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); |
2565 | 2590 | ||
2591 | if (info != NULL) | ||
2592 | kfree(info); | ||
2593 | |||
2566 | priv->connected = true; | 2594 | priv->connected = true; |
2567 | memcpy(priv->bssid, bssid, ETH_ALEN); | 2595 | memcpy(priv->bssid, bssid, ETH_ALEN); |
2568 | 2596 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index ad2c98af7e9d..1eb882e15fb4 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1076,9 +1076,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, | |||
1076 | struct txentry_desc *txdesc) | 1076 | struct txentry_desc *txdesc) |
1077 | { | 1077 | { |
1078 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 1078 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
1079 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1080 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1081 | u32 word; | ||
1082 | u32 reg; | 1079 | u32 reg; |
1083 | 1080 | ||
1084 | /* | 1081 | /* |
@@ -1091,9 +1088,15 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, | |||
1091 | 1088 | ||
1092 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); | 1089 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); |
1093 | 1090 | ||
1094 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 1091 | /* |
1095 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | 1092 | * Write the TX descriptor for the beacon. |
1096 | rt2x00_desc_write(entry_priv->desc, 1, word); | 1093 | */ |
1094 | rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); | ||
1095 | |||
1096 | /* | ||
1097 | * Dump beacon to userspace through debugfs. | ||
1098 | */ | ||
1099 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); | ||
1097 | 1100 | ||
1098 | /* | 1101 | /* |
1099 | * Enable beaconing again. | 1102 | * Enable beaconing again. |
@@ -1226,7 +1229,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1226 | } | 1229 | } |
1227 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); | 1230 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); |
1228 | 1231 | ||
1229 | rt2x00lib_txdone(entry, &txdesc); | 1232 | rt2x00pci_txdone(entry, &txdesc); |
1230 | } | 1233 | } |
1231 | } | 1234 | } |
1232 | 1235 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 41da3d218c65..a29cb212f89a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1233,9 +1233,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, | |||
1233 | struct txentry_desc *txdesc) | 1233 | struct txentry_desc *txdesc) |
1234 | { | 1234 | { |
1235 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 1235 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
1236 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1237 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1238 | u32 word; | ||
1239 | u32 reg; | 1236 | u32 reg; |
1240 | 1237 | ||
1241 | /* | 1238 | /* |
@@ -1248,9 +1245,15 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, | |||
1248 | 1245 | ||
1249 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); | 1246 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); |
1250 | 1247 | ||
1251 | rt2x00_desc_read(entry_priv->desc, 1, &word); | 1248 | /* |
1252 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | 1249 | * Write the TX descriptor for the beacon. |
1253 | rt2x00_desc_write(entry_priv->desc, 1, word); | 1250 | */ |
1251 | rt2500pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); | ||
1252 | |||
1253 | /* | ||
1254 | * Dump beacon to userspace through debugfs. | ||
1255 | */ | ||
1256 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); | ||
1254 | 1257 | ||
1255 | /* | 1258 | /* |
1256 | * Enable beaconing again. | 1259 | * Enable beaconing again. |
@@ -1362,7 +1365,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1362 | } | 1365 | } |
1363 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); | 1366 | txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); |
1364 | 1367 | ||
1365 | rt2x00lib_txdone(entry, &txdesc); | 1368 | rt2x00pci_txdone(entry, &txdesc); |
1366 | } | 1369 | } |
1367 | } | 1370 | } |
1368 | 1371 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9ae96a626e6d..963238c89080 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -345,9 +345,9 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | |||
345 | struct rt2x00lib_crypto *crypto, | 345 | struct rt2x00lib_crypto *crypto, |
346 | struct ieee80211_key_conf *key) | 346 | struct ieee80211_key_conf *key) |
347 | { | 347 | { |
348 | int timeout; | ||
349 | u32 mask; | 348 | u32 mask; |
350 | u16 reg; | 349 | u16 reg; |
350 | enum cipher curr_cipher; | ||
351 | 351 | ||
352 | if (crypto->cmd == SET_KEY) { | 352 | if (crypto->cmd == SET_KEY) { |
353 | /* | 353 | /* |
@@ -358,6 +358,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | |||
358 | mask = TXRX_CSR0_KEY_ID.bit_mask; | 358 | mask = TXRX_CSR0_KEY_ID.bit_mask; |
359 | 359 | ||
360 | rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 360 | rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
361 | curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM); | ||
361 | reg &= mask; | 362 | reg &= mask; |
362 | 363 | ||
363 | if (reg && reg == mask) | 364 | if (reg && reg == mask) |
@@ -366,19 +367,17 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | |||
366 | reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); | 367 | reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); |
367 | 368 | ||
368 | key->hw_key_idx += reg ? ffz(reg) : 0; | 369 | key->hw_key_idx += reg ? ffz(reg) : 0; |
369 | |||
370 | /* | 370 | /* |
371 | * The encryption key doesn't fit within the CSR cache, | 371 | * Hardware requires that all keys use the same cipher |
372 | * this means we should allocate it separately and use | 372 | * (e.g. TKIP-only, AES-only, but not TKIP+AES). |
373 | * rt2x00usb_vendor_request() to send the key to the hardware. | 373 | * If this is not the first key, compare the cipher with the |
374 | * first one and fall back to SW crypto if not the same. | ||
374 | */ | 375 | */ |
375 | reg = KEY_ENTRY(key->hw_key_idx); | 376 | if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher) |
376 | timeout = REGISTER_TIMEOUT32(sizeof(crypto->key)); | 377 | return -EOPNOTSUPP; |
377 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | 378 | |
378 | USB_VENDOR_REQUEST_OUT, reg, | 379 | rt2500usb_register_multiwrite(rt2x00dev, reg, |
379 | crypto->key, | 380 | crypto->key, sizeof(crypto->key)); |
380 | sizeof(crypto->key), | ||
381 | timeout); | ||
382 | 381 | ||
383 | /* | 382 | /* |
384 | * The driver does not support the IV/EIV generation | 383 | * The driver does not support the IV/EIV generation |
@@ -1034,7 +1033,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1034 | struct txentry_desc *txdesc) | 1033 | struct txentry_desc *txdesc) |
1035 | { | 1034 | { |
1036 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 1035 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
1037 | __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); | 1036 | __le32 *txd = (__le32 *) skb->data; |
1038 | u32 word; | 1037 | u32 word; |
1039 | 1038 | ||
1040 | /* | 1039 | /* |
@@ -1080,6 +1079,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1080 | /* | 1079 | /* |
1081 | * Register descriptor details in skb frame descriptor. | 1080 | * Register descriptor details in skb frame descriptor. |
1082 | */ | 1081 | */ |
1082 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; | ||
1083 | skbdesc->desc = txd; | 1083 | skbdesc->desc = txd; |
1084 | skbdesc->desc_len = TXD_DESC_SIZE; | 1084 | skbdesc->desc_len = TXD_DESC_SIZE; |
1085 | } | 1085 | } |
@@ -1108,9 +1108,20 @@ static void rt2500usb_write_beacon(struct queue_entry *entry, | |||
1108 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | 1108 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); |
1109 | 1109 | ||
1110 | /* | 1110 | /* |
1111 | * Take the descriptor in front of the skb into account. | 1111 | * Add space for the descriptor in front of the skb. |
1112 | */ | 1112 | */ |
1113 | skb_push(entry->skb, TXD_DESC_SIZE); | 1113 | skb_push(entry->skb, TXD_DESC_SIZE); |
1114 | memset(entry->skb->data, 0, TXD_DESC_SIZE); | ||
1115 | |||
1116 | /* | ||
1117 | * Write the TX descriptor for the beacon. | ||
1118 | */ | ||
1119 | rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); | ||
1120 | |||
1121 | /* | ||
1122 | * Dump beacon to userspace through debugfs. | ||
1123 | */ | ||
1124 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); | ||
1114 | 1125 | ||
1115 | /* | 1126 | /* |
1116 | * USB devices cannot blindly pass the skb->len as the | 1127 | * USB devices cannot blindly pass the skb->len as the |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 2aa03751c341..3ed87badc2d3 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -63,7 +63,6 @@ | |||
63 | */ | 63 | */ |
64 | #define REV_RT2860C 0x0100 | 64 | #define REV_RT2860C 0x0100 |
65 | #define REV_RT2860D 0x0101 | 65 | #define REV_RT2860D 0x0101 |
66 | #define REV_RT2870D 0x0101 | ||
67 | #define REV_RT2872E 0x0200 | 66 | #define REV_RT2872E 0x0200 |
68 | #define REV_RT3070E 0x0200 | 67 | #define REV_RT3070E 0x0200 |
69 | #define REV_RT3070F 0x0201 | 68 | #define REV_RT3070F 0x0201 |
@@ -99,6 +98,21 @@ | |||
99 | */ | 98 | */ |
100 | 99 | ||
101 | /* | 100 | /* |
101 | * E2PROM_CSR: PCI EEPROM control register. | ||
102 | * RELOAD: Write 1 to reload eeprom content. | ||
103 | * TYPE: 0: 93c46, 1:93c66. | ||
104 | * LOAD_STATUS: 1:loading, 0:done. | ||
105 | */ | ||
106 | #define E2PROM_CSR 0x0004 | ||
107 | #define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) | ||
108 | #define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) | ||
109 | #define E2PROM_CSR_DATA_IN FIELD32(0x00000004) | ||
110 | #define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) | ||
111 | #define E2PROM_CSR_TYPE FIELD32(0x00000030) | ||
112 | #define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) | ||
113 | #define E2PROM_CSR_RELOAD FIELD32(0x00000080) | ||
114 | |||
115 | /* | ||
102 | * OPT_14: Unknown register used by rt3xxx devices. | 116 | * OPT_14: Unknown register used by rt3xxx devices. |
103 | */ | 117 | */ |
104 | #define OPT_14_CSR 0x0114 | 118 | #define OPT_14_CSR 0x0114 |
@@ -322,6 +336,39 @@ | |||
322 | #define RX_DRX_IDX 0x029c | 336 | #define RX_DRX_IDX 0x029c |
323 | 337 | ||
324 | /* | 338 | /* |
339 | * USB_DMA_CFG | ||
340 | * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. | ||
341 | * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. | ||
342 | * PHY_CLEAR: phy watch dog enable. | ||
343 | * TX_CLEAR: Clear USB DMA TX path. | ||
344 | * TXOP_HALT: Halt TXOP count down when TX buffer is full. | ||
345 | * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. | ||
346 | * RX_BULK_EN: Enable USB DMA Rx. | ||
347 | * TX_BULK_EN: Enable USB DMA Tx. | ||
348 | * EP_OUT_VALID: OUT endpoint data valid. | ||
349 | * RX_BUSY: USB DMA RX FSM busy. | ||
350 | * TX_BUSY: USB DMA TX FSM busy. | ||
351 | */ | ||
352 | #define USB_DMA_CFG 0x02a0 | ||
353 | #define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) | ||
354 | #define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) | ||
355 | #define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) | ||
356 | #define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) | ||
357 | #define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) | ||
358 | #define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) | ||
359 | #define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) | ||
360 | #define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) | ||
361 | #define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) | ||
362 | #define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) | ||
363 | #define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) | ||
364 | |||
365 | /* | ||
366 | * US_CYC_CNT | ||
367 | */ | ||
368 | #define US_CYC_CNT 0x02a4 | ||
369 | #define US_CYC_CNT_CLOCK_CYCLE FIELD32(0x000000ff) | ||
370 | |||
371 | /* | ||
325 | * PBF_SYS_CTRL | 372 | * PBF_SYS_CTRL |
326 | * HOST_RAM_WRITE: enable Host program ram write selection | 373 | * HOST_RAM_WRITE: enable Host program ram write selection |
327 | */ | 374 | */ |
@@ -1389,6 +1436,10 @@ struct mac_iveiv_entry { | |||
1389 | #define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) | 1436 | #define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) |
1390 | #define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) | 1437 | #define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) |
1391 | #define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) | 1438 | #define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) |
1439 | #define MAC_WCID_ATTRIBUTE_CIPHER_EXT FIELD32(0x00000400) | ||
1440 | #define MAC_WCID_ATTRIBUTE_BSS_IDX_EXT FIELD32(0x00000800) | ||
1441 | #define MAC_WCID_ATTRIBUTE_WAPI_MCBC FIELD32(0x00008000) | ||
1442 | #define MAC_WCID_ATTRIBUTE_WAPI_KEY_IDX FIELD32(0xff000000) | ||
1392 | 1443 | ||
1393 | /* | 1444 | /* |
1394 | * SHARED_KEY_MODE: | 1445 | * SHARED_KEY_MODE: |
@@ -1510,7 +1561,9 @@ struct mac_iveiv_entry { | |||
1510 | */ | 1561 | */ |
1511 | 1562 | ||
1512 | /* | 1563 | /* |
1513 | * BBP 1: TX Antenna | 1564 | * BBP 1: TX Antenna & Power |
1565 | * POWER: 0 - normal, 1 - drop tx power by 6dBm, 2 - drop tx power by 12dBm, | ||
1566 | * 3 - increase tx power by 6dBm | ||
1514 | */ | 1567 | */ |
1515 | #define BBP1_TX_POWER FIELD8(0x07) | 1568 | #define BBP1_TX_POWER FIELD8(0x07) |
1516 | #define BBP1_TX_ANTENNA FIELD8(0x18) | 1569 | #define BBP1_TX_ANTENNA FIELD8(0x18) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index db4250d1c8b3..14c361ae87be 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
2 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 3 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> |
3 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | 5 | ||
5 | Based on the original rt2800pci.c and rt2800usb.c. | 6 | Based on the original rt2800pci.c and rt2800usb.c. |
6 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | ||
7 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | 7 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> |
8 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 8 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
9 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | 9 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> |
@@ -38,16 +38,8 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | 39 | ||
40 | #include "rt2x00.h" | 40 | #include "rt2x00.h" |
41 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) | ||
42 | #include "rt2x00usb.h" | ||
43 | #endif | ||
44 | #include "rt2800lib.h" | 41 | #include "rt2800lib.h" |
45 | #include "rt2800.h" | 42 | #include "rt2800.h" |
46 | #include "rt2800usb.h" | ||
47 | |||
48 | MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); | ||
49 | MODULE_DESCRIPTION("rt2800 library"); | ||
50 | MODULE_LICENSE("GPL"); | ||
51 | 43 | ||
52 | /* | 44 | /* |
53 | * Register access. | 45 | * Register access. |
@@ -282,9 +274,8 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | |||
282 | } | 274 | } |
283 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); | 275 | EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); |
284 | 276 | ||
285 | void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc) | 277 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) |
286 | { | 278 | { |
287 | __le32 *txwi = (__le32 *)(skb->data - TXWI_DESC_SIZE); | ||
288 | u32 word; | 279 | u32 word; |
289 | 280 | ||
290 | /* | 281 | /* |
@@ -380,6 +371,67 @@ void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) | |||
380 | } | 371 | } |
381 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 372 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
382 | 373 | ||
374 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | ||
375 | { | ||
376 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
377 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
378 | unsigned int beacon_base; | ||
379 | u32 reg; | ||
380 | |||
381 | /* | ||
382 | * Disable beaconing while we are reloading the beacon data, | ||
383 | * otherwise we might be sending out invalid data. | ||
384 | */ | ||
385 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
386 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
387 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
388 | |||
389 | /* | ||
390 | * Add space for the TXWI in front of the skb. | ||
391 | */ | ||
392 | skb_push(entry->skb, TXWI_DESC_SIZE); | ||
393 | memset(entry->skb, 0, TXWI_DESC_SIZE); | ||
394 | |||
395 | /* | ||
396 | * Register descriptor details in skb frame descriptor. | ||
397 | */ | ||
398 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; | ||
399 | skbdesc->desc = entry->skb->data; | ||
400 | skbdesc->desc_len = TXWI_DESC_SIZE; | ||
401 | |||
402 | /* | ||
403 | * Add the TXWI for the beacon to the skb. | ||
404 | */ | ||
405 | rt2800_write_txwi((__le32 *)entry->skb->data, txdesc); | ||
406 | |||
407 | /* | ||
408 | * Dump beacon to userspace through debugfs. | ||
409 | */ | ||
410 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); | ||
411 | |||
412 | /* | ||
413 | * Write entire beacon with TXWI to register. | ||
414 | */ | ||
415 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
416 | rt2800_register_multiwrite(rt2x00dev, beacon_base, | ||
417 | entry->skb->data, entry->skb->len); | ||
418 | |||
419 | /* | ||
420 | * Enable beaconing again. | ||
421 | */ | ||
422 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
423 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
424 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
425 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
426 | |||
427 | /* | ||
428 | * Clean up beacon skb. | ||
429 | */ | ||
430 | dev_kfree_skb_any(entry->skb); | ||
431 | entry->skb = NULL; | ||
432 | } | ||
433 | EXPORT_SYMBOL(rt2800_write_beacon); | ||
434 | |||
383 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 435 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
384 | const struct rt2x00debug rt2800_rt2x00debug = { | 436 | const struct rt2x00debug rt2800_rt2x00debug = { |
385 | .owner = THIS_MODULE, | 437 | .owner = THIS_MODULE, |
@@ -502,15 +554,28 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | |||
502 | 554 | ||
503 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); | 555 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); |
504 | 556 | ||
505 | rt2800_register_read(rt2x00dev, offset, ®); | 557 | if (crypto->cmd == SET_KEY) { |
506 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, | 558 | rt2800_register_read(rt2x00dev, offset, ®); |
507 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | 559 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, |
508 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | 560 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); |
509 | (crypto->cmd == SET_KEY) * crypto->cipher); | 561 | /* |
510 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | 562 | * Both the cipher as the BSS Idx numbers are split in a main |
511 | (crypto->cmd == SET_KEY) * crypto->bssidx); | 563 | * value of 3 bits, and a extended field for adding one additional |
512 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | 564 | * bit to the value. |
513 | rt2800_register_write(rt2x00dev, offset, reg); | 565 | */ |
566 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | ||
567 | (crypto->cipher & 0x7)); | ||
568 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, | ||
569 | (crypto->cipher & 0x8) >> 3); | ||
570 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | ||
571 | (crypto->bssidx & 0x7)); | ||
572 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, | ||
573 | (crypto->bssidx & 0x8) >> 3); | ||
574 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | ||
575 | rt2800_register_write(rt2x00dev, offset, reg); | ||
576 | } else { | ||
577 | rt2800_register_write(rt2x00dev, offset, 0); | ||
578 | } | ||
514 | 579 | ||
515 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); | 580 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); |
516 | 581 | ||
@@ -1023,7 +1088,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |||
1023 | u8 r1; | 1088 | u8 r1; |
1024 | 1089 | ||
1025 | rt2800_bbp_read(rt2x00dev, 1, &r1); | 1090 | rt2800_bbp_read(rt2x00dev, 1, &r1); |
1026 | rt2x00_set_field8(®, BBP1_TX_POWER, 0); | 1091 | rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); |
1027 | rt2800_bbp_write(rt2x00dev, 1, r1); | 1092 | rt2800_bbp_write(rt2x00dev, 1, r1); |
1028 | 1093 | ||
1029 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | 1094 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); |
@@ -1212,6 +1277,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1212 | u32 reg; | 1277 | u32 reg; |
1213 | u16 eeprom; | 1278 | u16 eeprom; |
1214 | unsigned int i; | 1279 | unsigned int i; |
1280 | int ret; | ||
1215 | 1281 | ||
1216 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 1282 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); |
1217 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | 1283 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); |
@@ -1221,59 +1287,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1221 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | 1287 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); |
1222 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | 1288 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); |
1223 | 1289 | ||
1224 | if (rt2x00_is_usb(rt2x00dev)) { | 1290 | ret = rt2800_drv_init_registers(rt2x00dev); |
1225 | /* | 1291 | if (ret) |
1226 | * Wait until BBP and RF are ready. | 1292 | return ret; |
1227 | */ | ||
1228 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1229 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
1230 | if (reg && reg != ~0) | ||
1231 | break; | ||
1232 | msleep(1); | ||
1233 | } | ||
1234 | |||
1235 | if (i == REGISTER_BUSY_COUNT) { | ||
1236 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
1237 | return -EBUSY; | ||
1238 | } | ||
1239 | |||
1240 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
1241 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, | ||
1242 | reg & ~0x00002000); | ||
1243 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { | ||
1244 | /* | ||
1245 | * Reset DMA indexes | ||
1246 | */ | ||
1247 | rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
1248 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
1249 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
1250 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
1251 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
1252 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
1253 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
1254 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
1255 | rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
1256 | |||
1257 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
1258 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
1259 | |||
1260 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
1261 | } | ||
1262 | |||
1263 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
1264 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
1265 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
1266 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
1267 | |||
1268 | if (rt2x00_is_usb(rt2x00dev)) { | ||
1269 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); | ||
1270 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) | ||
1271 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | ||
1272 | USB_MODE_RESET, REGISTER_TIMEOUT); | ||
1273 | #endif | ||
1274 | } | ||
1275 | |||
1276 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
1277 | 1293 | ||
1278 | rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); | 1294 | rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); |
1279 | rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ | 1295 | rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ |
@@ -1328,7 +1344,6 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1328 | } else { | 1344 | } else { |
1329 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1345 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
1330 | } | 1346 | } |
1331 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, reg); | ||
1332 | } else if (rt2x00_rt(rt2x00dev, RT3070)) { | 1347 | } else if (rt2x00_rt(rt2x00dev, RT3070)) { |
1333 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 1348 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
1334 | 1349 | ||
@@ -1339,6 +1354,10 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1339 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 1354 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
1340 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1355 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
1341 | } | 1356 | } |
1357 | } else if (rt2800_is_305x_soc(rt2x00dev)) { | ||
1358 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | ||
1359 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | ||
1360 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); | ||
1342 | } else { | 1361 | } else { |
1343 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); | 1362 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); |
1344 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 1363 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
@@ -1560,9 +1579,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1560 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); | 1579 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); |
1561 | 1580 | ||
1562 | if (rt2x00_is_usb(rt2x00dev)) { | 1581 | if (rt2x00_is_usb(rt2x00dev)) { |
1563 | rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); | 1582 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); |
1564 | rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); | 1583 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30); |
1565 | rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); | 1584 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); |
1566 | } | 1585 | } |
1567 | 1586 | ||
1568 | rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); | 1587 | rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); |
@@ -1706,8 +1725,7 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1706 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 1725 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
1707 | rt2800_bbp_write(rt2x00dev, 83, 0x6a); | 1726 | rt2800_bbp_write(rt2x00dev, 83, 0x6a); |
1708 | 1727 | ||
1709 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D) || | 1728 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) |
1710 | rt2x00_rt_rev(rt2x00dev, RT2870, REV_RT2870D)) | ||
1711 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 1729 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
1712 | else | 1730 | else |
1713 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 1731 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
@@ -2013,8 +2031,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2013 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 2031 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
2014 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 2032 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
2015 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { | 2033 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { |
2016 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | 2034 | if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) |
2017 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) | ||
2018 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); | 2035 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); |
2019 | } | 2036 | } |
2020 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); | 2037 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); |
@@ -2147,7 +2164,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2147 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | 2164 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); |
2148 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); | 2165 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); |
2149 | } else if (rt2x00_rt(rt2x00dev, RT2860) || | 2166 | } else if (rt2x00_rt(rt2x00dev, RT2860) || |
2150 | rt2x00_rt(rt2x00dev, RT2870) || | ||
2151 | rt2x00_rt(rt2x00dev, RT2872)) { | 2167 | rt2x00_rt(rt2x00dev, RT2872)) { |
2152 | /* | 2168 | /* |
2153 | * There is a max of 2 RX streams for RT28x0 series | 2169 | * There is a max of 2 RX streams for RT28x0 series |
@@ -2251,7 +2267,6 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2251 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); | 2267 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); |
2252 | 2268 | ||
2253 | if (!rt2x00_rt(rt2x00dev, RT2860) && | 2269 | if (!rt2x00_rt(rt2x00dev, RT2860) && |
2254 | !rt2x00_rt(rt2x00dev, RT2870) && | ||
2255 | !rt2x00_rt(rt2x00dev, RT2872) && | 2270 | !rt2x00_rt(rt2x00dev, RT2872) && |
2256 | !rt2x00_rt(rt2x00dev, RT2883) && | 2271 | !rt2x00_rt(rt2x00dev, RT2883) && |
2257 | !rt2x00_rt(rt2x00dev, RT3070) && | 2272 | !rt2x00_rt(rt2x00dev, RT3070) && |
@@ -2491,6 +2506,18 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2491 | rt2x00_eeprom_addr(rt2x00dev, | 2506 | rt2x00_eeprom_addr(rt2x00dev, |
2492 | EEPROM_MAC_ADDR_0)); | 2507 | EEPROM_MAC_ADDR_0)); |
2493 | 2508 | ||
2509 | /* | ||
2510 | * As rt2800 has a global fallback table we cannot specify | ||
2511 | * more then one tx rate per frame but since the hw will | ||
2512 | * try several rates (based on the fallback table) we should | ||
2513 | * still initialize max_rates to the maximum number of rates | ||
2514 | * we are going to try. Otherwise mac80211 will truncate our | ||
2515 | * reported tx rates and the rc algortihm will end up with | ||
2516 | * incorrect data. | ||
2517 | */ | ||
2518 | rt2x00dev->hw->max_rates = 7; | ||
2519 | rt2x00dev->hw->max_rate_tries = 1; | ||
2520 | |||
2494 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); | 2521 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); |
2495 | 2522 | ||
2496 | /* | 2523 | /* |
@@ -2528,16 +2555,16 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2528 | else | 2555 | else |
2529 | spec->ht.ht_supported = false; | 2556 | spec->ht.ht_supported = false; |
2530 | 2557 | ||
2531 | /* | ||
2532 | * Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes | ||
2533 | * reception problems with HT40 capable 11n APs | ||
2534 | */ | ||
2535 | spec->ht.cap = | 2558 | spec->ht.cap = |
2559 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
2536 | IEEE80211_HT_CAP_GRN_FLD | | 2560 | IEEE80211_HT_CAP_GRN_FLD | |
2537 | IEEE80211_HT_CAP_SGI_20 | | 2561 | IEEE80211_HT_CAP_SGI_20 | |
2538 | IEEE80211_HT_CAP_SGI_40 | | 2562 | IEEE80211_HT_CAP_SGI_40 | |
2539 | IEEE80211_HT_CAP_TX_STBC | | ||
2540 | IEEE80211_HT_CAP_RX_STBC; | 2563 | IEEE80211_HT_CAP_RX_STBC; |
2564 | |||
2565 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) | ||
2566 | spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; | ||
2567 | |||
2541 | spec->ht.ampdu_factor = 3; | 2568 | spec->ht.ampdu_factor = 3; |
2542 | spec->ht.ampdu_density = 4; | 2569 | spec->ht.ampdu_density = 4; |
2543 | spec->ht.mcs.tx_params = | 2570 | spec->ht.mcs.tx_params = |
@@ -2743,3 +2770,8 @@ const struct ieee80211_ops rt2800_mac80211_ops = { | |||
2743 | .rfkill_poll = rt2x00mac_rfkill_poll, | 2770 | .rfkill_poll = rt2x00mac_rfkill_poll, |
2744 | }; | 2771 | }; |
2745 | EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); | 2772 | EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); |
2773 | |||
2774 | MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); | ||
2775 | MODULE_VERSION(DRV_VERSION); | ||
2776 | MODULE_DESCRIPTION("Ralink RT2800 library"); | ||
2777 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 94de999e2290..8313dbf441a5 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -40,6 +40,8 @@ struct rt2800_ops { | |||
40 | int (*regbusy_read)(struct rt2x00_dev *rt2x00dev, | 40 | int (*regbusy_read)(struct rt2x00_dev *rt2x00dev, |
41 | const unsigned int offset, | 41 | const unsigned int offset, |
42 | const struct rt2x00_field32 field, u32 *reg); | 42 | const struct rt2x00_field32 field, u32 *reg); |
43 | |||
44 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, | 47 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, |
@@ -107,13 +109,22 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
107 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); | 109 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); |
108 | } | 110 | } |
109 | 111 | ||
112 | static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) | ||
113 | { | ||
114 | const struct rt2800_ops *rt2800ops = rt2x00dev->priv; | ||
115 | |||
116 | return rt2800ops->drv_init_registers(rt2x00dev); | ||
117 | } | ||
118 | |||
110 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | 119 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, |
111 | const u8 command, const u8 token, | 120 | const u8 command, const u8 token, |
112 | const u8 arg0, const u8 arg1); | 121 | const u8 arg0, const u8 arg1); |
113 | 122 | ||
114 | void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc); | 123 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); |
115 | void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); | 124 | void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc); |
116 | 125 | ||
126 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | ||
127 | |||
117 | extern const struct rt2x00debug rt2800_rt2x00debug; | 128 | extern const struct rt2x00debug rt2800_rt2x00debug; |
118 | 129 | ||
119 | int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); | 130 | int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b2f23272c3aa..e5ea670a18db 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -51,7 +51,7 @@ | |||
51 | /* | 51 | /* |
52 | * Allow hardware encryption to be disabled. | 52 | * Allow hardware encryption to be disabled. |
53 | */ | 53 | */ |
54 | static int modparam_nohwcrypt = 1; | 54 | static int modparam_nohwcrypt = 0; |
55 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 55 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
56 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 56 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
57 | 57 | ||
@@ -446,6 +446,38 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
446 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | 446 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); |
447 | } | 447 | } |
448 | 448 | ||
449 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | ||
450 | { | ||
451 | u32 reg; | ||
452 | |||
453 | /* | ||
454 | * Reset DMA indexes | ||
455 | */ | ||
456 | rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
457 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
458 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
459 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
460 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
461 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
462 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
463 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
464 | rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
465 | |||
466 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
467 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
468 | |||
469 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
470 | |||
471 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
472 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
473 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
474 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
475 | |||
476 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
449 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 481 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
450 | { | 482 | { |
451 | u32 reg; | 483 | u32 reg; |
@@ -465,7 +497,7 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
465 | /* | 497 | /* |
466 | * Send signal to firmware during boot time. | 498 | * Send signal to firmware during boot time. |
467 | */ | 499 | */ |
468 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); | 500 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); |
469 | 501 | ||
470 | /* | 502 | /* |
471 | * Enable RX. | 503 | * Enable RX. |
@@ -613,18 +645,10 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
613 | /* | 645 | /* |
614 | * TX descriptor initialization | 646 | * TX descriptor initialization |
615 | */ | 647 | */ |
616 | static int rt2800pci_write_tx_data(struct queue_entry* entry, | 648 | static void rt2800pci_write_tx_datadesc(struct queue_entry* entry, |
617 | struct txentry_desc *txdesc) | 649 | struct txentry_desc *txdesc) |
618 | { | 650 | { |
619 | int ret; | 651 | rt2800_write_txwi((__le32 *) entry->skb->data, txdesc); |
620 | |||
621 | ret = rt2x00pci_write_tx_data(entry, txdesc); | ||
622 | if (ret) | ||
623 | return ret; | ||
624 | |||
625 | rt2800_write_txwi(entry->skb, txdesc); | ||
626 | |||
627 | return 0; | ||
628 | } | 652 | } |
629 | 653 | ||
630 | 654 | ||
@@ -684,49 +708,6 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
684 | /* | 708 | /* |
685 | * TX data initialization | 709 | * TX data initialization |
686 | */ | 710 | */ |
687 | static void rt2800pci_write_beacon(struct queue_entry *entry, | ||
688 | struct txentry_desc *txdesc) | ||
689 | { | ||
690 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
691 | unsigned int beacon_base; | ||
692 | u32 reg; | ||
693 | |||
694 | /* | ||
695 | * Disable beaconing while we are reloading the beacon data, | ||
696 | * otherwise we might be sending out invalid data. | ||
697 | */ | ||
698 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
699 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
700 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
701 | |||
702 | /* | ||
703 | * Add the TXWI for the beacon to the skb. | ||
704 | */ | ||
705 | rt2800_write_txwi(entry->skb, txdesc); | ||
706 | skb_push(entry->skb, TXWI_DESC_SIZE); | ||
707 | |||
708 | /* | ||
709 | * Write entire beacon with TXWI to register. | ||
710 | */ | ||
711 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
712 | rt2800_register_multiwrite(rt2x00dev, beacon_base, | ||
713 | entry->skb->data, entry->skb->len); | ||
714 | |||
715 | /* | ||
716 | * Enable beaconing again. | ||
717 | */ | ||
718 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
719 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
720 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
721 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
722 | |||
723 | /* | ||
724 | * Clean up beacon skb. | ||
725 | */ | ||
726 | dev_kfree_skb_any(entry->skb); | ||
727 | entry->skb = NULL; | ||
728 | } | ||
729 | |||
730 | static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 711 | static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
731 | const enum data_queue_qid queue_idx) | 712 | const enum data_queue_qid queue_idx) |
732 | { | 713 | { |
@@ -832,29 +813,24 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
832 | struct txdone_entry_desc txdesc; | 813 | struct txdone_entry_desc txdesc; |
833 | u32 word; | 814 | u32 word; |
834 | u32 reg; | 815 | u32 reg; |
835 | u32 old_reg; | ||
836 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | 816 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; |
837 | u16 mcs, real_mcs; | 817 | u16 mcs, real_mcs; |
818 | int i; | ||
838 | 819 | ||
839 | /* | 820 | /* |
840 | * During each loop we will compare the freshly read | 821 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO |
841 | * TX_STA_FIFO register value with the value read from | 822 | * at most X times and also stop processing once the TX_STA_FIFO_VALID |
842 | * the previous loop. If the 2 values are equal then | 823 | * flag is not set anymore. |
843 | * we should stop processing because the chance it | 824 | * |
844 | * quite big that the device has been unplugged and | 825 | * The legacy drivers use X=TX_RING_SIZE but state in a comment |
845 | * we risk going into an endless loop. | 826 | * that the TX_STA_FIFO stack has a size of 16. We stick to our |
827 | * tx ring size for now. | ||
846 | */ | 828 | */ |
847 | old_reg = 0; | 829 | for (i = 0; i < TX_ENTRIES; i++) { |
848 | |||
849 | while (1) { | ||
850 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | 830 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); |
851 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | 831 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) |
852 | break; | 832 | break; |
853 | 833 | ||
854 | if (old_reg == reg) | ||
855 | break; | ||
856 | old_reg = reg; | ||
857 | |||
858 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | 834 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); |
859 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | 835 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); |
860 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | 836 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); |
@@ -880,8 +856,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
880 | 856 | ||
881 | /* Check if we got a match by looking at WCID/ACK/PID | 857 | /* Check if we got a match by looking at WCID/ACK/PID |
882 | * fields */ | 858 | * fields */ |
883 | txwi = (__le32 *)(entry->skb->data - | 859 | txwi = (__le32 *) entry->skb->data; |
884 | rt2x00dev->ops->extra_tx_headroom); | ||
885 | 860 | ||
886 | rt2x00_desc_read(txwi, 1, &word); | 861 | rt2x00_desc_read(txwi, 1, &word); |
887 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | 862 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); |
@@ -923,10 +898,14 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
923 | txdesc.retry = 7; | 898 | txdesc.retry = 7; |
924 | } | 899 | } |
925 | 900 | ||
926 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | 901 | /* |
927 | 902 | * the frame was retried at least once | |
903 | * -> hw used fallback rates | ||
904 | */ | ||
905 | if (txdesc.retry) | ||
906 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
928 | 907 | ||
929 | rt2x00lib_txdone(entry, &txdesc); | 908 | rt2x00pci_txdone(entry, &txdesc); |
930 | } | 909 | } |
931 | } | 910 | } |
932 | 911 | ||
@@ -996,6 +975,8 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
996 | .register_multiwrite = rt2x00pci_register_multiwrite, | 975 | .register_multiwrite = rt2x00pci_register_multiwrite, |
997 | 976 | ||
998 | .regbusy_read = rt2x00pci_regbusy_read, | 977 | .regbusy_read = rt2x00pci_regbusy_read, |
978 | |||
979 | .drv_init_registers = rt2800pci_init_registers, | ||
999 | }; | 980 | }; |
1000 | 981 | ||
1001 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | 982 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) |
@@ -1063,8 +1044,9 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1063 | .reset_tuner = rt2800_reset_tuner, | 1044 | .reset_tuner = rt2800_reset_tuner, |
1064 | .link_tuner = rt2800_link_tuner, | 1045 | .link_tuner = rt2800_link_tuner, |
1065 | .write_tx_desc = rt2800pci_write_tx_desc, | 1046 | .write_tx_desc = rt2800pci_write_tx_desc, |
1066 | .write_tx_data = rt2800pci_write_tx_data, | 1047 | .write_tx_data = rt2x00pci_write_tx_data, |
1067 | .write_beacon = rt2800pci_write_beacon, | 1048 | .write_tx_datadesc = rt2800pci_write_tx_datadesc, |
1049 | .write_beacon = rt2800_write_beacon, | ||
1068 | .kick_tx_queue = rt2800pci_kick_tx_queue, | 1050 | .kick_tx_queue = rt2800pci_kick_tx_queue, |
1069 | .kill_tx_queue = rt2800pci_kill_tx_queue, | 1051 | .kill_tx_queue = rt2800pci_kill_tx_queue, |
1070 | .fill_rxdone = rt2800pci_fill_rxdone, | 1052 | .fill_rxdone = rt2800pci_fill_rxdone, |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index afc8e7da27cb..5a8dda9b5b5a 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h | |||
@@ -35,25 +35,6 @@ | |||
35 | #define RT2800PCI_H | 35 | #define RT2800PCI_H |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * PCI registers. | ||
39 | */ | ||
40 | |||
41 | /* | ||
42 | * E2PROM_CSR: EEPROM control register. | ||
43 | * RELOAD: Write 1 to reload eeprom content. | ||
44 | * TYPE: 0: 93c46, 1:93c66. | ||
45 | * LOAD_STATUS: 1:loading, 0:done. | ||
46 | */ | ||
47 | #define E2PROM_CSR 0x0004 | ||
48 | #define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) | ||
49 | #define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) | ||
50 | #define E2PROM_CSR_DATA_IN FIELD32(0x00000004) | ||
51 | #define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) | ||
52 | #define E2PROM_CSR_TYPE FIELD32(0x00000030) | ||
53 | #define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) | ||
54 | #define E2PROM_CSR_RELOAD FIELD32(0x00000080) | ||
55 | |||
56 | /* | ||
57 | * Queue register offset macros | 38 | * Queue register offset macros |
58 | */ | 39 | */ |
59 | #define TX_QUEUE_REG_OFFSET 0x10 | 40 | #define TX_QUEUE_REG_OFFSET 0x10 |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0f8b84b7224c..f18c12a19cc9 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -45,7 +45,7 @@ | |||
45 | /* | 45 | /* |
46 | * Allow hardware encryption to be disabled. | 46 | * Allow hardware encryption to be disabled. |
47 | */ | 47 | */ |
48 | static int modparam_nohwcrypt = 1; | 48 | static int modparam_nohwcrypt = 0; |
49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
51 | 51 | ||
@@ -169,11 +169,8 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
169 | /* | 169 | /* |
170 | * Write firmware to device. | 170 | * Write firmware to device. |
171 | */ | 171 | */ |
172 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | 172 | rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
173 | USB_VENDOR_REQUEST_OUT, | 173 | data + offset, length); |
174 | FIRMWARE_IMAGE_BASE, | ||
175 | data + offset, length, | ||
176 | REGISTER_TIMEOUT32(length)); | ||
177 | 174 | ||
178 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 175 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
179 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); | 176 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); |
@@ -196,7 +193,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
196 | /* | 193 | /* |
197 | * Send signal to firmware during boot time. | 194 | * Send signal to firmware during boot time. |
198 | */ | 195 | */ |
199 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); | 196 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); |
200 | 197 | ||
201 | if (rt2x00_rt(rt2x00dev, RT3070) || | 198 | if (rt2x00_rt(rt2x00dev, RT3070) || |
202 | rt2x00_rt(rt2x00dev, RT3071) || | 199 | rt2x00_rt(rt2x00dev, RT3071) || |
@@ -246,6 +243,44 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
246 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 243 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
247 | } | 244 | } |
248 | 245 | ||
246 | static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) | ||
247 | { | ||
248 | u32 reg; | ||
249 | int i; | ||
250 | |||
251 | /* | ||
252 | * Wait until BBP and RF are ready. | ||
253 | */ | ||
254 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
255 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
256 | if (reg && reg != ~0) | ||
257 | break; | ||
258 | msleep(1); | ||
259 | } | ||
260 | |||
261 | if (i == REGISTER_BUSY_COUNT) { | ||
262 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
263 | return -EBUSY; | ||
264 | } | ||
265 | |||
266 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
267 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); | ||
268 | |||
269 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
270 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
271 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
272 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
273 | |||
274 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); | ||
275 | |||
276 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | ||
277 | USB_MODE_RESET, REGISTER_TIMEOUT); | ||
278 | |||
279 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
249 | static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) | 284 | static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) |
250 | { | 285 | { |
251 | u32 reg; | 286 | u32 reg; |
@@ -400,20 +435,21 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
400 | struct txentry_desc *txdesc) | 435 | struct txentry_desc *txdesc) |
401 | { | 436 | { |
402 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 437 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
403 | __le32 *txi = (__le32 *)(skb->data - TXWI_DESC_SIZE - TXINFO_DESC_SIZE); | 438 | __le32 *txi = (__le32 *) skb->data; |
439 | __le32 *txwi = (__le32 *) (skb->data + TXINFO_DESC_SIZE); | ||
404 | u32 word; | 440 | u32 word; |
405 | 441 | ||
406 | /* | 442 | /* |
407 | * Initialize TXWI descriptor | 443 | * Initialize TXWI descriptor |
408 | */ | 444 | */ |
409 | rt2800_write_txwi(skb, txdesc); | 445 | rt2800_write_txwi(txwi, txdesc); |
410 | 446 | ||
411 | /* | 447 | /* |
412 | * Initialize TXINFO descriptor | 448 | * Initialize TXINFO descriptor |
413 | */ | 449 | */ |
414 | rt2x00_desc_read(txi, 0, &word); | 450 | rt2x00_desc_read(txi, 0, &word); |
415 | rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, | 451 | rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, |
416 | skb->len + TXWI_DESC_SIZE); | 452 | skb->len - TXINFO_DESC_SIZE); |
417 | rt2x00_set_field32(&word, TXINFO_W0_WIV, | 453 | rt2x00_set_field32(&word, TXINFO_W0_WIV, |
418 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | 454 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); |
419 | rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); | 455 | rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); |
@@ -426,6 +462,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
426 | /* | 462 | /* |
427 | * Register descriptor details in skb frame descriptor. | 463 | * Register descriptor details in skb frame descriptor. |
428 | */ | 464 | */ |
465 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; | ||
429 | skbdesc->desc = txi; | 466 | skbdesc->desc = txi; |
430 | skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; | 467 | skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; |
431 | } | 468 | } |
@@ -433,51 +470,6 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
433 | /* | 470 | /* |
434 | * TX data initialization | 471 | * TX data initialization |
435 | */ | 472 | */ |
436 | static void rt2800usb_write_beacon(struct queue_entry *entry, | ||
437 | struct txentry_desc *txdesc) | ||
438 | { | ||
439 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
440 | unsigned int beacon_base; | ||
441 | u32 reg; | ||
442 | |||
443 | /* | ||
444 | * Disable beaconing while we are reloading the beacon data, | ||
445 | * otherwise we might be sending out invalid data. | ||
446 | */ | ||
447 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
448 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
449 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
450 | |||
451 | /* | ||
452 | * Add the TXWI for the beacon to the skb. | ||
453 | */ | ||
454 | rt2800_write_txwi(entry->skb, txdesc); | ||
455 | skb_push(entry->skb, TXWI_DESC_SIZE); | ||
456 | |||
457 | /* | ||
458 | * Write entire beacon with descriptor to register. | ||
459 | */ | ||
460 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
461 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | ||
462 | USB_VENDOR_REQUEST_OUT, beacon_base, | ||
463 | entry->skb->data, entry->skb->len, | ||
464 | REGISTER_TIMEOUT32(entry->skb->len)); | ||
465 | |||
466 | /* | ||
467 | * Enable beaconing again. | ||
468 | */ | ||
469 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
470 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
471 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
472 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
473 | |||
474 | /* | ||
475 | * Clean up the beacon skb. | ||
476 | */ | ||
477 | dev_kfree_skb(entry->skb); | ||
478 | entry->skb = NULL; | ||
479 | } | ||
480 | |||
481 | static int rt2800usb_get_tx_data_len(struct queue_entry *entry) | 473 | static int rt2800usb_get_tx_data_len(struct queue_entry *entry) |
482 | { | 474 | { |
483 | int length; | 475 | int length; |
@@ -595,6 +587,8 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { | |||
595 | .register_multiwrite = rt2x00usb_register_multiwrite, | 587 | .register_multiwrite = rt2x00usb_register_multiwrite, |
596 | 588 | ||
597 | .regbusy_read = rt2x00usb_regbusy_read, | 589 | .regbusy_read = rt2x00usb_regbusy_read, |
590 | |||
591 | .drv_init_registers = rt2800usb_init_registers, | ||
598 | }; | 592 | }; |
599 | 593 | ||
600 | static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | 594 | static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) |
@@ -659,7 +653,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
659 | .link_tuner = rt2800_link_tuner, | 653 | .link_tuner = rt2800_link_tuner, |
660 | .write_tx_desc = rt2800usb_write_tx_desc, | 654 | .write_tx_desc = rt2800usb_write_tx_desc, |
661 | .write_tx_data = rt2x00usb_write_tx_data, | 655 | .write_tx_data = rt2x00usb_write_tx_data, |
662 | .write_beacon = rt2800usb_write_beacon, | 656 | .write_beacon = rt2800_write_beacon, |
663 | .get_tx_data_len = rt2800usb_get_tx_data_len, | 657 | .get_tx_data_len = rt2800usb_get_tx_data_len, |
664 | .kick_tx_queue = rt2x00usb_kick_tx_queue, | 658 | .kick_tx_queue = rt2x00usb_kick_tx_queue, |
665 | .kill_tx_queue = rt2x00usb_kill_tx_queue, | 659 | .kill_tx_queue = rt2x00usb_kill_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 2bca6a71a7f5..0722badccf86 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h | |||
@@ -32,43 +32,6 @@ | |||
32 | #define RT2800USB_H | 32 | #define RT2800USB_H |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * USB registers. | ||
36 | */ | ||
37 | |||
38 | /* | ||
39 | * USB_DMA_CFG | ||
40 | * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. | ||
41 | * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. | ||
42 | * PHY_CLEAR: phy watch dog enable. | ||
43 | * TX_CLEAR: Clear USB DMA TX path. | ||
44 | * TXOP_HALT: Halt TXOP count down when TX buffer is full. | ||
45 | * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. | ||
46 | * RX_BULK_EN: Enable USB DMA Rx. | ||
47 | * TX_BULK_EN: Enable USB DMA Tx. | ||
48 | * EP_OUT_VALID: OUT endpoint data valid. | ||
49 | * RX_BUSY: USB DMA RX FSM busy. | ||
50 | * TX_BUSY: USB DMA TX FSM busy. | ||
51 | */ | ||
52 | #define USB_DMA_CFG 0x02a0 | ||
53 | #define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) | ||
54 | #define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) | ||
55 | #define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) | ||
56 | #define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) | ||
57 | #define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) | ||
58 | #define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) | ||
59 | #define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) | ||
60 | #define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) | ||
61 | #define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) | ||
62 | #define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) | ||
63 | #define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) | ||
64 | |||
65 | /* | ||
66 | * USB_CYC_CFG | ||
67 | */ | ||
68 | #define USB_CYC_CFG 0x02a4 | ||
69 | #define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) | ||
70 | |||
71 | /* | ||
72 | * 8051 firmware image. | 35 | * 8051 firmware image. |
73 | */ | 36 | */ |
74 | #define FIRMWARE_RT2870 "rt2870.bin" | 37 | #define FIRMWARE_RT2870 "rt2870.bin" |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6c1ff4c15c84..e7acc6abfd89 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <net/mac80211.h> | 39 | #include <net/mac80211.h> |
40 | 40 | ||
41 | #include "rt2x00debug.h" | 41 | #include "rt2x00debug.h" |
42 | #include "rt2x00dump.h" | ||
42 | #include "rt2x00leds.h" | 43 | #include "rt2x00leds.h" |
43 | #include "rt2x00reg.h" | 44 | #include "rt2x00reg.h" |
44 | #include "rt2x00queue.h" | 45 | #include "rt2x00queue.h" |
@@ -159,6 +160,7 @@ struct avg_val { | |||
159 | 160 | ||
160 | enum rt2x00_chip_intf { | 161 | enum rt2x00_chip_intf { |
161 | RT2X00_CHIP_INTF_PCI, | 162 | RT2X00_CHIP_INTF_PCI, |
163 | RT2X00_CHIP_INTF_PCIE, | ||
162 | RT2X00_CHIP_INTF_USB, | 164 | RT2X00_CHIP_INTF_USB, |
163 | RT2X00_CHIP_INTF_SOC, | 165 | RT2X00_CHIP_INTF_SOC, |
164 | }; | 166 | }; |
@@ -175,8 +177,7 @@ struct rt2x00_chip { | |||
175 | #define RT2570 0x2570 | 177 | #define RT2570 0x2570 |
176 | #define RT2661 0x2661 | 178 | #define RT2661 0x2661 |
177 | #define RT2573 0x2573 | 179 | #define RT2573 0x2573 |
178 | #define RT2860 0x2860 /* 2.4GHz PCI/CB */ | 180 | #define RT2860 0x2860 /* 2.4GHz */ |
179 | #define RT2870 0x2870 | ||
180 | #define RT2872 0x2872 /* WSOC */ | 181 | #define RT2872 0x2872 /* WSOC */ |
181 | #define RT2883 0x2883 /* WSOC */ | 182 | #define RT2883 0x2883 /* WSOC */ |
182 | #define RT3070 0x3070 | 183 | #define RT3070 0x3070 |
@@ -551,6 +552,8 @@ struct rt2x00lib_ops { | |||
551 | struct txentry_desc *txdesc); | 552 | struct txentry_desc *txdesc); |
552 | int (*write_tx_data) (struct queue_entry *entry, | 553 | int (*write_tx_data) (struct queue_entry *entry, |
553 | struct txentry_desc *txdesc); | 554 | struct txentry_desc *txdesc); |
555 | void (*write_tx_datadesc) (struct queue_entry *entry, | ||
556 | struct txentry_desc *txdesc); | ||
554 | void (*write_beacon) (struct queue_entry *entry, | 557 | void (*write_beacon) (struct queue_entry *entry, |
555 | struct txentry_desc *txdesc); | 558 | struct txentry_desc *txdesc); |
556 | int (*get_tx_data_len) (struct queue_entry *entry); | 559 | int (*get_tx_data_len) (struct queue_entry *entry); |
@@ -978,7 +981,13 @@ static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, | |||
978 | 981 | ||
979 | static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) | 982 | static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) |
980 | { | 983 | { |
981 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | 984 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI) || |
985 | rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); | ||
986 | } | ||
987 | |||
988 | static inline bool rt2x00_is_pcie(struct rt2x00_dev *rt2x00dev) | ||
989 | { | ||
990 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); | ||
982 | } | 991 | } |
983 | 992 | ||
984 | static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) | 993 | static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) |
@@ -999,6 +1008,13 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) | |||
999 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | 1008 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); |
1000 | 1009 | ||
1001 | /** | 1010 | /** |
1011 | * rt2x00queue_unmap_skb - Unmap a skb from DMA. | ||
1012 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
1013 | * @skb: The skb to unmap. | ||
1014 | */ | ||
1015 | void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | ||
1016 | |||
1017 | /** | ||
1002 | * rt2x00queue_get_queue - Convert queue index to queue pointer | 1018 | * rt2x00queue_get_queue - Convert queue index to queue pointer |
1003 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 1019 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
1004 | * @queue: rt2x00 queue index (see &enum data_queue_qid). | 1020 | * @queue: rt2x00 queue index (see &enum data_queue_qid). |
@@ -1015,6 +1031,26 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, | |||
1015 | enum queue_index index); | 1031 | enum queue_index index); |
1016 | 1032 | ||
1017 | /* | 1033 | /* |
1034 | * Debugfs handlers. | ||
1035 | */ | ||
1036 | /** | ||
1037 | * rt2x00debug_dump_frame - Dump a frame to userspace through debugfs. | ||
1038 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
1039 | * @type: The type of frame that is being dumped. | ||
1040 | * @skb: The skb containing the frame to be dumped. | ||
1041 | */ | ||
1042 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
1043 | void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | ||
1044 | enum rt2x00_dump_type type, struct sk_buff *skb); | ||
1045 | #else | ||
1046 | static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | ||
1047 | enum rt2x00_dump_type type, | ||
1048 | struct sk_buff *skb) | ||
1049 | { | ||
1050 | } | ||
1051 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
1052 | |||
1053 | /* | ||
1018 | * Interrupt context handlers. | 1054 | * Interrupt context handlers. |
1019 | */ | 1055 | */ |
1020 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | 1056 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 098315a271ca..8dbd634dae27 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -170,23 +170,27 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
170 | unsigned int ieee80211_flags) | 170 | unsigned int ieee80211_flags) |
171 | { | 171 | { |
172 | struct rt2x00lib_conf libconf; | 172 | struct rt2x00lib_conf libconf; |
173 | u16 hw_value; | ||
173 | 174 | ||
174 | memset(&libconf, 0, sizeof(libconf)); | 175 | memset(&libconf, 0, sizeof(libconf)); |
175 | 176 | ||
176 | libconf.conf = conf; | 177 | libconf.conf = conf; |
177 | 178 | ||
178 | if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { | 179 | if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { |
179 | if (conf_is_ht40(conf)) | 180 | if (conf_is_ht40(conf)) { |
180 | __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); | 181 | __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); |
181 | else | 182 | hw_value = rt2x00ht_center_channel(rt2x00dev, conf); |
183 | } else { | ||
182 | __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); | 184 | __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); |
185 | hw_value = conf->channel->hw_value; | ||
186 | } | ||
183 | 187 | ||
184 | memcpy(&libconf.rf, | 188 | memcpy(&libconf.rf, |
185 | &rt2x00dev->spec.channels[conf->channel->hw_value], | 189 | &rt2x00dev->spec.channels[hw_value], |
186 | sizeof(libconf.rf)); | 190 | sizeof(libconf.rf)); |
187 | 191 | ||
188 | memcpy(&libconf.channel, | 192 | memcpy(&libconf.channel, |
189 | &rt2x00dev->spec.channels_info[conf->channel->hw_value], | 193 | &rt2x00dev->spec.channels_info[hw_value], |
190 | sizeof(libconf.channel)); | 194 | sizeof(libconf.channel)); |
191 | } | 195 | } |
192 | 196 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index e9fe93fd8042..b0498e7e7aae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
@@ -211,6 +211,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | |||
211 | if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) | 211 | if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) |
212 | skb_queue_purge(&intf->frame_dump_skbqueue); | 212 | skb_queue_purge(&intf->frame_dump_skbqueue); |
213 | } | 213 | } |
214 | EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame); | ||
214 | 215 | ||
215 | static int rt2x00debug_file_open(struct inode *inode, struct file *file) | 216 | static int rt2x00debug_file_open(struct inode *inode, struct file *file) |
216 | { | 217 | { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 3ae468c4d760..339cc84bf4fb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -211,11 +211,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
211 | bool success; | 211 | bool success; |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * Unmap the skb. | ||
215 | */ | ||
216 | rt2x00queue_unmap_skb(rt2x00dev, entry->skb); | ||
217 | |||
218 | /* | ||
219 | * Remove L2 padding which was added during | 214 | * Remove L2 padding which was added during |
220 | */ | 215 | */ |
221 | if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) | 216 | if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) |
@@ -224,7 +219,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
224 | /* | 219 | /* |
225 | * If the IV/EIV data was stripped from the frame before it was | 220 | * If the IV/EIV data was stripped from the frame before it was |
226 | * passed to the hardware, we should now reinsert it again because | 221 | * passed to the hardware, we should now reinsert it again because |
227 | * mac80211 will expect the the same data to be present it the | 222 | * mac80211 will expect the same data to be present it the |
228 | * frame as it was passed to us. | 223 | * frame as it was passed to us. |
229 | */ | 224 | */ |
230 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) | 225 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) |
@@ -241,8 +236,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
241 | */ | 236 | */ |
242 | success = | 237 | success = |
243 | test_bit(TXDONE_SUCCESS, &txdesc->flags) || | 238 | test_bit(TXDONE_SUCCESS, &txdesc->flags) || |
244 | test_bit(TXDONE_UNKNOWN, &txdesc->flags) || | 239 | test_bit(TXDONE_UNKNOWN, &txdesc->flags); |
245 | test_bit(TXDONE_FALLBACK, &txdesc->flags); | ||
246 | 240 | ||
247 | /* | 241 | /* |
248 | * Update TX statistics. | 242 | * Update TX statistics. |
@@ -264,11 +258,22 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
264 | /* | 258 | /* |
265 | * Frame was send with retries, hardware tried | 259 | * Frame was send with retries, hardware tried |
266 | * different rates to send out the frame, at each | 260 | * different rates to send out the frame, at each |
267 | * retry it lowered the rate 1 step. | 261 | * retry it lowered the rate 1 step except when the |
262 | * lowest rate was used. | ||
268 | */ | 263 | */ |
269 | for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { | 264 | for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { |
270 | tx_info->status.rates[i].idx = rate_idx - i; | 265 | tx_info->status.rates[i].idx = rate_idx - i; |
271 | tx_info->status.rates[i].flags = rate_flags; | 266 | tx_info->status.rates[i].flags = rate_flags; |
267 | |||
268 | if (rate_idx - i == 0) { | ||
269 | /* | ||
270 | * The lowest rate (index 0) was used until the | ||
271 | * number of max retries was reached. | ||
272 | */ | ||
273 | tx_info->status.rates[i].count = retry_rates - i; | ||
274 | i++; | ||
275 | break; | ||
276 | } | ||
272 | tx_info->status.rates[i].count = 1; | 277 | tx_info->status.rates[i].count = 1; |
273 | } | 278 | } |
274 | if (i < (IEEE80211_TX_MAX_RATES - 1)) | 279 | if (i < (IEEE80211_TX_MAX_RATES - 1)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index ed303b423e41..6df2e0b746b8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h | |||
@@ -20,7 +20,12 @@ | |||
20 | 20 | ||
21 | /* | 21 | /* |
22 | Module: rt2x00dump | 22 | Module: rt2x00dump |
23 | Abstract: Data structures for the rt2x00debug & userspace. | 23 | Abstract: |
24 | Data structures for the rt2x00debug & userspace. | ||
25 | |||
26 | The declarations in this file can be used by both rt2x00 | ||
27 | and userspace and therefore should be kept together in | ||
28 | this file. | ||
24 | */ | 29 | */ |
25 | 30 | ||
26 | #ifndef RT2X00DUMP_H | 31 | #ifndef RT2X00DUMP_H |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index 5a407602ce3e..c004cd3a8847 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c | |||
@@ -44,11 +44,22 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
44 | txdesc->mpdu_density = 0; | 44 | txdesc->mpdu_density = 0; |
45 | 45 | ||
46 | txdesc->ba_size = 7; /* FIXME: What value is needed? */ | 46 | txdesc->ba_size = 7; /* FIXME: What value is needed? */ |
47 | txdesc->stbc = 0; /* FIXME: What value is needed? */ | ||
48 | 47 | ||
49 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | 48 | txdesc->stbc = |
50 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 49 | (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT; |
51 | txdesc->mcs |= 0x08; | 50 | |
51 | /* | ||
52 | * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the | ||
53 | * mcs rate to be used | ||
54 | */ | ||
55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | ||
56 | txdesc->mcs = txrate->idx; | ||
57 | } else { | ||
58 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | ||
59 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
60 | txdesc->mcs |= 0x08; | ||
61 | } | ||
62 | |||
52 | 63 | ||
53 | /* | 64 | /* |
54 | * Convert flags | 65 | * Convert flags |
@@ -84,3 +95,31 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
84 | else | 95 | else |
85 | txdesc->txop = TXOP_HTTXOP; | 96 | txdesc->txop = TXOP_HTTXOP; |
86 | } | 97 | } |
98 | |||
99 | u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, | ||
100 | struct ieee80211_conf *conf) | ||
101 | { | ||
102 | struct hw_mode_spec *spec = &rt2x00dev->spec; | ||
103 | int center_channel; | ||
104 | u16 i; | ||
105 | |||
106 | /* | ||
107 | * Initialize center channel to current channel. | ||
108 | */ | ||
109 | center_channel = spec->channels[conf->channel->hw_value].channel; | ||
110 | |||
111 | /* | ||
112 | * Adjust center channel to HT40+ and HT40- operation. | ||
113 | */ | ||
114 | if (conf_is_ht40_plus(conf)) | ||
115 | center_channel += 2; | ||
116 | else if (conf_is_ht40_minus(conf)) | ||
117 | center_channel -= (center_channel == 14) ? 1 : 2; | ||
118 | |||
119 | for (i = 0; i < spec->num_channels; i++) | ||
120 | if (spec->channels[i].channel == center_channel) | ||
121 | return i; | ||
122 | |||
123 | WARN_ON(1); | ||
124 | return conf->channel->hw_value; | ||
125 | } | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index be2e37fb4071..ed27de1de57b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -27,8 +27,6 @@ | |||
27 | #ifndef RT2X00LIB_H | 27 | #ifndef RT2X00LIB_H |
28 | #define RT2X00LIB_H | 28 | #define RT2X00LIB_H |
29 | 29 | ||
30 | #include "rt2x00dump.h" | ||
31 | |||
32 | /* | 30 | /* |
33 | * Interval defines | 31 | * Interval defines |
34 | */ | 32 | */ |
@@ -107,13 +105,6 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, | |||
107 | struct queue_entry *entry); | 105 | struct queue_entry *entry); |
108 | 106 | ||
109 | /** | 107 | /** |
110 | * rt2x00queue_unmap_skb - Unmap a skb from DMA. | ||
111 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
112 | * @skb: The skb to unmap. | ||
113 | */ | ||
114 | void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | ||
115 | |||
116 | /** | ||
117 | * rt2x00queue_free_skb - free a skb | 108 | * rt2x00queue_free_skb - free a skb |
118 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 109 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
119 | * @skb: The skb to free. | 110 | * @skb: The skb to free. |
@@ -296,8 +287,6 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) | |||
296 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 287 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
297 | void rt2x00debug_register(struct rt2x00_dev *rt2x00dev); | 288 | void rt2x00debug_register(struct rt2x00_dev *rt2x00dev); |
298 | void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); | 289 | void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); |
299 | void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | ||
300 | enum rt2x00_dump_type type, struct sk_buff *skb); | ||
301 | void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, | 290 | void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, |
302 | struct rxdone_entry_desc *rxdesc); | 291 | struct rxdone_entry_desc *rxdesc); |
303 | #else | 292 | #else |
@@ -309,12 +298,6 @@ static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) | |||
309 | { | 298 | { |
310 | } | 299 | } |
311 | 300 | ||
312 | static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | ||
313 | enum rt2x00_dump_type type, | ||
314 | struct sk_buff *skb) | ||
315 | { | ||
316 | } | ||
317 | |||
318 | static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, | 301 | static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, |
319 | struct rxdone_entry_desc *rxdesc) | 302 | struct rxdone_entry_desc *rxdesc) |
320 | { | 303 | { |
@@ -384,12 +367,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, | |||
384 | void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | 367 | void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, |
385 | struct txentry_desc *txdesc, | 368 | struct txentry_desc *txdesc, |
386 | const struct rt2x00_rate *hwrate); | 369 | const struct rt2x00_rate *hwrate); |
370 | |||
371 | u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, | ||
372 | struct ieee80211_conf *conf); | ||
387 | #else | 373 | #else |
388 | static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | 374 | static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, |
389 | struct txentry_desc *txdesc, | 375 | struct txentry_desc *txdesc, |
390 | const struct rt2x00_rate *hwrate) | 376 | const struct rt2x00_rate *hwrate) |
391 | { | 377 | { |
392 | } | 378 | } |
379 | |||
380 | static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, | ||
381 | struct ieee80211_conf *conf) | ||
382 | { | ||
383 | return conf->channel->hw_value; | ||
384 | } | ||
393 | #endif /* CONFIG_RT2X00_LIB_HT */ | 385 | #endif /* CONFIG_RT2X00_LIB_HT */ |
394 | 386 | ||
395 | /* | 387 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index f71eee67f977..10eaffd12b1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -81,6 +81,24 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry, | |||
81 | return -EINVAL; | 81 | return -EINVAL; |
82 | } | 82 | } |
83 | 83 | ||
84 | /* | ||
85 | * Add the requested extra tx headroom in front of the skb. | ||
86 | */ | ||
87 | skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom); | ||
88 | memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom); | ||
89 | |||
90 | /* | ||
91 | * Call the driver's write_tx_datadesc function, if it exists. | ||
92 | */ | ||
93 | if (rt2x00dev->ops->lib->write_tx_datadesc) | ||
94 | rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc); | ||
95 | |||
96 | /* | ||
97 | * Map the skb to DMA. | ||
98 | */ | ||
99 | if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) | ||
100 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); | ||
101 | |||
84 | return 0; | 102 | return 0; |
85 | } | 103 | } |
86 | EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); | 104 | EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); |
@@ -88,6 +106,34 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); | |||
88 | /* | 106 | /* |
89 | * TX/RX data handlers. | 107 | * TX/RX data handlers. |
90 | */ | 108 | */ |
109 | void rt2x00pci_txdone(struct queue_entry *entry, | ||
110 | struct txdone_entry_desc *txdesc) | ||
111 | { | ||
112 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
113 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
114 | |||
115 | /* | ||
116 | * Unmap the skb. | ||
117 | */ | ||
118 | rt2x00queue_unmap_skb(rt2x00dev, entry->skb); | ||
119 | |||
120 | /* | ||
121 | * Remove the extra tx headroom from the skb. | ||
122 | */ | ||
123 | skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom); | ||
124 | |||
125 | /* | ||
126 | * Signal that the TX descriptor is no longer in the skb. | ||
127 | */ | ||
128 | skbdesc->flags &= ~SKBDESC_DESC_IN_SKB; | ||
129 | |||
130 | /* | ||
131 | * Pass on to rt2x00lib. | ||
132 | */ | ||
133 | rt2x00lib_txdone(entry, txdesc); | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(rt2x00pci_txdone); | ||
136 | |||
91 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | 137 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) |
92 | { | 138 | { |
93 | struct data_queue *queue = rt2x00dev->rx; | 139 | struct data_queue *queue = rt2x00dev->rx; |
@@ -305,7 +351,10 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
305 | rt2x00dev->irq = pci_dev->irq; | 351 | rt2x00dev->irq = pci_dev->irq; |
306 | rt2x00dev->name = pci_name(pci_dev); | 352 | rt2x00dev->name = pci_name(pci_dev); |
307 | 353 | ||
308 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | 354 | if (pci_dev->is_pcie) |
355 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); | ||
356 | else | ||
357 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | ||
309 | 358 | ||
310 | retval = rt2x00pci_alloc_reg(rt2x00dev); | 359 | retval = rt2x00pci_alloc_reg(rt2x00dev); |
311 | if (retval) | 360 | if (retval) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 51bcef3839ce..00528b8a754d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -109,6 +109,14 @@ struct queue_entry_priv_pci { | |||
109 | }; | 109 | }; |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * rt2x00pci_txdone - Handle TX done events. | ||
113 | * @entry: The queue entry for which a TX done event was received. | ||
114 | * @txdesc: The TX done descriptor for the entry. | ||
115 | */ | ||
116 | void rt2x00pci_txdone(struct queue_entry *entry, | ||
117 | struct txdone_entry_desc *txdesc); | ||
118 | |||
119 | /** | ||
112 | * rt2x00pci_rxdone - Handle RX done events | 120 | * rt2x00pci_rxdone - Handle RX done events |
113 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | 121 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. |
114 | */ | 122 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 20dbdd6fb904..f91637147116 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -100,21 +100,8 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | |||
100 | { | 100 | { |
101 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 101 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
102 | 102 | ||
103 | /* | ||
104 | * If device has requested headroom, we should make sure that | ||
105 | * is also mapped to the DMA so it can be used for transfering | ||
106 | * additional descriptor information to the hardware. | ||
107 | */ | ||
108 | skb_push(skb, rt2x00dev->ops->extra_tx_headroom); | ||
109 | |||
110 | skbdesc->skb_dma = | 103 | skbdesc->skb_dma = |
111 | dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); | 104 | dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); |
112 | |||
113 | /* | ||
114 | * Restore data pointer to original location again. | ||
115 | */ | ||
116 | skb_pull(skb, rt2x00dev->ops->extra_tx_headroom); | ||
117 | |||
118 | skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; | 105 | skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; |
119 | } | 106 | } |
120 | EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); | 107 | EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); |
@@ -130,16 +117,12 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | |||
130 | } | 117 | } |
131 | 118 | ||
132 | if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { | 119 | if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { |
133 | /* | 120 | dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, |
134 | * Add headroom to the skb length, it has been removed | ||
135 | * by the driver, but it was actually mapped to DMA. | ||
136 | */ | ||
137 | dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, | ||
138 | skb->len + rt2x00dev->ops->extra_tx_headroom, | ||
139 | DMA_TO_DEVICE); | 121 | DMA_TO_DEVICE); |
140 | skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; | 122 | skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; |
141 | } | 123 | } |
142 | } | 124 | } |
125 | EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb); | ||
143 | 126 | ||
144 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | 127 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) |
145 | { | 128 | { |
@@ -370,13 +353,18 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
370 | /* | 353 | /* |
371 | * Check if more fragments are pending | 354 | * Check if more fragments are pending |
372 | */ | 355 | */ |
373 | if (ieee80211_has_morefrags(hdr->frame_control) || | 356 | if (ieee80211_has_morefrags(hdr->frame_control)) { |
374 | (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) { | ||
375 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | 357 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); |
376 | __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); | 358 | __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); |
377 | } | 359 | } |
378 | 360 | ||
379 | /* | 361 | /* |
362 | * Check if more frames (!= fragments) are pending | ||
363 | */ | ||
364 | if (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES) | ||
365 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | ||
366 | |||
367 | /* | ||
380 | * Beacons and probe responses require the tsf timestamp | 368 | * Beacons and probe responses require the tsf timestamp |
381 | * to be inserted into the frame, except for a frame that has been injected | 369 | * to be inserted into the frame, except for a frame that has been injected |
382 | * through a monitor interface. This latter is needed for testing a | 370 | * through a monitor interface. This latter is needed for testing a |
@@ -421,7 +409,6 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | |||
421 | { | 409 | { |
422 | struct data_queue *queue = entry->queue; | 410 | struct data_queue *queue = entry->queue; |
423 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | 411 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; |
424 | enum rt2x00_dump_type dump_type; | ||
425 | 412 | ||
426 | rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); | 413 | rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); |
427 | 414 | ||
@@ -429,9 +416,7 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | |||
429 | * All processing on the frame has been completed, this means | 416 | * All processing on the frame has been completed, this means |
430 | * it is now ready to be dumped to userspace through debugfs. | 417 | * it is now ready to be dumped to userspace through debugfs. |
431 | */ | 418 | */ |
432 | dump_type = (txdesc->queue == QID_BEACON) ? | 419 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); |
433 | DUMP_FRAME_BEACON : DUMP_FRAME_TX; | ||
434 | rt2x00debug_dump_frame(rt2x00dev, dump_type, entry->skb); | ||
435 | } | 420 | } |
436 | 421 | ||
437 | static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, | 422 | static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, |
@@ -537,9 +522,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | |||
537 | return -EIO; | 522 | return -EIO; |
538 | } | 523 | } |
539 | 524 | ||
540 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) | ||
541 | rt2x00queue_map_txskb(queue->rt2x00dev, skb); | ||
542 | |||
543 | set_bit(ENTRY_DATA_PENDING, &entry->flags); | 525 | set_bit(ENTRY_DATA_PENDING, &entry->flags); |
544 | 526 | ||
545 | rt2x00queue_index_inc(queue, Q_INDEX); | 527 | rt2x00queue_index_inc(queue, Q_INDEX); |
@@ -595,11 +577,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
595 | skbdesc->entry = intf->beacon; | 577 | skbdesc->entry = intf->beacon; |
596 | 578 | ||
597 | /* | 579 | /* |
598 | * Write TX descriptor into reserved room in front of the beacon. | ||
599 | */ | ||
600 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
601 | |||
602 | /* | ||
603 | * Send beacon to hardware and enable beacon genaration.. | 580 | * Send beacon to hardware and enable beacon genaration.. |
604 | */ | 581 | */ |
605 | rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); | 582 | rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index f79170849add..bd54f55a8cb9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -213,9 +213,16 @@ struct rxdone_entry_desc { | |||
213 | /** | 213 | /** |
214 | * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc | 214 | * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc |
215 | * | 215 | * |
216 | * Every txdone report has to contain the basic result of the | ||
217 | * transmission, either &TXDONE_UNKNOWN, &TXDONE_SUCCESS or | ||
218 | * &TXDONE_FAILURE. The flag &TXDONE_FALLBACK can be used in | ||
219 | * conjunction with all of these flags but should only be set | ||
220 | * if retires > 0. The flag &TXDONE_EXCESSIVE_RETRY can only be used | ||
221 | * in conjunction with &TXDONE_FAILURE. | ||
222 | * | ||
216 | * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. | 223 | * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. |
217 | * @TXDONE_SUCCESS: Frame was successfully send | 224 | * @TXDONE_SUCCESS: Frame was successfully send |
218 | * @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. | 225 | * @TXDONE_FALLBACK: Hardware used fallback rates for retries |
219 | * @TXDONE_FAILURE: Frame was not successfully send | 226 | * @TXDONE_FAILURE: Frame was not successfully send |
220 | * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the | 227 | * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the |
221 | * frame transmission failed due to excessive retries. | 228 | * frame transmission failed due to excessive retries. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index bd1546ba7ad2..b45bc24c3dae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -113,26 +113,6 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | |||
113 | const u16 offset, void *buffer, | 113 | const u16 offset, void *buffer, |
114 | const u16 buffer_length, const int timeout) | 114 | const u16 buffer_length, const int timeout) |
115 | { | 115 | { |
116 | int status; | ||
117 | |||
118 | mutex_lock(&rt2x00dev->csr_mutex); | ||
119 | |||
120 | status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, | ||
121 | requesttype, offset, buffer, | ||
122 | buffer_length, timeout); | ||
123 | |||
124 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
125 | |||
126 | return status; | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); | ||
129 | |||
130 | int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, | ||
131 | const u8 request, const u8 requesttype, | ||
132 | const u16 offset, const void *buffer, | ||
133 | const u16 buffer_length, | ||
134 | const int timeout) | ||
135 | { | ||
136 | int status = 0; | 116 | int status = 0; |
137 | unsigned char *tb; | 117 | unsigned char *tb; |
138 | u16 off, len, bsize; | 118 | u16 off, len, bsize; |
@@ -157,7 +137,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, | |||
157 | 137 | ||
158 | return status; | 138 | return status; |
159 | } | 139 | } |
160 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); | 140 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); |
161 | 141 | ||
162 | int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, | 142 | int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, |
163 | const unsigned int offset, | 143 | const unsigned int offset, |
@@ -198,6 +178,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
198 | return; | 178 | return; |
199 | 179 | ||
200 | /* | 180 | /* |
181 | * Remove the descriptor from the front of the skb. | ||
182 | */ | ||
183 | skb_pull(entry->skb, entry->queue->desc_size); | ||
184 | |||
185 | /* | ||
201 | * Obtain the status about this packet. | 186 | * Obtain the status about this packet. |
202 | * Note that when the status is 0 it does not mean the | 187 | * Note that when the status is 0 it does not mean the |
203 | * frame was send out correctly. It only means the frame | 188 | * frame was send out correctly. It only means the frame |
@@ -243,10 +228,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry, | |||
243 | rt2x00usb_interrupt_txdone, entry); | 228 | rt2x00usb_interrupt_txdone, entry); |
244 | 229 | ||
245 | /* | 230 | /* |
246 | * Make sure the skb->data pointer points to the frame, not the | 231 | * Call the driver's write_tx_datadesc function, if it exists. |
247 | * descriptor. | ||
248 | */ | 232 | */ |
249 | skb_pull(entry->skb, entry->queue->desc_size); | 233 | if (rt2x00dev->ops->lib->write_tx_datadesc) |
234 | rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc); | ||
250 | 235 | ||
251 | return 0; | 236 | return 0; |
252 | } | 237 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 621d0f829251..255b81ef9530 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -167,25 +167,6 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, | |||
167 | const u16 buffer_length, const int timeout); | 167 | const u16 buffer_length, const int timeout); |
168 | 168 | ||
169 | /** | 169 | /** |
170 | * rt2x00usb_vendor_request_large_buff - Send register command to device (buffered) | ||
171 | * @rt2x00dev: Pointer to &struct rt2x00_dev | ||
172 | * @request: USB vendor command (See &enum rt2x00usb_vendor_request) | ||
173 | * @requesttype: Request type &USB_VENDOR_REQUEST_* | ||
174 | * @offset: Register start offset to perform action on | ||
175 | * @buffer: Buffer where information will be read/written to by device | ||
176 | * @buffer_length: Size of &buffer | ||
177 | * @timeout: Operation timeout | ||
178 | * | ||
179 | * This function is used to transfer register data in blocks larger | ||
180 | * then CSR_CACHE_SIZE. Use for firmware upload, keys and beacons. | ||
181 | */ | ||
182 | int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, | ||
183 | const u8 request, const u8 requesttype, | ||
184 | const u16 offset, const void *buffer, | ||
185 | const u16 buffer_length, | ||
186 | const int timeout); | ||
187 | |||
188 | /** | ||
189 | * rt2x00usb_vendor_request_sw - Send single register command to device | 170 | * rt2x00usb_vendor_request_sw - Send single register command to device |
190 | * @rt2x00dev: Pointer to &struct rt2x00_dev | 171 | * @rt2x00dev: Pointer to &struct rt2x00_dev |
191 | * @request: USB vendor command (See &enum rt2x00usb_vendor_request) | 172 | * @request: USB vendor command (See &enum rt2x00usb_vendor_request) |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6a74baf4e934..7ca383478eeb 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -931,6 +931,9 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
931 | u32 reg; | 931 | u32 reg; |
932 | 932 | ||
933 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); | 933 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); |
934 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); | ||
935 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); | ||
936 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); | ||
934 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, | 937 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, |
935 | libconf->conf->long_frame_max_tx_count); | 938 | libconf->conf->long_frame_max_tx_count); |
936 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, | 939 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, |
@@ -1874,6 +1877,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
1874 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1877 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
1875 | 1878 | ||
1876 | /* | 1879 | /* |
1880 | * Write the TX descriptor for the beacon. | ||
1881 | */ | ||
1882 | rt61pci_write_tx_desc(rt2x00dev, entry->skb, txdesc); | ||
1883 | |||
1884 | /* | ||
1885 | * Dump beacon to userspace through debugfs. | ||
1886 | */ | ||
1887 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); | ||
1888 | |||
1889 | /* | ||
1877 | * Write entire beacon with descriptor to register. | 1890 | * Write entire beacon with descriptor to register. |
1878 | */ | 1891 | */ |
1879 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | 1892 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); |
@@ -2039,29 +2052,24 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2039 | struct txdone_entry_desc txdesc; | 2052 | struct txdone_entry_desc txdesc; |
2040 | u32 word; | 2053 | u32 word; |
2041 | u32 reg; | 2054 | u32 reg; |
2042 | u32 old_reg; | ||
2043 | int type; | 2055 | int type; |
2044 | int index; | 2056 | int index; |
2057 | int i; | ||
2045 | 2058 | ||
2046 | /* | 2059 | /* |
2047 | * During each loop we will compare the freshly read | 2060 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO |
2048 | * STA_CSR4 register value with the value read from | 2061 | * at most X times and also stop processing once the TX_STA_FIFO_VALID |
2049 | * the previous loop. If the 2 values are equal then | 2062 | * flag is not set anymore. |
2050 | * we should stop processing because the chance is | 2063 | * |
2051 | * quite big that the device has been unplugged and | 2064 | * The legacy drivers use X=TX_RING_SIZE but state in a comment |
2052 | * we risk going into an endless loop. | 2065 | * that the TX_STA_FIFO stack has a size of 16. We stick to our |
2066 | * tx ring size for now. | ||
2053 | */ | 2067 | */ |
2054 | old_reg = 0; | 2068 | for (i = 0; i < TX_ENTRIES; i++) { |
2055 | |||
2056 | while (1) { | ||
2057 | rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); | 2069 | rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); |
2058 | if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) | 2070 | if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) |
2059 | break; | 2071 | break; |
2060 | 2072 | ||
2061 | if (old_reg == reg) | ||
2062 | break; | ||
2063 | old_reg = reg; | ||
2064 | |||
2065 | /* | 2073 | /* |
2066 | * Skip this entry when it contains an invalid | 2074 | * Skip this entry when it contains an invalid |
2067 | * queue identication number. | 2075 | * queue identication number. |
@@ -2100,7 +2108,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2100 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | 2108 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); |
2101 | txdesc.retry = 0; | 2109 | txdesc.retry = 0; |
2102 | 2110 | ||
2103 | rt2x00lib_txdone(entry_done, &txdesc); | 2111 | rt2x00pci_txdone(entry_done, &txdesc); |
2104 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 2112 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
2105 | } | 2113 | } |
2106 | 2114 | ||
@@ -2120,7 +2128,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2120 | } | 2128 | } |
2121 | txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); | 2129 | txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); |
2122 | 2130 | ||
2123 | rt2x00lib_txdone(entry, &txdesc); | 2131 | /* |
2132 | * the frame was retried at least once | ||
2133 | * -> hw used fallback rates | ||
2134 | */ | ||
2135 | if (txdesc.retry) | ||
2136 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
2137 | |||
2138 | rt2x00pci_txdone(entry, &txdesc); | ||
2124 | } | 2139 | } |
2125 | } | 2140 | } |
2126 | 2141 | ||
@@ -2577,6 +2592,18 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2577 | EEPROM_MAC_ADDR_0)); | 2592 | EEPROM_MAC_ADDR_0)); |
2578 | 2593 | ||
2579 | /* | 2594 | /* |
2595 | * As rt61 has a global fallback table we cannot specify | ||
2596 | * more then one tx rate per frame but since the hw will | ||
2597 | * try several rates (based on the fallback table) we should | ||
2598 | * still initialize max_rates to the maximum number of rates | ||
2599 | * we are going to try. Otherwise mac80211 will truncate our | ||
2600 | * reported tx rates and the rc algortihm will end up with | ||
2601 | * incorrect data. | ||
2602 | */ | ||
2603 | rt2x00dev->hw->max_rates = 7; | ||
2604 | rt2x00dev->hw->max_rate_tries = 1; | ||
2605 | |||
2606 | /* | ||
2580 | * Initialize hw_mode information. | 2607 | * Initialize hw_mode information. |
2581 | */ | 2608 | */ |
2582 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2609 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6e0d82efe924..d06d90f003e7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -270,7 +270,6 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
270 | { | 270 | { |
271 | struct hw_key_entry key_entry; | 271 | struct hw_key_entry key_entry; |
272 | struct rt2x00_field32 field; | 272 | struct rt2x00_field32 field; |
273 | int timeout; | ||
274 | u32 mask; | 273 | u32 mask; |
275 | u32 reg; | 274 | u32 reg; |
276 | 275 | ||
@@ -306,12 +305,8 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
306 | sizeof(key_entry.rx_mic)); | 305 | sizeof(key_entry.rx_mic)); |
307 | 306 | ||
308 | reg = SHARED_KEY_ENTRY(key->hw_key_idx); | 307 | reg = SHARED_KEY_ENTRY(key->hw_key_idx); |
309 | timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); | 308 | rt2x00usb_register_multiwrite(rt2x00dev, reg, |
310 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | 309 | &key_entry, sizeof(key_entry)); |
311 | USB_VENDOR_REQUEST_OUT, reg, | ||
312 | &key_entry, | ||
313 | sizeof(key_entry), | ||
314 | timeout); | ||
315 | 310 | ||
316 | /* | 311 | /* |
317 | * The cipher types are stored over 2 registers. | 312 | * The cipher types are stored over 2 registers. |
@@ -372,7 +367,6 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
372 | { | 367 | { |
373 | struct hw_pairwise_ta_entry addr_entry; | 368 | struct hw_pairwise_ta_entry addr_entry; |
374 | struct hw_key_entry key_entry; | 369 | struct hw_key_entry key_entry; |
375 | int timeout; | ||
376 | u32 mask; | 370 | u32 mask; |
377 | u32 reg; | 371 | u32 reg; |
378 | 372 | ||
@@ -407,17 +401,11 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
407 | sizeof(key_entry.rx_mic)); | 401 | sizeof(key_entry.rx_mic)); |
408 | 402 | ||
409 | reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | 403 | reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); |
410 | timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); | 404 | rt2x00usb_register_multiwrite(rt2x00dev, reg, |
411 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | 405 | &key_entry, sizeof(key_entry)); |
412 | USB_VENDOR_REQUEST_OUT, reg, | ||
413 | &key_entry, | ||
414 | sizeof(key_entry), | ||
415 | timeout); | ||
416 | 406 | ||
417 | /* | 407 | /* |
418 | * Send the address and cipher type to the hardware register. | 408 | * Send the address and cipher type to the hardware register. |
419 | * This data fits within the CSR cache size, so we can use | ||
420 | * rt2x00usb_register_multiwrite() directly. | ||
421 | */ | 409 | */ |
422 | memset(&addr_entry, 0, sizeof(addr_entry)); | 410 | memset(&addr_entry, 0, sizeof(addr_entry)); |
423 | memcpy(&addr_entry, crypto->address, ETH_ALEN); | 411 | memcpy(&addr_entry, crypto->address, ETH_ALEN); |
@@ -828,6 +816,9 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
828 | u32 reg; | 816 | u32 reg; |
829 | 817 | ||
830 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); | 818 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); |
819 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); | ||
820 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); | ||
821 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); | ||
831 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, | 822 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, |
832 | libconf->conf->long_frame_max_tx_count); | 823 | libconf->conf->long_frame_max_tx_count); |
833 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, | 824 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, |
@@ -1092,11 +1083,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
1092 | /* | 1083 | /* |
1093 | * Write firmware to device. | 1084 | * Write firmware to device. |
1094 | */ | 1085 | */ |
1095 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | 1086 | rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); |
1096 | USB_VENDOR_REQUEST_OUT, | ||
1097 | FIRMWARE_IMAGE_BASE, | ||
1098 | data, len, | ||
1099 | REGISTER_TIMEOUT32(len)); | ||
1100 | 1087 | ||
1101 | /* | 1088 | /* |
1102 | * Send firmware request to device to load firmware, | 1089 | * Send firmware request to device to load firmware, |
@@ -1442,7 +1429,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1442 | struct txentry_desc *txdesc) | 1429 | struct txentry_desc *txdesc) |
1443 | { | 1430 | { |
1444 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 1431 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
1445 | __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); | 1432 | __le32 *txd = (__le32 *) skb->data; |
1446 | u32 word; | 1433 | u32 word; |
1447 | 1434 | ||
1448 | /* | 1435 | /* |
@@ -1505,6 +1492,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1505 | /* | 1492 | /* |
1506 | * Register descriptor details in skb frame descriptor. | 1493 | * Register descriptor details in skb frame descriptor. |
1507 | */ | 1494 | */ |
1495 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; | ||
1508 | skbdesc->desc = txd; | 1496 | skbdesc->desc = txd; |
1509 | skbdesc->desc_len = TXD_DESC_SIZE; | 1497 | skbdesc->desc_len = TXD_DESC_SIZE; |
1510 | } | 1498 | } |
@@ -1528,18 +1516,27 @@ static void rt73usb_write_beacon(struct queue_entry *entry, | |||
1528 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 1516 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
1529 | 1517 | ||
1530 | /* | 1518 | /* |
1531 | * Take the descriptor in front of the skb into account. | 1519 | * Add space for the descriptor in front of the skb. |
1532 | */ | 1520 | */ |
1533 | skb_push(entry->skb, TXD_DESC_SIZE); | 1521 | skb_push(entry->skb, TXD_DESC_SIZE); |
1522 | memset(entry->skb->data, 0, TXD_DESC_SIZE); | ||
1523 | |||
1524 | /* | ||
1525 | * Write the TX descriptor for the beacon. | ||
1526 | */ | ||
1527 | rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc); | ||
1528 | |||
1529 | /* | ||
1530 | * Dump beacon to userspace through debugfs. | ||
1531 | */ | ||
1532 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); | ||
1534 | 1533 | ||
1535 | /* | 1534 | /* |
1536 | * Write entire beacon with descriptor to register. | 1535 | * Write entire beacon with descriptor to register. |
1537 | */ | 1536 | */ |
1538 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | 1537 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); |
1539 | rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, | 1538 | rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, |
1540 | USB_VENDOR_REQUEST_OUT, beacon_base, | 1539 | entry->skb->data, entry->skb->len); |
1541 | entry->skb->data, entry->skb->len, | ||
1542 | REGISTER_TIMEOUT32(entry->skb->len)); | ||
1543 | 1540 | ||
1544 | /* | 1541 | /* |
1545 | * Enable beaconing again. | 1542 | * Enable beaconing again. |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 515817de2905..42705028751d 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -671,7 +671,7 @@ static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) | |||
671 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | 671 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; |
672 | } | 672 | } |
673 | 673 | ||
674 | void rtl8180_beacon_work(struct work_struct *work) | 674 | static void rtl8180_beacon_work(struct work_struct *work) |
675 | { | 675 | { |
676 | struct rtl8180_vif *vif_priv = | 676 | struct rtl8180_vif *vif_priv = |
677 | container_of(work, struct rtl8180_vif, beacon_work.work); | 677 | container_of(work, struct rtl8180_vif, beacon_work.work); |
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 337fc7bec5a5..2f98058be451 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -41,7 +41,7 @@ config WL1251_SDIO | |||
41 | 41 | ||
42 | config WL1271 | 42 | config WL1271 |
43 | tristate "TI wl1271 support" | 43 | tristate "TI wl1271 support" |
44 | depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS | 44 | depends on WL12XX && GENERIC_HARDIRQS |
45 | depends on INET | 45 | depends on INET |
46 | select FW_LOADER | 46 | select FW_LOADER |
47 | select CRC7 | 47 | select CRC7 |
@@ -65,7 +65,7 @@ config WL1271_SPI | |||
65 | 65 | ||
66 | config WL1271_SDIO | 66 | config WL1271_SDIO |
67 | tristate "TI wl1271 SDIO support" | 67 | tristate "TI wl1271 SDIO support" |
68 | depends on WL1271 && MMC && ARM | 68 | depends on WL1271 && MMC |
69 | ---help--- | 69 | ---help--- |
70 | This module adds support for the SDIO interface of adapters using | 70 | This module adds support for the SDIO interface of adapters using |
71 | TI wl1271 chipset. Select this if your platform is using | 71 | TI wl1271 chipset. Select this if your platform is using |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 00b24282fc73..c8f268951e10 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -124,7 +124,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | wl->nvs_len = fw->size; | 126 | wl->nvs_len = fw->size; |
127 | wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); | 127 | wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL); |
128 | 128 | ||
129 | if (!wl->nvs) { | 129 | if (!wl->nvs) { |
130 | wl1251_error("could not allocate memory for the nvs file"); | 130 | wl1251_error("could not allocate memory for the nvs file"); |
@@ -132,8 +132,6 @@ static int wl1251_fetch_nvs(struct wl1251 *wl) | |||
132 | goto out; | 132 | goto out; |
133 | } | 133 | } |
134 | 134 | ||
135 | memcpy(wl->nvs, fw->data, wl->nvs_len); | ||
136 | |||
137 | ret = 0; | 135 | ret = 0; |
138 | 136 | ||
139 | out: | 137 | out: |
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index c561332e7009..b901b6135654 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c | |||
@@ -37,11 +37,17 @@ | |||
37 | #define SDIO_DEVICE_ID_TI_WL1251 0x9066 | 37 | #define SDIO_DEVICE_ID_TI_WL1251 0x9066 |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | struct wl1251_sdio { | ||
41 | struct sdio_func *func; | ||
42 | u32 elp_val; | ||
43 | }; | ||
44 | |||
40 | static struct wl12xx_platform_data *wl12xx_board_data; | 45 | static struct wl12xx_platform_data *wl12xx_board_data; |
41 | 46 | ||
42 | static struct sdio_func *wl_to_func(struct wl1251 *wl) | 47 | static struct sdio_func *wl_to_func(struct wl1251 *wl) |
43 | { | 48 | { |
44 | return wl->if_priv; | 49 | struct wl1251_sdio *wl_sdio = wl->if_priv; |
50 | return wl_sdio->func; | ||
45 | } | 51 | } |
46 | 52 | ||
47 | static void wl1251_sdio_interrupt(struct sdio_func *func) | 53 | static void wl1251_sdio_interrupt(struct sdio_func *func) |
@@ -90,10 +96,17 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr, | |||
90 | static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) | 96 | static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) |
91 | { | 97 | { |
92 | int ret = 0; | 98 | int ret = 0; |
93 | struct sdio_func *func = wl_to_func(wl); | 99 | struct wl1251_sdio *wl_sdio = wl->if_priv; |
94 | 100 | struct sdio_func *func = wl_sdio->func; | |
101 | |||
102 | /* | ||
103 | * The hardware only supports RAW (read after write) access for | ||
104 | * reading, regular sdio_readb won't work here (it interprets | ||
105 | * the unused bits of CMD52 as write data even if we send read | ||
106 | * request). | ||
107 | */ | ||
95 | sdio_claim_host(func); | 108 | sdio_claim_host(func); |
96 | *val = sdio_readb(func, addr, &ret); | 109 | *val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret); |
97 | sdio_release_host(func); | 110 | sdio_release_host(func); |
98 | 111 | ||
99 | if (ret) | 112 | if (ret) |
@@ -103,7 +116,8 @@ static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) | |||
103 | static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) | 116 | static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) |
104 | { | 117 | { |
105 | int ret = 0; | 118 | int ret = 0; |
106 | struct sdio_func *func = wl_to_func(wl); | 119 | struct wl1251_sdio *wl_sdio = wl->if_priv; |
120 | struct sdio_func *func = wl_sdio->func; | ||
107 | 121 | ||
108 | sdio_claim_host(func); | 122 | sdio_claim_host(func); |
109 | sdio_writeb(func, val, addr, &ret); | 123 | sdio_writeb(func, val, addr, &ret); |
@@ -111,6 +125,8 @@ static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) | |||
111 | 125 | ||
112 | if (ret) | 126 | if (ret) |
113 | wl1251_error("sdio_writeb failed (%d)", ret); | 127 | wl1251_error("sdio_writeb failed (%d)", ret); |
128 | else | ||
129 | wl_sdio->elp_val = val; | ||
114 | } | 130 | } |
115 | 131 | ||
116 | static void wl1251_sdio_reset(struct wl1251 *wl) | 132 | static void wl1251_sdio_reset(struct wl1251 *wl) |
@@ -197,6 +213,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, | |||
197 | int ret; | 213 | int ret; |
198 | struct wl1251 *wl; | 214 | struct wl1251 *wl; |
199 | struct ieee80211_hw *hw; | 215 | struct ieee80211_hw *hw; |
216 | struct wl1251_sdio *wl_sdio; | ||
200 | 217 | ||
201 | hw = wl1251_alloc_hw(); | 218 | hw = wl1251_alloc_hw(); |
202 | if (IS_ERR(hw)) | 219 | if (IS_ERR(hw)) |
@@ -204,6 +221,12 @@ static int wl1251_sdio_probe(struct sdio_func *func, | |||
204 | 221 | ||
205 | wl = hw->priv; | 222 | wl = hw->priv; |
206 | 223 | ||
224 | wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL); | ||
225 | if (wl_sdio == NULL) { | ||
226 | ret = -ENOMEM; | ||
227 | goto out_free_hw; | ||
228 | } | ||
229 | |||
207 | sdio_claim_host(func); | 230 | sdio_claim_host(func); |
208 | ret = sdio_enable_func(func); | 231 | ret = sdio_enable_func(func); |
209 | if (ret) | 232 | if (ret) |
@@ -213,7 +236,8 @@ static int wl1251_sdio_probe(struct sdio_func *func, | |||
213 | sdio_release_host(func); | 236 | sdio_release_host(func); |
214 | 237 | ||
215 | SET_IEEE80211_DEV(hw, &func->dev); | 238 | SET_IEEE80211_DEV(hw, &func->dev); |
216 | wl->if_priv = func; | 239 | wl_sdio->func = func; |
240 | wl->if_priv = wl_sdio; | ||
217 | wl->if_ops = &wl1251_sdio_ops; | 241 | wl->if_ops = &wl1251_sdio_ops; |
218 | wl->set_power = wl1251_sdio_set_power; | 242 | wl->set_power = wl1251_sdio_set_power; |
219 | 243 | ||
@@ -259,6 +283,8 @@ disable: | |||
259 | sdio_disable_func(func); | 283 | sdio_disable_func(func); |
260 | release: | 284 | release: |
261 | sdio_release_host(func); | 285 | sdio_release_host(func); |
286 | kfree(wl_sdio); | ||
287 | out_free_hw: | ||
262 | wl1251_free_hw(wl); | 288 | wl1251_free_hw(wl); |
263 | return ret; | 289 | return ret; |
264 | } | 290 | } |
@@ -266,9 +292,11 @@ release: | |||
266 | static void __devexit wl1251_sdio_remove(struct sdio_func *func) | 292 | static void __devexit wl1251_sdio_remove(struct sdio_func *func) |
267 | { | 293 | { |
268 | struct wl1251 *wl = sdio_get_drvdata(func); | 294 | struct wl1251 *wl = sdio_get_drvdata(func); |
295 | struct wl1251_sdio *wl_sdio = wl->if_priv; | ||
269 | 296 | ||
270 | if (wl->irq) | 297 | if (wl->irq) |
271 | free_irq(wl->irq, wl); | 298 | free_irq(wl->irq, wl); |
299 | kfree(wl_sdio); | ||
272 | wl1251_free_hw(wl); | 300 | wl1251_free_hw(wl); |
273 | 301 | ||
274 | sdio_claim_host(func); | 302 | sdio_claim_host(func); |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 6f1b6b5640c0..1b52ce6a84d7 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
34 | 34 | ||
35 | #include "wl1271_conf.h" | 35 | #include "wl1271_conf.h" |
36 | #include "wl1271_ini.h" | ||
36 | 37 | ||
37 | #define DRIVER_NAME "wl1271" | 38 | #define DRIVER_NAME "wl1271" |
38 | #define DRIVER_PREFIX DRIVER_NAME ": " | 39 | #define DRIVER_PREFIX DRIVER_NAME ": " |
@@ -116,33 +117,6 @@ enum { | |||
116 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | 117 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) |
117 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | 118 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) |
118 | 119 | ||
119 | /* NVS data structure */ | ||
120 | #define WL1271_NVS_SECTION_SIZE 468 | ||
121 | |||
122 | #define WL1271_NVS_GENERAL_PARAMS_SIZE 57 | ||
123 | #define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \ | ||
124 | (WL1271_NVS_GENERAL_PARAMS_SIZE + 1) | ||
125 | #define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17 | ||
126 | #define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \ | ||
127 | (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1) | ||
128 | #define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65 | ||
129 | #define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \ | ||
130 | (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1) | ||
131 | #define WL1271_NVS_FEM_COUNT 2 | ||
132 | #define WL1271_NVS_INI_SPARE_SIZE 124 | ||
133 | |||
134 | struct wl1271_nvs_file { | ||
135 | /* NVS section */ | ||
136 | u8 nvs[WL1271_NVS_SECTION_SIZE]; | ||
137 | |||
138 | /* INI section */ | ||
139 | u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED]; | ||
140 | u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED]; | ||
141 | u8 dyn_radio_params[WL1271_NVS_FEM_COUNT] | ||
142 | [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED]; | ||
143 | u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE]; | ||
144 | } __attribute__ ((packed)); | ||
145 | |||
146 | /* | 120 | /* |
147 | * Enable/disable 802.11a support for WL1273 | 121 | * Enable/disable 802.11a support for WL1273 |
148 | */ | 122 | */ |
@@ -325,6 +299,7 @@ struct wl1271_rx_mem_pool_addr { | |||
325 | }; | 299 | }; |
326 | 300 | ||
327 | struct wl1271_scan { | 301 | struct wl1271_scan { |
302 | struct cfg80211_scan_request *req; | ||
328 | u8 state; | 303 | u8 state; |
329 | u8 ssid[IW_ESSID_MAX_SIZE+1]; | 304 | u8 ssid[IW_ESSID_MAX_SIZE+1]; |
330 | size_t ssid_len; | 305 | size_t ssid_len; |
@@ -375,6 +350,7 @@ struct wl1271 { | |||
375 | #define WL1271_FLAG_IRQ_PENDING (9) | 350 | #define WL1271_FLAG_IRQ_PENDING (9) |
376 | #define WL1271_FLAG_IRQ_RUNNING (10) | 351 | #define WL1271_FLAG_IRQ_RUNNING (10) |
377 | #define WL1271_FLAG_IDLE (11) | 352 | #define WL1271_FLAG_IDLE (11) |
353 | #define WL1271_FLAG_IDLE_REQUESTED (12) | ||
378 | unsigned long flags; | 354 | unsigned long flags; |
379 | 355 | ||
380 | struct wl1271_partition_set part; | 356 | struct wl1271_partition_set part; |
@@ -421,6 +397,7 @@ struct wl1271 { | |||
421 | 397 | ||
422 | /* Pending TX frames */ | 398 | /* Pending TX frames */ |
423 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; | 399 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; |
400 | int tx_frames_cnt; | ||
424 | 401 | ||
425 | /* Security sequence number counters */ | 402 | /* Security sequence number counters */ |
426 | u8 tx_security_last_seq; | 403 | u8 tx_security_last_seq; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 19393e236e2c..530678e45a13 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -212,8 +212,8 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
212 | 212 | ||
213 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | 213 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; |
214 | 214 | ||
215 | memcpy(gen_parms->params, wl->nvs->general_params, | 215 | memcpy(&gen_parms->general_params, &wl->nvs->general_params, |
216 | WL1271_NVS_GENERAL_PARAMS_SIZE); | 216 | sizeof(struct wl1271_ini_general_params)); |
217 | 217 | ||
218 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 218 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
219 | if (ret < 0) | 219 | if (ret < 0) |
@@ -238,13 +238,20 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
238 | 238 | ||
239 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 239 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
240 | 240 | ||
241 | memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, | 241 | /* 2.4GHz parameters */ |
242 | WL1271_NVS_STAT_RADIO_PARAMS_SIZE); | 242 | memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, |
243 | memcpy(radio_parms->dyn_radio_params, | 243 | sizeof(struct wl1271_ini_band_params_2)); |
244 | wl->nvs->dyn_radio_params[rparam->fem], | 244 | memcpy(&radio_parms->dyn_params_2, |
245 | WL1271_NVS_DYN_RADIO_PARAMS_SIZE); | 245 | &wl->nvs->dyn_radio_params_2[rparam->fem].params, |
246 | 246 | sizeof(struct wl1271_ini_fem_params_2)); | |
247 | /* FIXME: current NVS is missing 5GHz parameters */ | 247 | |
248 | /* 5GHz parameters */ | ||
249 | memcpy(&radio_parms->static_params_5, | ||
250 | &wl->nvs->stat_radio_params_5, | ||
251 | sizeof(struct wl1271_ini_band_params_5)); | ||
252 | memcpy(&radio_parms->dyn_params_5, | ||
253 | &wl->nvs->dyn_radio_params_5[rparam->fem].params, | ||
254 | sizeof(struct wl1271_ini_fem_params_5)); | ||
248 | 255 | ||
249 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 256 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
250 | radio_parms, sizeof(*radio_parms)); | 257 | radio_parms, sizeof(*radio_parms)); |
@@ -329,12 +336,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | |||
329 | join->channel = wl->channel; | 336 | join->channel = wl->channel; |
330 | join->ssid_len = wl->ssid_len; | 337 | join->ssid_len = wl->ssid_len; |
331 | memcpy(join->ssid, wl->ssid, wl->ssid_len); | 338 | memcpy(join->ssid, wl->ssid, wl->ssid_len); |
332 | join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH; | ||
333 | |||
334 | /* increment the session counter */ | ||
335 | wl->session_counter++; | ||
336 | if (wl->session_counter >= SESSION_COUNTER_MAX) | ||
337 | wl->session_counter = 0; | ||
338 | 339 | ||
339 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; | 340 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; |
340 | 341 | ||
@@ -517,7 +518,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) | |||
517 | ps_params->send_null_data = send; | 518 | ps_params->send_null_data = send; |
518 | ps_params->retries = 5; | 519 | ps_params->retries = 5; |
519 | ps_params->hang_over_period = 1; | 520 | ps_params->hang_over_period = 1; |
520 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ | 521 | ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set); |
521 | 522 | ||
522 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 523 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
523 | sizeof(*ps_params), 0); | 524 | sizeof(*ps_params), 0); |
@@ -567,7 +568,7 @@ out: | |||
567 | } | 568 | } |
568 | 569 | ||
569 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | 570 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
570 | const u8 *ie, size_t ie_len, u8 active_scan, | 571 | struct cfg80211_scan_request *req, u8 active_scan, |
571 | u8 high_prio, u8 band, u8 probe_requests) | 572 | u8 high_prio, u8 band, u8 probe_requests) |
572 | { | 573 | { |
573 | 574 | ||
@@ -648,7 +649,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
648 | } | 649 | } |
649 | 650 | ||
650 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, | 651 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, |
651 | ie, ie_len, ieee_band); | 652 | req->ie, req->ie_len, ieee_band); |
652 | if (ret < 0) { | 653 | if (ret < 0) { |
653 | wl1271_error("PROBE request template failed"); | 654 | wl1271_error("PROBE request template failed"); |
654 | goto out; | 655 | goto out; |
@@ -684,7 +685,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
684 | memcpy(wl->scan.ssid, ssid, ssid_len); | 685 | memcpy(wl->scan.ssid, ssid, ssid_len); |
685 | } else | 686 | } else |
686 | wl->scan.ssid_len = 0; | 687 | wl->scan.ssid_len = 0; |
687 | } | 688 | wl->scan.req = req; |
689 | } else | ||
690 | wl->scan.req = NULL; | ||
688 | } | 691 | } |
689 | 692 | ||
690 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | 693 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index f2820b42a943..68001dffe716 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -42,7 +42,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | |||
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | 44 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
45 | const u8 *ie, size_t ie_len, u8 active_scan, | 45 | struct cfg80211_scan_request *req, u8 active_scan, |
46 | u8 high_prio, u8 band, u8 probe_requests); | 46 | u8 high_prio, u8 band, u8 probe_requests); |
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len, int index, u32 rates); | 48 | void *buf, size_t buf_len, int index, u32 rates); |
@@ -439,24 +439,30 @@ struct wl1271_general_parms_cmd { | |||
439 | 439 | ||
440 | struct wl1271_cmd_test_header test; | 440 | struct wl1271_cmd_test_header test; |
441 | 441 | ||
442 | u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE]; | 442 | struct wl1271_ini_general_params general_params; |
443 | s8 reserved[23]; | ||
444 | } __attribute__ ((packed)); | ||
445 | 443 | ||
446 | #define WL1271_STAT_RADIO_PARAMS_5_SIZE 29 | 444 | u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; |
447 | #define WL1271_DYN_RADIO_PARAMS_5_SIZE 104 | 445 | u8 sr_sen_n_p; |
446 | u8 sr_sen_n_p_gain; | ||
447 | u8 sr_sen_nrn; | ||
448 | u8 sr_sen_prn; | ||
449 | u8 padding[3]; | ||
450 | } __attribute__ ((packed)); | ||
448 | 451 | ||
449 | struct wl1271_radio_parms_cmd { | 452 | struct wl1271_radio_parms_cmd { |
450 | struct wl1271_cmd_header header; | 453 | struct wl1271_cmd_header header; |
451 | 454 | ||
452 | struct wl1271_cmd_test_header test; | 455 | struct wl1271_cmd_test_header test; |
453 | 456 | ||
454 | u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE]; | 457 | /* Static radio parameters */ |
455 | u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE]; | 458 | struct wl1271_ini_band_params_2 static_params_2; |
459 | struct wl1271_ini_band_params_5 static_params_5; | ||
456 | 460 | ||
457 | u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE]; | 461 | /* Dynamic radio parameters */ |
458 | u8 reserved; | 462 | struct wl1271_ini_fem_params_2 dyn_params_2; |
459 | u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE]; | 463 | u8 padding2; |
464 | struct wl1271_ini_fem_params_5 dyn_params_5; | ||
465 | u8 padding3[2]; | ||
460 | } __attribute__ ((packed)); | 466 | } __attribute__ ((packed)); |
461 | 467 | ||
462 | struct wl1271_cmd_cal_channel_tune { | 468 | struct wl1271_cmd_cal_channel_tune { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index cf37aa6eb137..ca52cdec7a8f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -43,11 +43,11 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
43 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | 43 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
44 | /* FIXME: ie missing! */ | 44 | /* FIXME: ie missing! */ |
45 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 45 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
46 | NULL, 0, | 46 | wl->scan.req, |
47 | wl->scan.active, | 47 | wl->scan.active, |
48 | wl->scan.high_prio, | 48 | wl->scan.high_prio, |
49 | WL1271_SCAN_BAND_5_GHZ, | 49 | WL1271_SCAN_BAND_5_GHZ, |
50 | wl->scan.probe_requests); | 50 | wl->scan.probe_requests); |
51 | } else { | 51 | } else { |
52 | mutex_unlock(&wl->mutex); | 52 | mutex_unlock(&wl->mutex); |
53 | ieee80211_scan_completed(wl->hw, false); | 53 | ieee80211_scan_completed(wl->hw, false); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ini.h b/drivers/net/wireless/wl12xx/wl1271_ini.h new file mode 100644 index 000000000000..0fb156a5af12 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_ini.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1271_INI_H__ | ||
25 | #define __WL1271_INI_H__ | ||
26 | |||
27 | #define WL1271_INI_MAX_SMART_REFLEX_PARAM 16 | ||
28 | |||
29 | struct wl1271_ini_general_params { | ||
30 | u8 ref_clock; | ||
31 | u8 settling_time; | ||
32 | u8 clk_valid_on_wakeup; | ||
33 | u8 dc2dc_mode; | ||
34 | u8 dual_mode_select; | ||
35 | u8 tx_bip_fem_auto_detect; | ||
36 | u8 tx_bip_fem_manufacturer; | ||
37 | u8 general_settings; | ||
38 | u8 sr_state; | ||
39 | u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
40 | u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
41 | u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; | ||
42 | } __attribute__ ((packed)); | ||
43 | |||
44 | #define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15 | ||
45 | |||
46 | struct wl1271_ini_band_params_2 { | ||
47 | u8 rx_trace_insertion_loss; | ||
48 | u8 tx_trace_loss; | ||
49 | u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; | ||
50 | } __attribute__ ((packed)); | ||
51 | |||
52 | #define WL1271_INI_RATE_GROUP_COUNT 6 | ||
53 | #define WL1271_INI_CHANNEL_COUNT_2 14 | ||
54 | |||
55 | struct wl1271_ini_fem_params_2 { | ||
56 | __le16 tx_bip_ref_pd_voltage; | ||
57 | u8 tx_bip_ref_power; | ||
58 | u8 tx_bip_ref_offset; | ||
59 | u8 tx_per_rate_pwr_limits_normal[WL1271_INI_RATE_GROUP_COUNT]; | ||
60 | u8 tx_per_rate_pwr_limits_degraded[WL1271_INI_RATE_GROUP_COUNT]; | ||
61 | u8 tx_per_rate_pwr_limits_extreme[WL1271_INI_RATE_GROUP_COUNT]; | ||
62 | u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2]; | ||
63 | u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2]; | ||
64 | u8 tx_pd_vs_rate_offsets[WL1271_INI_RATE_GROUP_COUNT]; | ||
65 | u8 tx_ibias[WL1271_INI_RATE_GROUP_COUNT]; | ||
66 | u8 rx_fem_insertion_loss; | ||
67 | u8 degraded_low_to_normal_thr; | ||
68 | u8 normal_to_degraded_high_thr; | ||
69 | } __attribute__ ((packed)); | ||
70 | |||
71 | #define WL1271_INI_CHANNEL_COUNT_5 35 | ||
72 | #define WL1271_INI_SUB_BAND_COUNT_5 7 | ||
73 | |||
74 | struct wl1271_ini_band_params_5 { | ||
75 | u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; | ||
76 | u8 tx_trace_loss[WL1271_INI_SUB_BAND_COUNT_5]; | ||
77 | u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; | ||
78 | } __attribute__ ((packed)); | ||
79 | |||
80 | struct wl1271_ini_fem_params_5 { | ||
81 | __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; | ||
82 | u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; | ||
83 | u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5]; | ||
84 | u8 tx_per_rate_pwr_limits_normal[WL1271_INI_RATE_GROUP_COUNT]; | ||
85 | u8 tx_per_rate_pwr_limits_degraded[WL1271_INI_RATE_GROUP_COUNT]; | ||
86 | u8 tx_per_rate_pwr_limits_extreme[WL1271_INI_RATE_GROUP_COUNT]; | ||
87 | u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5]; | ||
88 | u8 tx_pd_vs_rate_offsets[WL1271_INI_RATE_GROUP_COUNT]; | ||
89 | u8 tx_ibias[WL1271_INI_RATE_GROUP_COUNT]; | ||
90 | u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; | ||
91 | u8 degraded_low_to_normal_thr; | ||
92 | u8 normal_to_degraded_high_thr; | ||
93 | } __attribute__ ((packed)); | ||
94 | |||
95 | |||
96 | /* NVS data structure */ | ||
97 | #define WL1271_INI_NVS_SECTION_SIZE 468 | ||
98 | #define WL1271_INI_FEM_MODULE_COUNT 2 | ||
99 | |||
100 | #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 | ||
101 | |||
102 | struct wl1271_nvs_file { | ||
103 | /* NVS section */ | ||
104 | u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; | ||
105 | |||
106 | /* INI section */ | ||
107 | struct wl1271_ini_general_params general_params; | ||
108 | u8 padding1; | ||
109 | struct wl1271_ini_band_params_2 stat_radio_params_2; | ||
110 | u8 padding2; | ||
111 | struct { | ||
112 | struct wl1271_ini_fem_params_2 params; | ||
113 | u8 padding; | ||
114 | } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; | ||
115 | struct wl1271_ini_band_params_5 stat_radio_params_5; | ||
116 | u8 padding3; | ||
117 | struct { | ||
118 | struct wl1271_ini_fem_params_5 params; | ||
119 | u8 padding; | ||
120 | } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; | ||
121 | } __attribute__ ((packed)); | ||
122 | |||
123 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b7d9137851ac..7a14da506d78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -566,14 +566,21 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
566 | return ret; | 566 | return ret; |
567 | } | 567 | } |
568 | 568 | ||
569 | if (fw->size != sizeof(struct wl1271_nvs_file)) { | 569 | /* |
570 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
571 | * configurations) can be removed when those NVS files stop floating | ||
572 | * around. | ||
573 | */ | ||
574 | if (fw->size != sizeof(struct wl1271_nvs_file) && | ||
575 | (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
576 | wl1271_11a_enabled())) { | ||
570 | wl1271_error("nvs size is not as expected: %zu != %zu", | 577 | wl1271_error("nvs size is not as expected: %zu != %zu", |
571 | fw->size, sizeof(struct wl1271_nvs_file)); | 578 | fw->size, sizeof(struct wl1271_nvs_file)); |
572 | ret = -EILSEQ; | 579 | ret = -EILSEQ; |
573 | goto out; | 580 | goto out; |
574 | } | 581 | } |
575 | 582 | ||
576 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); | 583 | wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
577 | 584 | ||
578 | if (!wl->nvs) { | 585 | if (!wl->nvs) { |
579 | wl1271_error("could not allocate memory for the nvs file"); | 586 | wl1271_error("could not allocate memory for the nvs file"); |
@@ -581,7 +588,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
581 | goto out; | 588 | goto out; |
582 | } | 589 | } |
583 | 590 | ||
584 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); | 591 | memcpy(wl->nvs, fw->data, fw->size); |
585 | 592 | ||
586 | out: | 593 | out: |
587 | release_firmware(fw); | 594 | release_firmware(fw); |
@@ -1044,7 +1051,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1044 | mutex_lock(&wl->mutex); | 1051 | mutex_lock(&wl->mutex); |
1045 | 1052 | ||
1046 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1053 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1047 | wl1271_tx_flush(wl); | 1054 | wl1271_tx_reset(wl); |
1048 | wl1271_power_off(wl); | 1055 | wl1271_power_off(wl); |
1049 | 1056 | ||
1050 | memset(wl->bssid, 0, ETH_ALEN); | 1057 | memset(wl->bssid, 0, ETH_ALEN); |
@@ -1241,6 +1248,42 @@ static u32 wl1271_min_rate_get(struct wl1271 *wl) | |||
1241 | return rate; | 1248 | return rate; |
1242 | } | 1249 | } |
1243 | 1250 | ||
1251 | static int wl1271_handle_idle(struct wl1271 *wl, bool idle) | ||
1252 | { | ||
1253 | int ret; | ||
1254 | |||
1255 | if (idle) { | ||
1256 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1257 | ret = wl1271_unjoin(wl); | ||
1258 | if (ret < 0) | ||
1259 | goto out; | ||
1260 | } | ||
1261 | wl->rate_set = wl1271_min_rate_get(wl); | ||
1262 | wl->sta_rate_set = 0; | ||
1263 | ret = wl1271_acx_rate_policies(wl); | ||
1264 | if (ret < 0) | ||
1265 | goto out; | ||
1266 | ret = wl1271_acx_keep_alive_config( | ||
1267 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1268 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1269 | if (ret < 0) | ||
1270 | goto out; | ||
1271 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1272 | } else { | ||
1273 | /* increment the session counter */ | ||
1274 | wl->session_counter++; | ||
1275 | if (wl->session_counter >= SESSION_COUNTER_MAX) | ||
1276 | wl->session_counter = 0; | ||
1277 | ret = wl1271_dummy_join(wl); | ||
1278 | if (ret < 0) | ||
1279 | goto out; | ||
1280 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1281 | } | ||
1282 | |||
1283 | out: | ||
1284 | return ret; | ||
1285 | } | ||
1286 | |||
1244 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1287 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1245 | { | 1288 | { |
1246 | struct wl1271 *wl = hw->priv; | 1289 | struct wl1271 *wl = hw->priv; |
@@ -1255,6 +1298,15 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1255 | conf->power_level, | 1298 | conf->power_level, |
1256 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | 1299 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); |
1257 | 1300 | ||
1301 | /* | ||
1302 | * mac80211 will go to idle nearly immediately after transmitting some | ||
1303 | * frames, such as the deauth. To make sure those frames reach the air, | ||
1304 | * wait here until the TX queue is fully flushed. | ||
1305 | */ | ||
1306 | if ((changed & IEEE80211_CONF_CHANGE_IDLE) && | ||
1307 | (conf->flags & IEEE80211_CONF_IDLE)) | ||
1308 | wl1271_tx_flush(wl); | ||
1309 | |||
1258 | mutex_lock(&wl->mutex); | 1310 | mutex_lock(&wl->mutex); |
1259 | 1311 | ||
1260 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 1312 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
@@ -1295,22 +1347,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1295 | } | 1347 | } |
1296 | 1348 | ||
1297 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1349 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1298 | if (conf->flags & IEEE80211_CONF_IDLE && | 1350 | ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE); |
1299 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1351 | if (ret < 0) |
1300 | wl1271_unjoin(wl); | 1352 | wl1271_warning("idle mode change failed %d", ret); |
1301 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) | ||
1302 | wl1271_dummy_join(wl); | ||
1303 | |||
1304 | if (conf->flags & IEEE80211_CONF_IDLE) { | ||
1305 | wl->rate_set = wl1271_min_rate_get(wl); | ||
1306 | wl->sta_rate_set = 0; | ||
1307 | wl1271_acx_rate_policies(wl); | ||
1308 | wl1271_acx_keep_alive_config( | ||
1309 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1310 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1311 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1312 | } else | ||
1313 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1314 | } | 1353 | } |
1315 | 1354 | ||
1316 | if (conf->flags & IEEE80211_CONF_PS && | 1355 | if (conf->flags & IEEE80211_CONF_PS && |
@@ -1595,13 +1634,11 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1595 | goto out; | 1634 | goto out; |
1596 | 1635 | ||
1597 | if (wl1271_11a_enabled()) | 1636 | if (wl1271_11a_enabled()) |
1598 | ret = wl1271_cmd_scan(hw->priv, ssid, len, | 1637 | ret = wl1271_cmd_scan(hw->priv, ssid, len, req, |
1599 | req->ie, req->ie_len, 1, 0, | 1638 | 1, 0, WL1271_SCAN_BAND_DUAL, 3); |
1600 | WL1271_SCAN_BAND_DUAL, 3); | ||
1601 | else | 1639 | else |
1602 | ret = wl1271_cmd_scan(hw->priv, ssid, len, | 1640 | ret = wl1271_cmd_scan(hw->priv, ssid, len, req, |
1603 | req->ie, req->ie_len, 1, 0, | 1641 | 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3); |
1604 | WL1271_SCAN_BAND_2_4_GHZ, 3); | ||
1605 | 1642 | ||
1606 | wl1271_ps_elp_sleep(wl); | 1643 | wl1271_ps_elp_sleep(wl); |
1607 | 1644 | ||
@@ -1991,7 +2028,7 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1991 | }; | 2028 | }; |
1992 | 2029 | ||
1993 | /* mapping to indexes for wl1271_rates */ | 2030 | /* mapping to indexes for wl1271_rates */ |
1994 | const static u8 wl1271_rate_to_idx_2ghz[] = { | 2031 | static const u8 wl1271_rate_to_idx_2ghz[] = { |
1995 | /* MCS rates are used only with 11n */ | 2032 | /* MCS rates are used only with 11n */ |
1996 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | 2033 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ |
1997 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | 2034 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ |
@@ -2103,7 +2140,7 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
2103 | }; | 2140 | }; |
2104 | 2141 | ||
2105 | /* mapping to indexes for wl1271_rates_5ghz */ | 2142 | /* mapping to indexes for wl1271_rates_5ghz */ |
2106 | const static u8 wl1271_rate_to_idx_5ghz[] = { | 2143 | static const u8 wl1271_rate_to_idx_5ghz[] = { |
2107 | /* MCS rates are used only with 11n */ | 2144 | /* MCS rates are used only with 11n */ |
2108 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | 2145 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ |
2109 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | 2146 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ |
@@ -2139,7 +2176,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
2139 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2176 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
2140 | }; | 2177 | }; |
2141 | 2178 | ||
2142 | const static u8 *wl1271_band_rate_to_idx[] = { | 2179 | static const u8 *wl1271_band_rate_to_idx[] = { |
2143 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | 2180 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, |
2144 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | 2181 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz |
2145 | }; | 2182 | }; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index d3d6f302f705..7059b5cccf0f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/mmc/sdio_func.h> | 28 | #include <linux/mmc/sdio_func.h> |
29 | #include <linux/mmc/sdio_ids.h> | 29 | #include <linux/mmc/sdio_ids.h> |
30 | #include <linux/mmc/card.h> | 30 | #include <linux/mmc/card.h> |
31 | #include <plat/gpio.h> | 31 | #include <linux/gpio.h> |
32 | 32 | ||
33 | #include "wl1271.h" | 33 | #include "wl1271.h" |
34 | #include "wl12xx_80211.h" | 34 | #include "wl12xx_80211.h" |
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 554deb4d024e..6e0952f79e9a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -199,7 +199,14 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | |||
199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | 199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); |
200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); | 200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); |
201 | 201 | ||
202 | if (len != sizeof(struct wl1271_nvs_file)) { | 202 | /* |
203 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
204 | * configurations) can be removed when those NVS files stop floating | ||
205 | * around. | ||
206 | */ | ||
207 | if (len != sizeof(struct wl1271_nvs_file) && | ||
208 | (len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
209 | wl1271_11a_enabled())) { | ||
203 | wl1271_error("nvs size is not as expected: %zu != %zu", | 210 | wl1271_error("nvs size is not as expected: %zu != %zu", |
204 | len, sizeof(struct wl1271_nvs_file)); | 211 | len, sizeof(struct wl1271_nvs_file)); |
205 | return -EMSGSIZE; | 212 | return -EMSGSIZE; |
@@ -209,7 +216,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | |||
209 | 216 | ||
210 | kfree(wl->nvs); | 217 | kfree(wl->nvs); |
211 | 218 | ||
212 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); | 219 | wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
213 | if (!wl->nvs) { | 220 | if (!wl->nvs) { |
214 | wl1271_error("could not allocate memory for the nvs file"); | 221 | wl1271_error("could not allocate memory for the nvs file"); |
215 | ret = -ENOMEM; | 222 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 62db79508ddf..c592cc2e9fe8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -36,6 +36,7 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
36 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 36 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
37 | if (wl->tx_frames[i] == NULL) { | 37 | if (wl->tx_frames[i] == NULL) { |
38 | wl->tx_frames[i] = skb; | 38 | wl->tx_frames[i] = skb; |
39 | wl->tx_frames_cnt++; | ||
39 | return i; | 40 | return i; |
40 | } | 41 | } |
41 | 42 | ||
@@ -73,8 +74,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
73 | wl1271_debug(DEBUG_TX, | 74 | wl1271_debug(DEBUG_TX, |
74 | "tx_allocate: size: %d, blocks: %d, id: %d", | 75 | "tx_allocate: size: %d, blocks: %d, id: %d", |
75 | total_len, total_blocks, id); | 76 | total_len, total_blocks, id); |
76 | } else | 77 | } else { |
77 | wl->tx_frames[id] = NULL; | 78 | wl->tx_frames[id] = NULL; |
79 | wl->tx_frames_cnt--; | ||
80 | } | ||
78 | 81 | ||
79 | return ret; | 82 | return ret; |
80 | } | 83 | } |
@@ -358,6 +361,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
358 | /* return the packet to the stack */ | 361 | /* return the packet to the stack */ |
359 | ieee80211_tx_status(wl->hw, skb); | 362 | ieee80211_tx_status(wl->hw, skb); |
360 | wl->tx_frames[result->id] = NULL; | 363 | wl->tx_frames[result->id] = NULL; |
364 | wl->tx_frames_cnt--; | ||
361 | } | 365 | } |
362 | 366 | ||
363 | /* Called upon reception of a TX complete interrupt */ | 367 | /* Called upon reception of a TX complete interrupt */ |
@@ -412,7 +416,7 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
412 | } | 416 | } |
413 | 417 | ||
414 | /* caller must hold wl->mutex */ | 418 | /* caller must hold wl->mutex */ |
415 | void wl1271_tx_flush(struct wl1271 *wl) | 419 | void wl1271_tx_reset(struct wl1271 *wl) |
416 | { | 420 | { |
417 | int i; | 421 | int i; |
418 | struct sk_buff *skb; | 422 | struct sk_buff *skb; |
@@ -421,7 +425,7 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
421 | /* control->flags = 0; FIXME */ | 425 | /* control->flags = 0; FIXME */ |
422 | 426 | ||
423 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 427 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); | 428 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); |
425 | ieee80211_tx_status(wl->hw, skb); | 429 | ieee80211_tx_status(wl->hw, skb); |
426 | } | 430 | } |
427 | 431 | ||
@@ -429,6 +433,32 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
429 | if (wl->tx_frames[i] != NULL) { | 433 | if (wl->tx_frames[i] != NULL) { |
430 | skb = wl->tx_frames[i]; | 434 | skb = wl->tx_frames[i]; |
431 | wl->tx_frames[i] = NULL; | 435 | wl->tx_frames[i] = NULL; |
436 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); | ||
432 | ieee80211_tx_status(wl->hw, skb); | 437 | ieee80211_tx_status(wl->hw, skb); |
433 | } | 438 | } |
439 | wl->tx_frames_cnt = 0; | ||
440 | } | ||
441 | |||
442 | #define WL1271_TX_FLUSH_TIMEOUT 500000 | ||
443 | |||
444 | /* caller must *NOT* hold wl->mutex */ | ||
445 | void wl1271_tx_flush(struct wl1271 *wl) | ||
446 | { | ||
447 | unsigned long timeout; | ||
448 | timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); | ||
449 | |||
450 | while (!time_after(jiffies, timeout)) { | ||
451 | mutex_lock(&wl->mutex); | ||
452 | wl1271_debug(DEBUG_TX, "flushing tx buffer: %d", | ||
453 | wl->tx_frames_cnt); | ||
454 | if ((wl->tx_frames_cnt == 0) && | ||
455 | skb_queue_empty(&wl->tx_queue)) { | ||
456 | mutex_unlock(&wl->mutex); | ||
457 | return; | ||
458 | } | ||
459 | mutex_unlock(&wl->mutex); | ||
460 | msleep(1); | ||
461 | } | ||
462 | |||
463 | wl1271_warning("Unable to flush all TX buffers, timed out."); | ||
434 | } | 464 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 3b8b7ac253fd..0ae00637933e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -158,6 +158,7 @@ static inline int wl1271_tx_ac_to_tid(int ac) | |||
158 | 158 | ||
159 | void wl1271_tx_work(struct work_struct *work); | 159 | void wl1271_tx_work(struct work_struct *work); |
160 | void wl1271_tx_complete(struct wl1271 *wl); | 160 | void wl1271_tx_complete(struct wl1271 *wl); |
161 | void wl1271_tx_reset(struct wl1271 *wl); | ||
161 | void wl1271_tx_flush(struct wl1271 *wl); | 162 | void wl1271_tx_flush(struct wl1271 *wl); |
162 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | 163 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); |
163 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 164 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index b0b666019a93..43307bd42a69 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -42,7 +42,8 @@ static struct zd_reg_alpha2_map reg_alpha2_map[] = { | |||
42 | { ZD_REGDOMAIN_IC, "CA" }, | 42 | { ZD_REGDOMAIN_IC, "CA" }, |
43 | { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ | 43 | { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ |
44 | { ZD_REGDOMAIN_JAPAN, "JP" }, | 44 | { ZD_REGDOMAIN_JAPAN, "JP" }, |
45 | { ZD_REGDOMAIN_JAPAN_ADD, "JP" }, | 45 | { ZD_REGDOMAIN_JAPAN_2, "JP" }, |
46 | { ZD_REGDOMAIN_JAPAN_3, "JP" }, | ||
46 | { ZD_REGDOMAIN_SPAIN, "ES" }, | 47 | { ZD_REGDOMAIN_SPAIN, "ES" }, |
47 | { ZD_REGDOMAIN_FRANCE, "FR" }, | 48 | { ZD_REGDOMAIN_FRANCE, "FR" }, |
48 | }; | 49 | }; |
@@ -855,7 +856,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
855 | if (skb == NULL) | 856 | if (skb == NULL) |
856 | return -ENOMEM; | 857 | return -ENOMEM; |
857 | if (need_padding) { | 858 | if (need_padding) { |
858 | /* Make sure the the payload data is 4 byte aligned. */ | 859 | /* Make sure the payload data is 4 byte aligned. */ |
859 | skb_reserve(skb, 2); | 860 | skb_reserve(skb, 2); |
860 | } | 861 | } |
861 | 862 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 630c298a730e..d21739a530ec 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -212,8 +212,9 @@ struct zd_mac { | |||
212 | #define ZD_REGDOMAIN_ETSI 0x30 | 212 | #define ZD_REGDOMAIN_ETSI 0x30 |
213 | #define ZD_REGDOMAIN_SPAIN 0x31 | 213 | #define ZD_REGDOMAIN_SPAIN 0x31 |
214 | #define ZD_REGDOMAIN_FRANCE 0x32 | 214 | #define ZD_REGDOMAIN_FRANCE 0x32 |
215 | #define ZD_REGDOMAIN_JAPAN_ADD 0x40 | 215 | #define ZD_REGDOMAIN_JAPAN_2 0x40 |
216 | #define ZD_REGDOMAIN_JAPAN 0x41 | 216 | #define ZD_REGDOMAIN_JAPAN 0x41 |
217 | #define ZD_REGDOMAIN_JAPAN_3 0x49 | ||
217 | 218 | ||
218 | enum { | 219 | enum { |
219 | MIN_CHANNEL24 = 1, | 220 | MIN_CHANNEL24 = 1, |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index c257940b71b6..818e1480ca93 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -844,7 +844,7 @@ out: | |||
844 | * @usb: a &struct zd_usb pointer | 844 | * @usb: a &struct zd_usb pointer |
845 | * @urb: URB to be freed | 845 | * @urb: URB to be freed |
846 | * | 846 | * |
847 | * Frees the the transmission URB, which means to put it on the free URB | 847 | * Frees the transmission URB, which means to put it on the free URB |
848 | * list. | 848 | * list. |
849 | */ | 849 | */ |
850 | static void free_tx_urb(struct zd_usb *usb, struct urb *urb) | 850 | static void free_tx_urb(struct zd_usb *usb, struct urb *urb) |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 59ae76bace14..7c031fdc8205 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -209,6 +209,24 @@ static void chipco_powercontrol_init(struct ssb_chipcommon *cc) | |||
209 | } | 209 | } |
210 | } | 210 | } |
211 | 211 | ||
212 | /* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */ | ||
213 | static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc) | ||
214 | { | ||
215 | struct ssb_bus *bus = cc->dev->bus; | ||
216 | |||
217 | switch (bus->chip_id) { | ||
218 | case 0x4312: | ||
219 | case 0x4322: | ||
220 | case 0x4328: | ||
221 | return 7000; | ||
222 | case 0x4325: | ||
223 | /* TODO: */ | ||
224 | default: | ||
225 | return 15000; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | /* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */ | ||
212 | static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) | 230 | static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) |
213 | { | 231 | { |
214 | struct ssb_bus *bus = cc->dev->bus; | 232 | struct ssb_bus *bus = cc->dev->bus; |
@@ -218,6 +236,12 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) | |||
218 | 236 | ||
219 | if (bus->bustype != SSB_BUSTYPE_PCI) | 237 | if (bus->bustype != SSB_BUSTYPE_PCI) |
220 | return; | 238 | return; |
239 | |||
240 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { | ||
241 | cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc); | ||
242 | return; | ||
243 | } | ||
244 | |||
221 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) | 245 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) |
222 | return; | 246 | return; |
223 | 247 | ||
@@ -235,6 +259,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) | |||
235 | return; /* We don't have a ChipCommon */ | 259 | return; /* We don't have a ChipCommon */ |
236 | if (cc->dev->id.revision >= 11) | 260 | if (cc->dev->id.revision >= 11) |
237 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); | 261 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); |
262 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); | ||
238 | ssb_pmu_init(cc); | 263 | ssb_pmu_init(cc); |
239 | chipco_powercontrol_init(cc); | 264 | chipco_powercontrol_init(cc); |
240 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); | 265 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); |
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 3d551245a4e2..5732bb2c3578 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -502,9 +502,9 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) | |||
502 | chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); | 502 | chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); |
503 | } | 503 | } |
504 | 504 | ||
505 | /* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */ | ||
505 | void ssb_pmu_init(struct ssb_chipcommon *cc) | 506 | void ssb_pmu_init(struct ssb_chipcommon *cc) |
506 | { | 507 | { |
507 | struct ssb_bus *bus = cc->dev->bus; | ||
508 | u32 pmucap; | 508 | u32 pmucap; |
509 | 509 | ||
510 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) | 510 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) |
@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) | |||
516 | ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", | 516 | ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", |
517 | cc->pmu.rev, pmucap); | 517 | cc->pmu.rev, pmucap); |
518 | 518 | ||
519 | if (cc->pmu.rev >= 1) { | 519 | if (cc->pmu.rev == 1) |
520 | if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) { | 520 | chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, |
521 | chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, | 521 | ~SSB_CHIPCO_PMU_CTL_NOILPONW); |
522 | ~SSB_CHIPCO_PMU_CTL_NOILPONW); | 522 | else |
523 | } else { | 523 | chipco_set32(cc, SSB_CHIPCO_PMU_CTL, |
524 | chipco_set32(cc, SSB_CHIPCO_PMU_CTL, | 524 | SSB_CHIPCO_PMU_CTL_NOILPONW); |
525 | SSB_CHIPCO_PMU_CTL_NOILPONW); | ||
526 | } | ||
527 | } | ||
528 | ssb_pmu_pll_init(cc); | 525 | ssb_pmu_pll_init(cc); |
529 | ssb_pmu_resources_init(cc); | 526 | ssb_pmu_resources_init(cc); |
530 | } | 527 | } |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 51275aac5b34..7cee7f4eb60b 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -486,6 +486,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
486 | #ifdef CONFIG_SSB_PCIHOST | 486 | #ifdef CONFIG_SSB_PCIHOST |
487 | sdev->irq = bus->host_pci->irq; | 487 | sdev->irq = bus->host_pci->irq; |
488 | dev->parent = &bus->host_pci->dev; | 488 | dev->parent = &bus->host_pci->dev; |
489 | sdev->dma_dev = dev->parent; | ||
489 | #endif | 490 | #endif |
490 | break; | 491 | break; |
491 | case SSB_BUSTYPE_PCMCIA: | 492 | case SSB_BUSTYPE_PCMCIA: |
@@ -501,6 +502,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
501 | break; | 502 | break; |
502 | case SSB_BUSTYPE_SSB: | 503 | case SSB_BUSTYPE_SSB: |
503 | dev->dma_mask = &dev->coherent_dma_mask; | 504 | dev->dma_mask = &dev->coherent_dma_mask; |
505 | sdev->dma_dev = dev; | ||
504 | break; | 506 | break; |
505 | } | 507 | } |
506 | 508 | ||
@@ -1226,80 +1228,6 @@ u32 ssb_dma_translation(struct ssb_device *dev) | |||
1226 | } | 1228 | } |
1227 | EXPORT_SYMBOL(ssb_dma_translation); | 1229 | EXPORT_SYMBOL(ssb_dma_translation); |
1228 | 1230 | ||
1229 | int ssb_dma_set_mask(struct ssb_device *dev, u64 mask) | ||
1230 | { | ||
1231 | #ifdef CONFIG_SSB_PCIHOST | ||
1232 | int err; | ||
1233 | #endif | ||
1234 | |||
1235 | switch (dev->bus->bustype) { | ||
1236 | case SSB_BUSTYPE_PCI: | ||
1237 | #ifdef CONFIG_SSB_PCIHOST | ||
1238 | err = pci_set_dma_mask(dev->bus->host_pci, mask); | ||
1239 | if (err) | ||
1240 | return err; | ||
1241 | err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask); | ||
1242 | return err; | ||
1243 | #endif | ||
1244 | case SSB_BUSTYPE_SSB: | ||
1245 | return dma_set_mask(dev->dev, mask); | ||
1246 | default: | ||
1247 | __ssb_dma_not_implemented(dev); | ||
1248 | } | ||
1249 | return -ENOSYS; | ||
1250 | } | ||
1251 | EXPORT_SYMBOL(ssb_dma_set_mask); | ||
1252 | |||
1253 | void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, | ||
1254 | dma_addr_t *dma_handle, gfp_t gfp_flags) | ||
1255 | { | ||
1256 | switch (dev->bus->bustype) { | ||
1257 | case SSB_BUSTYPE_PCI: | ||
1258 | #ifdef CONFIG_SSB_PCIHOST | ||
1259 | if (gfp_flags & GFP_DMA) { | ||
1260 | /* Workaround: The PCI API does not support passing | ||
1261 | * a GFP flag. */ | ||
1262 | return dma_alloc_coherent(&dev->bus->host_pci->dev, | ||
1263 | size, dma_handle, gfp_flags); | ||
1264 | } | ||
1265 | return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle); | ||
1266 | #endif | ||
1267 | case SSB_BUSTYPE_SSB: | ||
1268 | return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags); | ||
1269 | default: | ||
1270 | __ssb_dma_not_implemented(dev); | ||
1271 | } | ||
1272 | return NULL; | ||
1273 | } | ||
1274 | EXPORT_SYMBOL(ssb_dma_alloc_consistent); | ||
1275 | |||
1276 | void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, | ||
1277 | void *vaddr, dma_addr_t dma_handle, | ||
1278 | gfp_t gfp_flags) | ||
1279 | { | ||
1280 | switch (dev->bus->bustype) { | ||
1281 | case SSB_BUSTYPE_PCI: | ||
1282 | #ifdef CONFIG_SSB_PCIHOST | ||
1283 | if (gfp_flags & GFP_DMA) { | ||
1284 | /* Workaround: The PCI API does not support passing | ||
1285 | * a GFP flag. */ | ||
1286 | dma_free_coherent(&dev->bus->host_pci->dev, | ||
1287 | size, vaddr, dma_handle); | ||
1288 | return; | ||
1289 | } | ||
1290 | pci_free_consistent(dev->bus->host_pci, size, | ||
1291 | vaddr, dma_handle); | ||
1292 | return; | ||
1293 | #endif | ||
1294 | case SSB_BUSTYPE_SSB: | ||
1295 | dma_free_coherent(dev->dev, size, vaddr, dma_handle); | ||
1296 | return; | ||
1297 | default: | ||
1298 | __ssb_dma_not_implemented(dev); | ||
1299 | } | ||
1300 | } | ||
1301 | EXPORT_SYMBOL(ssb_dma_free_consistent); | ||
1302 | |||
1303 | int ssb_bus_may_powerdown(struct ssb_bus *bus) | 1231 | int ssb_bus_may_powerdown(struct ssb_bus *bus) |
1304 | { | 1232 | { |
1305 | struct ssb_chipcommon *cc; | 1233 | struct ssb_chipcommon *cc; |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 6dcda86be6eb..6e88d2b603b4 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -626,11 +626,22 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
626 | return -ENODEV; | 626 | return -ENODEV; |
627 | } | 627 | } |
628 | if (bus->chipco.dev) { /* can be unavailible! */ | 628 | if (bus->chipco.dev) { /* can be unavailible! */ |
629 | bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ? | 629 | /* |
630 | SSB_SPROM_BASE1 : SSB_SPROM_BASE31; | 630 | * get SPROM offset: SSB_SPROM_BASE1 except for |
631 | * chipcommon rev >= 31 or chip ID is 0x4312 and | ||
632 | * chipcommon status & 3 == 2 | ||
633 | */ | ||
634 | if (bus->chipco.dev->id.revision >= 31) | ||
635 | bus->sprom_offset = SSB_SPROM_BASE31; | ||
636 | else if (bus->chip_id == 0x4312 && | ||
637 | (bus->chipco.status & 0x03) == 2) | ||
638 | bus->sprom_offset = SSB_SPROM_BASE31; | ||
639 | else | ||
640 | bus->sprom_offset = SSB_SPROM_BASE1; | ||
631 | } else { | 641 | } else { |
632 | bus->sprom_offset = SSB_SPROM_BASE1; | 642 | bus->sprom_offset = SSB_SPROM_BASE1; |
633 | } | 643 | } |
644 | ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); | ||
634 | 645 | ||
635 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); | 646 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); |
636 | if (!buf) | 647 | if (!buf) |