diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2400pci.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 89 |
1 files changed, 35 insertions, 54 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 89b874ca6107..027580bfa7c3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1058,6 +1058,40 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1058 | /* | 1058 | /* |
1059 | * TX data initialization | 1059 | * TX data initialization |
1060 | */ | 1060 | */ |
1061 | static void rt2400pci_write_beacon(struct queue_entry *entry) | ||
1062 | { | ||
1063 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1064 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1065 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1066 | u32 word; | ||
1067 | u32 reg; | ||
1068 | |||
1069 | /* | ||
1070 | * Disable beaconing while we are reloading the beacon data, | ||
1071 | * otherwise we might be sending out invalid data. | ||
1072 | */ | ||
1073 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | ||
1074 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | ||
1075 | rt2x00_set_field32(®, CSR14_TBCN, 0); | ||
1076 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | ||
1077 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | ||
1078 | |||
1079 | /* | ||
1080 | * Replace rt2x00lib allocated descriptor with the | ||
1081 | * pointer to the _real_ hardware descriptor. | ||
1082 | * After that, map the beacon to DMA and update the | ||
1083 | * descriptor. | ||
1084 | */ | ||
1085 | memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); | ||
1086 | skbdesc->desc = entry_priv->desc; | ||
1087 | |||
1088 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); | ||
1089 | |||
1090 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1091 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | ||
1092 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
1093 | } | ||
1094 | |||
1061 | static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 1095 | static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
1062 | const enum data_queue_qid queue) | 1096 | const enum data_queue_qid queue) |
1063 | { | 1097 | { |
@@ -1504,59 +1538,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) | |||
1504 | return tsf; | 1538 | return tsf; |
1505 | } | 1539 | } |
1506 | 1540 | ||
1507 | static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1508 | { | ||
1509 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1510 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1511 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
1512 | struct queue_entry_priv_pci *entry_priv; | ||
1513 | struct skb_frame_desc *skbdesc; | ||
1514 | struct txentry_desc txdesc; | ||
1515 | u32 reg; | ||
1516 | |||
1517 | if (unlikely(!intf->beacon)) | ||
1518 | return -ENOBUFS; | ||
1519 | entry_priv = intf->beacon->priv_data; | ||
1520 | |||
1521 | /* | ||
1522 | * Copy all TX descriptor information into txdesc, | ||
1523 | * after that we are free to use the skb->cb array | ||
1524 | * for our information. | ||
1525 | */ | ||
1526 | intf->beacon->skb = skb; | ||
1527 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
1528 | |||
1529 | /* | ||
1530 | * Fill in skb descriptor | ||
1531 | */ | ||
1532 | skbdesc = get_skb_frame_desc(skb); | ||
1533 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
1534 | skbdesc->desc = entry_priv->desc; | ||
1535 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
1536 | skbdesc->entry = intf->beacon; | ||
1537 | |||
1538 | /* | ||
1539 | * Disable beaconing while we are reloading the beacon data, | ||
1540 | * otherwise we might be sending out invalid data. | ||
1541 | */ | ||
1542 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | ||
1543 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | ||
1544 | rt2x00_set_field32(®, CSR14_TBCN, 0); | ||
1545 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | ||
1546 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | ||
1547 | |||
1548 | /* | ||
1549 | * Enable beacon generation. | ||
1550 | * Write entire beacon with descriptor to register, | ||
1551 | * and kick the beacon generator. | ||
1552 | */ | ||
1553 | rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); | ||
1554 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
1555 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | ||
1556 | |||
1557 | return 0; | ||
1558 | } | ||
1559 | |||
1560 | static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) | 1541 | static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) |
1561 | { | 1542 | { |
1562 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1543 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -1598,9 +1579,9 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | |||
1598 | .link_tuner = rt2400pci_link_tuner, | 1579 | .link_tuner = rt2400pci_link_tuner, |
1599 | .write_tx_desc = rt2400pci_write_tx_desc, | 1580 | .write_tx_desc = rt2400pci_write_tx_desc, |
1600 | .write_tx_data = rt2x00pci_write_tx_data, | 1581 | .write_tx_data = rt2x00pci_write_tx_data, |
1582 | .write_beacon = rt2400pci_write_beacon, | ||
1601 | .kick_tx_queue = rt2400pci_kick_tx_queue, | 1583 | .kick_tx_queue = rt2400pci_kick_tx_queue, |
1602 | .fill_rxdone = rt2400pci_fill_rxdone, | 1584 | .fill_rxdone = rt2400pci_fill_rxdone, |
1603 | .beacon_update = rt2400pci_beacon_update, | ||
1604 | .config_filter = rt2400pci_config_filter, | 1585 | .config_filter = rt2400pci_config_filter, |
1605 | .config_intf = rt2400pci_config_intf, | 1586 | .config_intf = rt2400pci_config_intf, |
1606 | .config_erp = rt2400pci_config_erp, | 1587 | .config_erp = rt2400pci_config_erp, |