diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-01-21 09:21:10 -0500 |
---|---|---|
committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-03-09 19:03:13 -0500 |
commit | a1175124f34a4b859b5064efb84a197e4f6794a6 (patch) | |
tree | 878c5965a18c27c61007be9d668f9e3aa8b3f554 /drivers/net/wireless/iwlwifi/iwl-core.c | |
parent | eff66c519e8087e18526a6e0c5ee3dd1de1bc792 (diff) |
iwlagn: move ICT code into separate file
All the ICT ISR code is iwlagn specific, and doesn't
need to be in iwlcore. So create a new iwl-agn.h
header file that will hold agn specific function
declarations etc., and move the ICT code into a new
iwl-agn-ict.c file that is linked into iwlagn. This
also gets rid of exporting those symbols.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 112149e9b31e..b994eee771a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -114,8 +114,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | |||
114 | u32 iwl_debug_level; | 114 | u32 iwl_debug_level; |
115 | EXPORT_SYMBOL(iwl_debug_level); | 115 | EXPORT_SYMBOL(iwl_debug_level); |
116 | 116 | ||
117 | static irqreturn_t iwl_isr(int irq, void *data); | ||
118 | |||
119 | /* | 117 | /* |
120 | * Parameter order: | 118 | * Parameter order: |
121 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate | 119 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate |
@@ -1664,277 +1662,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1664 | } | 1662 | } |
1665 | EXPORT_SYMBOL(iwl_set_tx_power); | 1663 | EXPORT_SYMBOL(iwl_set_tx_power); |
1666 | 1664 | ||
1667 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | ||
1668 | |||
1669 | /* Free dram table */ | ||
1670 | void iwl_free_isr_ict(struct iwl_priv *priv) | ||
1671 | { | ||
1672 | if (priv->ict_tbl_vir) { | ||
1673 | dma_free_coherent(&priv->pci_dev->dev, | ||
1674 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
1675 | priv->ict_tbl_vir, priv->ict_tbl_dma); | ||
1676 | priv->ict_tbl_vir = NULL; | ||
1677 | } | ||
1678 | } | ||
1679 | EXPORT_SYMBOL(iwl_free_isr_ict); | ||
1680 | |||
1681 | |||
1682 | /* allocate dram shared table it is a PAGE_SIZE aligned | ||
1683 | * also reset all data related to ICT table interrupt. | ||
1684 | */ | ||
1685 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | ||
1686 | { | ||
1687 | |||
1688 | if (priv->cfg->use_isr_legacy) | ||
1689 | return 0; | ||
1690 | /* allocate shrared data table */ | ||
1691 | priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, | ||
1692 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
1693 | &priv->ict_tbl_dma, GFP_KERNEL); | ||
1694 | if (!priv->ict_tbl_vir) | ||
1695 | return -ENOMEM; | ||
1696 | |||
1697 | /* align table to PAGE_SIZE boundry */ | ||
1698 | priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); | ||
1699 | |||
1700 | IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", | ||
1701 | (unsigned long long)priv->ict_tbl_dma, | ||
1702 | (unsigned long long)priv->aligned_ict_tbl_dma, | ||
1703 | (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); | ||
1704 | |||
1705 | priv->ict_tbl = priv->ict_tbl_vir + | ||
1706 | (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); | ||
1707 | |||
1708 | IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", | ||
1709 | priv->ict_tbl, priv->ict_tbl_vir, | ||
1710 | (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); | ||
1711 | |||
1712 | /* reset table and index to all 0 */ | ||
1713 | memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); | ||
1714 | priv->ict_index = 0; | ||
1715 | |||
1716 | /* add periodic RX interrupt */ | ||
1717 | priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | ||
1718 | return 0; | ||
1719 | } | ||
1720 | EXPORT_SYMBOL(iwl_alloc_isr_ict); | ||
1721 | |||
1722 | /* Device is going up inform it about using ICT interrupt table, | ||
1723 | * also we need to tell the driver to start using ICT interrupt. | ||
1724 | */ | ||
1725 | int iwl_reset_ict(struct iwl_priv *priv) | ||
1726 | { | ||
1727 | u32 val; | ||
1728 | unsigned long flags; | ||
1729 | |||
1730 | if (!priv->ict_tbl_vir) | ||
1731 | return 0; | ||
1732 | |||
1733 | spin_lock_irqsave(&priv->lock, flags); | ||
1734 | iwl_disable_interrupts(priv); | ||
1735 | |||
1736 | memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); | ||
1737 | |||
1738 | val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; | ||
1739 | |||
1740 | val |= CSR_DRAM_INT_TBL_ENABLE; | ||
1741 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; | ||
1742 | |||
1743 | IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " | ||
1744 | "aligned dma address %Lx\n", | ||
1745 | val, (unsigned long long)priv->aligned_ict_tbl_dma); | ||
1746 | |||
1747 | iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); | ||
1748 | priv->use_ict = true; | ||
1749 | priv->ict_index = 0; | ||
1750 | iwl_write32(priv, CSR_INT, priv->inta_mask); | ||
1751 | iwl_enable_interrupts(priv); | ||
1752 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1753 | |||
1754 | return 0; | ||
1755 | } | ||
1756 | EXPORT_SYMBOL(iwl_reset_ict); | ||
1757 | |||
1758 | /* Device is going down disable ict interrupt usage */ | ||
1759 | void iwl_disable_ict(struct iwl_priv *priv) | ||
1760 | { | ||
1761 | unsigned long flags; | ||
1762 | |||
1763 | spin_lock_irqsave(&priv->lock, flags); | ||
1764 | priv->use_ict = false; | ||
1765 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1766 | } | ||
1767 | EXPORT_SYMBOL(iwl_disable_ict); | ||
1768 | |||
1769 | /* interrupt handler using ict table, with this interrupt driver will | ||
1770 | * stop using INTA register to get device's interrupt, reading this register | ||
1771 | * is expensive, device will write interrupts in ICT dram table, increment | ||
1772 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
1773 | * entries from current index up to table entry with 0 value. the result is | ||
1774 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
1775 | * set index. | ||
1776 | */ | ||
1777 | irqreturn_t iwl_isr_ict(int irq, void *data) | ||
1778 | { | ||
1779 | struct iwl_priv *priv = data; | ||
1780 | u32 inta, inta_mask; | ||
1781 | u32 val = 0; | ||
1782 | |||
1783 | if (!priv) | ||
1784 | return IRQ_NONE; | ||
1785 | |||
1786 | /* dram interrupt table not set yet, | ||
1787 | * use legacy interrupt. | ||
1788 | */ | ||
1789 | if (!priv->use_ict) | ||
1790 | return iwl_isr(irq, data); | ||
1791 | |||
1792 | spin_lock(&priv->lock); | ||
1793 | |||
1794 | /* Disable (but don't clear!) interrupts here to avoid | ||
1795 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
1796 | * If we have something to service, the tasklet will re-enable ints. | ||
1797 | * If we *don't* have something, we'll re-enable before leaving here. | ||
1798 | */ | ||
1799 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
1800 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1801 | |||
1802 | |||
1803 | /* Ignore interrupt if there's nothing in NIC to service. | ||
1804 | * This may be due to IRQ shared with another device, | ||
1805 | * or due to sporadic interrupts thrown from our NIC. */ | ||
1806 | if (!priv->ict_tbl[priv->ict_index]) { | ||
1807 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
1808 | goto none; | ||
1809 | } | ||
1810 | |||
1811 | /* read all entries that not 0 start with ict_index */ | ||
1812 | while (priv->ict_tbl[priv->ict_index]) { | ||
1813 | |||
1814 | val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); | ||
1815 | IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", | ||
1816 | priv->ict_index, | ||
1817 | le32_to_cpu(priv->ict_tbl[priv->ict_index])); | ||
1818 | priv->ict_tbl[priv->ict_index] = 0; | ||
1819 | priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, | ||
1820 | ICT_COUNT); | ||
1821 | |||
1822 | } | ||
1823 | |||
1824 | /* We should not get this value, just ignore it. */ | ||
1825 | if (val == 0xffffffff) | ||
1826 | val = 0; | ||
1827 | |||
1828 | /* | ||
1829 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
1830 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
1831 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
1832 | * so we use them to decide on the real state of the Rx bit. | ||
1833 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
1834 | */ | ||
1835 | if (val & 0xC0000) | ||
1836 | val |= 0x8000; | ||
1837 | |||
1838 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
1839 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | ||
1840 | inta, inta_mask, val); | ||
1841 | |||
1842 | inta &= priv->inta_mask; | ||
1843 | priv->inta |= inta; | ||
1844 | |||
1845 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
1846 | if (likely(inta)) | ||
1847 | tasklet_schedule(&priv->irq_tasklet); | ||
1848 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { | ||
1849 | /* Allow interrupt if was disabled by this handler and | ||
1850 | * no tasklet was schedules, We should not enable interrupt, | ||
1851 | * tasklet will enable it. | ||
1852 | */ | ||
1853 | iwl_enable_interrupts(priv); | ||
1854 | } | ||
1855 | |||
1856 | spin_unlock(&priv->lock); | ||
1857 | return IRQ_HANDLED; | ||
1858 | |||
1859 | none: | ||
1860 | /* re-enable interrupts here since we don't have anything to service. | ||
1861 | * only Re-enable if disabled by irq. | ||
1862 | */ | ||
1863 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1864 | iwl_enable_interrupts(priv); | ||
1865 | |||
1866 | spin_unlock(&priv->lock); | ||
1867 | return IRQ_NONE; | ||
1868 | } | ||
1869 | EXPORT_SYMBOL(iwl_isr_ict); | ||
1870 | |||
1871 | |||
1872 | static irqreturn_t iwl_isr(int irq, void *data) | ||
1873 | { | ||
1874 | struct iwl_priv *priv = data; | ||
1875 | u32 inta, inta_mask; | ||
1876 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1877 | u32 inta_fh; | ||
1878 | #endif | ||
1879 | if (!priv) | ||
1880 | return IRQ_NONE; | ||
1881 | |||
1882 | spin_lock(&priv->lock); | ||
1883 | |||
1884 | /* Disable (but don't clear!) interrupts here to avoid | ||
1885 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
1886 | * If we have something to service, the tasklet will re-enable ints. | ||
1887 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
1888 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
1889 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1890 | |||
1891 | /* Discover which interrupts are active/pending */ | ||
1892 | inta = iwl_read32(priv, CSR_INT); | ||
1893 | |||
1894 | /* Ignore interrupt if there's nothing in NIC to service. | ||
1895 | * This may be due to IRQ shared with another device, | ||
1896 | * or due to sporadic interrupts thrown from our NIC. */ | ||
1897 | if (!inta) { | ||
1898 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
1899 | goto none; | ||
1900 | } | ||
1901 | |||
1902 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
1903 | /* Hardware disappeared. It might have already raised | ||
1904 | * an interrupt */ | ||
1905 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
1906 | goto unplugged; | ||
1907 | } | ||
1908 | |||
1909 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1910 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
1911 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
1912 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | ||
1913 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | ||
1914 | } | ||
1915 | #endif | ||
1916 | |||
1917 | priv->inta |= inta; | ||
1918 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
1919 | if (likely(inta)) | ||
1920 | tasklet_schedule(&priv->irq_tasklet); | ||
1921 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1922 | iwl_enable_interrupts(priv); | ||
1923 | |||
1924 | unplugged: | ||
1925 | spin_unlock(&priv->lock); | ||
1926 | return IRQ_HANDLED; | ||
1927 | |||
1928 | none: | ||
1929 | /* re-enable interrupts here since we don't have anything to service. */ | ||
1930 | /* only Re-enable if diabled by irq and no schedules tasklet. */ | ||
1931 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1932 | iwl_enable_interrupts(priv); | ||
1933 | |||
1934 | spin_unlock(&priv->lock); | ||
1935 | return IRQ_NONE; | ||
1936 | } | ||
1937 | |||
1938 | irqreturn_t iwl_isr_legacy(int irq, void *data) | 1665 | irqreturn_t iwl_isr_legacy(int irq, void *data) |
1939 | { | 1666 | { |
1940 | struct iwl_priv *priv = data; | 1667 | struct iwl_priv *priv = data; |