diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ddd53c02be7a..5c7d74a6f16e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1658,3 +1658,160 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); | 1660 | EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); |
1661 | |||
1662 | /* | ||
1663 | * IEEE80211 stack callback functions. | ||
1664 | */ | ||
1665 | static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, | ||
1666 | u32 *iv32, u16 *iv16) | ||
1667 | { | ||
1668 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1669 | struct mac_iveiv_entry iveiv_entry; | ||
1670 | u32 offset; | ||
1671 | |||
1672 | offset = MAC_IVEIV_ENTRY(hw_key_idx); | ||
1673 | rt2800_register_multiread(rt2x00dev, offset, | ||
1674 | &iveiv_entry, sizeof(iveiv_entry)); | ||
1675 | |||
1676 | memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); | ||
1677 | memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); | ||
1678 | } | ||
1679 | |||
1680 | static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
1681 | { | ||
1682 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1683 | u32 reg; | ||
1684 | bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); | ||
1685 | |||
1686 | rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); | ||
1687 | rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); | ||
1688 | rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); | ||
1689 | |||
1690 | rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®); | ||
1691 | rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); | ||
1692 | rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg); | ||
1693 | |||
1694 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | ||
1695 | rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); | ||
1696 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
1697 | |||
1698 | rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); | ||
1699 | rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); | ||
1700 | rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); | ||
1701 | |||
1702 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); | ||
1703 | rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); | ||
1704 | rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); | ||
1705 | |||
1706 | rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); | ||
1707 | rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); | ||
1708 | rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); | ||
1709 | |||
1710 | rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); | ||
1711 | rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); | ||
1712 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); | ||
1713 | |||
1714 | return 0; | ||
1715 | } | ||
1716 | |||
1717 | static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | ||
1718 | const struct ieee80211_tx_queue_params *params) | ||
1719 | { | ||
1720 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1721 | struct data_queue *queue; | ||
1722 | struct rt2x00_field32 field; | ||
1723 | int retval; | ||
1724 | u32 reg; | ||
1725 | u32 offset; | ||
1726 | |||
1727 | /* | ||
1728 | * First pass the configuration through rt2x00lib, that will | ||
1729 | * update the queue settings and validate the input. After that | ||
1730 | * we are free to update the registers based on the value | ||
1731 | * in the queue parameter. | ||
1732 | */ | ||
1733 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | ||
1734 | if (retval) | ||
1735 | return retval; | ||
1736 | |||
1737 | /* | ||
1738 | * We only need to perform additional register initialization | ||
1739 | * for WMM queues/ | ||
1740 | */ | ||
1741 | if (queue_idx >= 4) | ||
1742 | return 0; | ||
1743 | |||
1744 | queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); | ||
1745 | |||
1746 | /* Update WMM TXOP register */ | ||
1747 | offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); | ||
1748 | field.bit_offset = (queue_idx & 1) * 16; | ||
1749 | field.bit_mask = 0xffff << field.bit_offset; | ||
1750 | |||
1751 | rt2800_register_read(rt2x00dev, offset, ®); | ||
1752 | rt2x00_set_field32(®, field, queue->txop); | ||
1753 | rt2800_register_write(rt2x00dev, offset, reg); | ||
1754 | |||
1755 | /* Update WMM registers */ | ||
1756 | field.bit_offset = queue_idx * 4; | ||
1757 | field.bit_mask = 0xf << field.bit_offset; | ||
1758 | |||
1759 | rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); | ||
1760 | rt2x00_set_field32(®, field, queue->aifs); | ||
1761 | rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); | ||
1762 | |||
1763 | rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); | ||
1764 | rt2x00_set_field32(®, field, queue->cw_min); | ||
1765 | rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); | ||
1766 | |||
1767 | rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); | ||
1768 | rt2x00_set_field32(®, field, queue->cw_max); | ||
1769 | rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); | ||
1770 | |||
1771 | /* Update EDCA registers */ | ||
1772 | offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); | ||
1773 | |||
1774 | rt2800_register_read(rt2x00dev, offset, ®); | ||
1775 | rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); | ||
1776 | rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); | ||
1777 | rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); | ||
1778 | rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); | ||
1779 | rt2800_register_write(rt2x00dev, offset, reg); | ||
1780 | |||
1781 | return 0; | ||
1782 | } | ||
1783 | |||
1784 | static u64 rt2800_get_tsf(struct ieee80211_hw *hw) | ||
1785 | { | ||
1786 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1787 | u64 tsf; | ||
1788 | u32 reg; | ||
1789 | |||
1790 | rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, ®); | ||
1791 | tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; | ||
1792 | rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, ®); | ||
1793 | tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); | ||
1794 | |||
1795 | return tsf; | ||
1796 | } | ||
1797 | |||
1798 | const struct ieee80211_ops rt2800_mac80211_ops = { | ||
1799 | .tx = rt2x00mac_tx, | ||
1800 | .start = rt2x00mac_start, | ||
1801 | .stop = rt2x00mac_stop, | ||
1802 | .add_interface = rt2x00mac_add_interface, | ||
1803 | .remove_interface = rt2x00mac_remove_interface, | ||
1804 | .config = rt2x00mac_config, | ||
1805 | .configure_filter = rt2x00mac_configure_filter, | ||
1806 | .set_tim = rt2x00mac_set_tim, | ||
1807 | .set_key = rt2x00mac_set_key, | ||
1808 | .get_stats = rt2x00mac_get_stats, | ||
1809 | .get_tkip_seq = rt2800_get_tkip_seq, | ||
1810 | .set_rts_threshold = rt2800_set_rts_threshold, | ||
1811 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
1812 | .conf_tx = rt2800_conf_tx, | ||
1813 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
1814 | .get_tsf = rt2800_get_tsf, | ||
1815 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
1816 | }; | ||
1817 | EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); | ||