.. | .. |
---|
4 | 4 | * |
---|
5 | 5 | * GPL LICENSE SUMMARY |
---|
6 | 6 | * |
---|
7 | | - * Copyright (C) 2016 T-Platforms All Rights Reserved. |
---|
| 7 | + * Copyright (C) 2016-2018 T-Platforms JSC All Rights Reserved. |
---|
8 | 8 | * |
---|
9 | 9 | * This program is free software; you can redistribute it and/or modify it |
---|
10 | 10 | * under the terms and conditions of the GNU General Public License, |
---|
.. | .. |
---|
49 | 49 | #include <linux/init.h> |
---|
50 | 50 | #include <linux/interrupt.h> |
---|
51 | 51 | #include <linux/spinlock.h> |
---|
| 52 | +#include <linux/mutex.h> |
---|
52 | 53 | #include <linux/pci.h> |
---|
53 | 54 | #include <linux/aer.h> |
---|
54 | 55 | #include <linux/slab.h> |
---|
55 | 56 | #include <linux/list.h> |
---|
56 | 57 | #include <linux/debugfs.h> |
---|
| 58 | +#include <linux/hwmon.h> |
---|
| 59 | +#include <linux/hwmon-sysfs.h> |
---|
57 | 60 | #include <linux/ntb.h> |
---|
58 | 61 | |
---|
59 | 62 | #include "ntb_hw_idt.h" |
---|
.. | .. |
---|
355 | 358 | iowrite32((u32)reg, ndev->cfgspc + (ptrdiff_t)IDT_NT_GASAADDR); |
---|
356 | 359 | /* Put the new value of the register */ |
---|
357 | 360 | iowrite32(data, ndev->cfgspc + (ptrdiff_t)IDT_NT_GASADATA); |
---|
358 | | - /* Make sure the PCIe transactions are executed */ |
---|
359 | | - mmiowb(); |
---|
360 | 361 | /* Unlock GASA registers operations */ |
---|
361 | 362 | spin_unlock_irqrestore(&ndev->gasa_lock, irqflags); |
---|
362 | 363 | } |
---|
.. | .. |
---|
747 | 748 | spin_lock_irqsave(&ndev->mtbl_lock, irqflags); |
---|
748 | 749 | idt_nt_write(ndev, IDT_NT_NTMTBLADDR, ndev->part); |
---|
749 | 750 | idt_nt_write(ndev, IDT_NT_NTMTBLDATA, mtbldata); |
---|
750 | | - mmiowb(); |
---|
751 | 751 | spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); |
---|
752 | 752 | |
---|
753 | 753 | /* Notify the peers by setting and clearing the global signal bit */ |
---|
.. | .. |
---|
775 | 775 | spin_lock_irqsave(&ndev->mtbl_lock, irqflags); |
---|
776 | 776 | idt_nt_write(ndev, IDT_NT_NTMTBLADDR, ndev->part); |
---|
777 | 777 | idt_nt_write(ndev, IDT_NT_NTMTBLDATA, 0); |
---|
778 | | - mmiowb(); |
---|
779 | 778 | spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags); |
---|
780 | 779 | |
---|
781 | 780 | /* Notify the peers by setting and clearing the global signal bit */ |
---|
.. | .. |
---|
1320 | 1319 | idt_nt_write(ndev, bar->ltbase, (u32)addr); |
---|
1321 | 1320 | idt_nt_write(ndev, bar->utbase, (u32)(addr >> 32)); |
---|
1322 | 1321 | /* Set the custom BAR aperture limit */ |
---|
1323 | | - limit = pci_resource_start(ntb->pdev, mw_cfg->bar) + size; |
---|
| 1322 | + limit = pci_bus_address(ntb->pdev, mw_cfg->bar) + size; |
---|
1324 | 1323 | idt_nt_write(ndev, bar->limit, (u32)limit); |
---|
1325 | 1324 | if (IS_FLD_SET(BARSETUP_TYPE, data, 64)) |
---|
1326 | 1325 | idt_nt_write(ndev, (bar + 1)->limit, (limit >> 32)); |
---|
.. | .. |
---|
1336 | 1335 | idt_nt_write(ndev, IDT_NT_LUTLDATA, (u32)addr); |
---|
1337 | 1336 | idt_nt_write(ndev, IDT_NT_LUTMDATA, (u32)(addr >> 32)); |
---|
1338 | 1337 | idt_nt_write(ndev, IDT_NT_LUTUDATA, data); |
---|
1339 | | - mmiowb(); |
---|
1340 | 1338 | spin_unlock_irqrestore(&ndev->lut_lock, irqflags); |
---|
1341 | 1339 | /* Limit address isn't specified since size is fixed for LUT */ |
---|
1342 | 1340 | } |
---|
.. | .. |
---|
1390 | 1388 | idt_nt_write(ndev, IDT_NT_LUTLDATA, 0); |
---|
1391 | 1389 | idt_nt_write(ndev, IDT_NT_LUTMDATA, 0); |
---|
1392 | 1390 | idt_nt_write(ndev, IDT_NT_LUTUDATA, 0); |
---|
1393 | | - mmiowb(); |
---|
1394 | 1391 | spin_unlock_irqrestore(&ndev->lut_lock, irqflags); |
---|
1395 | 1392 | } |
---|
1396 | 1393 | |
---|
.. | .. |
---|
1809 | 1806 | /* Set the route and send the data */ |
---|
1810 | 1807 | idt_sw_write(ndev, partdata_tbl[ndev->part].msgctl[midx], swpmsgctl); |
---|
1811 | 1808 | idt_nt_write(ndev, ntdata_tbl.msgs[midx].out, msg); |
---|
1812 | | - mmiowb(); |
---|
1813 | 1809 | /* Unlock the messages routing table */ |
---|
1814 | 1810 | spin_unlock_irqrestore(&ndev->msg_locks[midx], irqflags); |
---|
1815 | 1811 | |
---|
.. | .. |
---|
1821 | 1817 | * 7. Temperature sensor operations |
---|
1822 | 1818 | * |
---|
1823 | 1819 | * IDT PCIe-switch has an embedded temperature sensor, which can be used to |
---|
1824 | | - * warn a user-space of possible chip overheating. Since workload temperature |
---|
1825 | | - * can be different on different platforms, temperature thresholds as well as |
---|
1826 | | - * general sensor settings must be setup in the framework of BIOS/EEPROM |
---|
1827 | | - * initializations. It includes the actual sensor enabling as well. |
---|
| 1820 | + * check current chip core temperature. Since a workload environment can be |
---|
| 1821 | + * different on different platforms, an offset and ADC/filter settings can be |
---|
| 1822 | + * specified. Although the offset configuration is only exposed to the sysfs |
---|
| 1823 | + * hwmon interface at the moment. The rest of the settings can be adjusted |
---|
| 1824 | + * for instance by the BIOS/EEPROM firmware. |
---|
1828 | 1825 | *============================================================================= |
---|
1829 | 1826 | */ |
---|
1830 | 1827 | |
---|
1831 | 1828 | /* |
---|
1832 | | - * idt_read_temp() - read temperature from chip sensor |
---|
1833 | | - * @ntb: NTB device context. |
---|
1834 | | - * @val: OUT - integer value of temperature |
---|
1835 | | - * @frac: OUT - fraction |
---|
| 1829 | + * idt_get_deg() - convert millidegree Celsius value to just degree |
---|
| 1830 | + * @mdegC: IN - millidegree Celsius value |
---|
| 1831 | + * |
---|
| 1832 | + * Return: Degree corresponding to the passed millidegree value |
---|
1836 | 1833 | */ |
---|
1837 | | -static void idt_read_temp(struct idt_ntb_dev *ndev, unsigned char *val, |
---|
1838 | | - unsigned char *frac) |
---|
| 1834 | +static inline s8 idt_get_deg(long mdegC) |
---|
1839 | 1835 | { |
---|
1840 | | - u32 data; |
---|
1841 | | - |
---|
1842 | | - /* Read the data from TEMP field of the TMPSTS register */ |
---|
1843 | | - data = idt_sw_read(ndev, IDT_SW_TMPSTS); |
---|
1844 | | - data = GET_FIELD(TMPSTS_TEMP, data); |
---|
1845 | | - /* TEMP field has one fractional bit and seven integer bits */ |
---|
1846 | | - *val = data >> 1; |
---|
1847 | | - *frac = ((data & 0x1) ? 5 : 0); |
---|
| 1836 | + return mdegC / 1000; |
---|
1848 | 1837 | } |
---|
1849 | 1838 | |
---|
1850 | 1839 | /* |
---|
1851 | | - * idt_temp_isr() - temperature sensor alarm events ISR |
---|
1852 | | - * @ndev: IDT NTB hardware driver descriptor |
---|
1853 | | - * @ntint_sts: NT-function interrupt status |
---|
| 1840 | + * idt_get_frac() - retrieve 0/0.5 fraction of the millidegree Celsius value |
---|
| 1841 | + * @mdegC: IN - millidegree Celsius value |
---|
1854 | 1842 | * |
---|
1855 | | - * It handles events of temperature crossing alarm thresholds. Since reading |
---|
1856 | | - * of TMPALARM register clears it up, the function doesn't analyze the |
---|
1857 | | - * read value, instead the current temperature value just warningly printed to |
---|
1858 | | - * log. |
---|
1859 | | - * The method is called from PCIe ISR bottom-half routine. |
---|
| 1843 | + * Return: 0/0.5 degree fraction of the passed millidegree value |
---|
1860 | 1844 | */ |
---|
1861 | | -static void idt_temp_isr(struct idt_ntb_dev *ndev, u32 ntint_sts) |
---|
| 1845 | +static inline u8 idt_get_deg_frac(long mdegC) |
---|
1862 | 1846 | { |
---|
1863 | | - unsigned char val, frac; |
---|
| 1847 | + return (mdegC % 1000) >= 500 ? 5 : 0; |
---|
| 1848 | +} |
---|
1864 | 1849 | |
---|
1865 | | - /* Read the current temperature value */ |
---|
1866 | | - idt_read_temp(ndev, &val, &frac); |
---|
| 1850 | +/* |
---|
| 1851 | + * idt_get_temp_fmt() - convert millidegree Celsius value to 0:7:1 format |
---|
| 1852 | + * @mdegC: IN - millidegree Celsius value |
---|
| 1853 | + * |
---|
| 1854 | + * Return: 0:7:1 format acceptable by the IDT temperature sensor |
---|
| 1855 | + */ |
---|
| 1856 | +static inline u8 idt_temp_get_fmt(long mdegC) |
---|
| 1857 | +{ |
---|
| 1858 | + return (idt_get_deg(mdegC) << 1) | (idt_get_deg_frac(mdegC) ? 1 : 0); |
---|
| 1859 | +} |
---|
1867 | 1860 | |
---|
1868 | | - /* Read the temperature alarm to clean the alarm status out */ |
---|
1869 | | - /*(void)idt_sw_read(ndev, IDT_SW_TMPALARM);*/ |
---|
| 1861 | +/* |
---|
| 1862 | + * idt_get_temp_sval() - convert temp sample to signed millidegree Celsius |
---|
| 1863 | + * @data: IN - shifted to LSB 8-bits temperature sample |
---|
| 1864 | + * |
---|
| 1865 | + * Return: signed millidegree Celsius |
---|
| 1866 | + */ |
---|
| 1867 | +static inline long idt_get_temp_sval(u32 data) |
---|
| 1868 | +{ |
---|
| 1869 | + return ((s8)data / 2) * 1000 + (data & 0x1 ? 500 : 0); |
---|
| 1870 | +} |
---|
1870 | 1871 | |
---|
1871 | | - /* Clean the corresponding interrupt bit */ |
---|
1872 | | - idt_nt_write(ndev, IDT_NT_NTINTSTS, IDT_NTINTSTS_TMPSENSOR); |
---|
| 1872 | +/* |
---|
| 1873 | + * idt_get_temp_sval() - convert temp sample to unsigned millidegree Celsius |
---|
| 1874 | + * @data: IN - shifted to LSB 8-bits temperature sample |
---|
| 1875 | + * |
---|
| 1876 | + * Return: unsigned millidegree Celsius |
---|
| 1877 | + */ |
---|
| 1878 | +static inline long idt_get_temp_uval(u32 data) |
---|
| 1879 | +{ |
---|
| 1880 | + return (data / 2) * 1000 + (data & 0x1 ? 500 : 0); |
---|
| 1881 | +} |
---|
1873 | 1882 | |
---|
1874 | | - dev_dbg(&ndev->ntb.pdev->dev, |
---|
1875 | | - "Temp sensor IRQ detected %#08x", ntint_sts); |
---|
| 1883 | +/* |
---|
| 1884 | + * idt_read_temp() - read temperature from chip sensor |
---|
| 1885 | + * @ntb: NTB device context. |
---|
| 1886 | + * @type: IN - type of the temperature value to read |
---|
| 1887 | + * @val: OUT - integer value of temperature in millidegree Celsius |
---|
| 1888 | + */ |
---|
| 1889 | +static void idt_read_temp(struct idt_ntb_dev *ndev, |
---|
| 1890 | + const enum idt_temp_val type, long *val) |
---|
| 1891 | +{ |
---|
| 1892 | + u32 data; |
---|
1876 | 1893 | |
---|
1877 | | - /* Print temperature value to log */ |
---|
1878 | | - dev_warn(&ndev->ntb.pdev->dev, "Temperature %hhu.%hhu", val, frac); |
---|
| 1894 | + /* Alter the temperature field in accordance with the passed type */ |
---|
| 1895 | + switch (type) { |
---|
| 1896 | + case IDT_TEMP_CUR: |
---|
| 1897 | + data = GET_FIELD(TMPSTS_TEMP, |
---|
| 1898 | + idt_sw_read(ndev, IDT_SW_TMPSTS)); |
---|
| 1899 | + break; |
---|
| 1900 | + case IDT_TEMP_LOW: |
---|
| 1901 | + data = GET_FIELD(TMPSTS_LTEMP, |
---|
| 1902 | + idt_sw_read(ndev, IDT_SW_TMPSTS)); |
---|
| 1903 | + break; |
---|
| 1904 | + case IDT_TEMP_HIGH: |
---|
| 1905 | + data = GET_FIELD(TMPSTS_HTEMP, |
---|
| 1906 | + idt_sw_read(ndev, IDT_SW_TMPSTS)); |
---|
| 1907 | + break; |
---|
| 1908 | + case IDT_TEMP_OFFSET: |
---|
| 1909 | + /* This is the only field with signed 0:7:1 format */ |
---|
| 1910 | + data = GET_FIELD(TMPADJ_OFFSET, |
---|
| 1911 | + idt_sw_read(ndev, IDT_SW_TMPADJ)); |
---|
| 1912 | + *val = idt_get_temp_sval(data); |
---|
| 1913 | + return; |
---|
| 1914 | + default: |
---|
| 1915 | + data = GET_FIELD(TMPSTS_TEMP, |
---|
| 1916 | + idt_sw_read(ndev, IDT_SW_TMPSTS)); |
---|
| 1917 | + break; |
---|
| 1918 | + } |
---|
| 1919 | + |
---|
| 1920 | + /* The rest of the fields accept unsigned 0:7:1 format */ |
---|
| 1921 | + *val = idt_get_temp_uval(data); |
---|
| 1922 | +} |
---|
| 1923 | + |
---|
| 1924 | +/* |
---|
| 1925 | + * idt_write_temp() - write temperature to the chip sensor register |
---|
| 1926 | + * @ntb: NTB device context. |
---|
| 1927 | + * @type: IN - type of the temperature value to change |
---|
| 1928 | + * @val: IN - integer value of temperature in millidegree Celsius |
---|
| 1929 | + */ |
---|
| 1930 | +static void idt_write_temp(struct idt_ntb_dev *ndev, |
---|
| 1931 | + const enum idt_temp_val type, const long val) |
---|
| 1932 | +{ |
---|
| 1933 | + unsigned int reg; |
---|
| 1934 | + u32 data; |
---|
| 1935 | + u8 fmt; |
---|
| 1936 | + |
---|
| 1937 | + /* Retrieve the properly formatted temperature value */ |
---|
| 1938 | + fmt = idt_temp_get_fmt(val); |
---|
| 1939 | + |
---|
| 1940 | + mutex_lock(&ndev->hwmon_mtx); |
---|
| 1941 | + switch (type) { |
---|
| 1942 | + case IDT_TEMP_LOW: |
---|
| 1943 | + reg = IDT_SW_TMPALARM; |
---|
| 1944 | + data = SET_FIELD(TMPALARM_LTEMP, idt_sw_read(ndev, reg), fmt) & |
---|
| 1945 | + ~IDT_TMPALARM_IRQ_MASK; |
---|
| 1946 | + break; |
---|
| 1947 | + case IDT_TEMP_HIGH: |
---|
| 1948 | + reg = IDT_SW_TMPALARM; |
---|
| 1949 | + data = SET_FIELD(TMPALARM_HTEMP, idt_sw_read(ndev, reg), fmt) & |
---|
| 1950 | + ~IDT_TMPALARM_IRQ_MASK; |
---|
| 1951 | + break; |
---|
| 1952 | + case IDT_TEMP_OFFSET: |
---|
| 1953 | + reg = IDT_SW_TMPADJ; |
---|
| 1954 | + data = SET_FIELD(TMPADJ_OFFSET, idt_sw_read(ndev, reg), fmt); |
---|
| 1955 | + break; |
---|
| 1956 | + default: |
---|
| 1957 | + goto inval_spin_unlock; |
---|
| 1958 | + } |
---|
| 1959 | + |
---|
| 1960 | + idt_sw_write(ndev, reg, data); |
---|
| 1961 | + |
---|
| 1962 | +inval_spin_unlock: |
---|
| 1963 | + mutex_unlock(&ndev->hwmon_mtx); |
---|
| 1964 | +} |
---|
| 1965 | + |
---|
| 1966 | +/* |
---|
| 1967 | + * idt_sysfs_show_temp() - printout corresponding temperature value |
---|
| 1968 | + * @dev: Pointer to the NTB device structure |
---|
| 1969 | + * @da: Sensor device attribute structure |
---|
| 1970 | + * @buf: Buffer to print temperature out |
---|
| 1971 | + * |
---|
| 1972 | + * Return: Number of written symbols or negative error |
---|
| 1973 | + */ |
---|
| 1974 | +static ssize_t idt_sysfs_show_temp(struct device *dev, |
---|
| 1975 | + struct device_attribute *da, char *buf) |
---|
| 1976 | +{ |
---|
| 1977 | + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
---|
| 1978 | + struct idt_ntb_dev *ndev = dev_get_drvdata(dev); |
---|
| 1979 | + enum idt_temp_val type = attr->index; |
---|
| 1980 | + long mdeg; |
---|
| 1981 | + |
---|
| 1982 | + idt_read_temp(ndev, type, &mdeg); |
---|
| 1983 | + return sprintf(buf, "%ld\n", mdeg); |
---|
| 1984 | +} |
---|
| 1985 | + |
---|
| 1986 | +/* |
---|
| 1987 | + * idt_sysfs_set_temp() - set corresponding temperature value |
---|
| 1988 | + * @dev: Pointer to the NTB device structure |
---|
| 1989 | + * @da: Sensor device attribute structure |
---|
| 1990 | + * @buf: Buffer to print temperature out |
---|
| 1991 | + * @count: Size of the passed buffer |
---|
| 1992 | + * |
---|
| 1993 | + * Return: Number of written symbols or negative error |
---|
| 1994 | + */ |
---|
| 1995 | +static ssize_t idt_sysfs_set_temp(struct device *dev, |
---|
| 1996 | + struct device_attribute *da, const char *buf, |
---|
| 1997 | + size_t count) |
---|
| 1998 | +{ |
---|
| 1999 | + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
---|
| 2000 | + struct idt_ntb_dev *ndev = dev_get_drvdata(dev); |
---|
| 2001 | + enum idt_temp_val type = attr->index; |
---|
| 2002 | + long mdeg; |
---|
| 2003 | + int ret; |
---|
| 2004 | + |
---|
| 2005 | + ret = kstrtol(buf, 10, &mdeg); |
---|
| 2006 | + if (ret) |
---|
| 2007 | + return ret; |
---|
| 2008 | + |
---|
| 2009 | + /* Clamp the passed value in accordance with the type */ |
---|
| 2010 | + if (type == IDT_TEMP_OFFSET) |
---|
| 2011 | + mdeg = clamp_val(mdeg, IDT_TEMP_MIN_OFFSET, |
---|
| 2012 | + IDT_TEMP_MAX_OFFSET); |
---|
| 2013 | + else |
---|
| 2014 | + mdeg = clamp_val(mdeg, IDT_TEMP_MIN_MDEG, IDT_TEMP_MAX_MDEG); |
---|
| 2015 | + |
---|
| 2016 | + idt_write_temp(ndev, type, mdeg); |
---|
| 2017 | + |
---|
| 2018 | + return count; |
---|
| 2019 | +} |
---|
| 2020 | + |
---|
| 2021 | +/* |
---|
| 2022 | + * idt_sysfs_reset_hist() - reset temperature history |
---|
| 2023 | + * @dev: Pointer to the NTB device structure |
---|
| 2024 | + * @da: Sensor device attribute structure |
---|
| 2025 | + * @buf: Buffer to print temperature out |
---|
| 2026 | + * @count: Size of the passed buffer |
---|
| 2027 | + * |
---|
| 2028 | + * Return: Number of written symbols or negative error |
---|
| 2029 | + */ |
---|
| 2030 | +static ssize_t idt_sysfs_reset_hist(struct device *dev, |
---|
| 2031 | + struct device_attribute *da, |
---|
| 2032 | + const char *buf, size_t count) |
---|
| 2033 | +{ |
---|
| 2034 | + struct idt_ntb_dev *ndev = dev_get_drvdata(dev); |
---|
| 2035 | + |
---|
| 2036 | + /* Just set the maximal value to the lowest temperature field and |
---|
| 2037 | + * minimal value to the highest temperature field |
---|
| 2038 | + */ |
---|
| 2039 | + idt_write_temp(ndev, IDT_TEMP_LOW, IDT_TEMP_MAX_MDEG); |
---|
| 2040 | + idt_write_temp(ndev, IDT_TEMP_HIGH, IDT_TEMP_MIN_MDEG); |
---|
| 2041 | + |
---|
| 2042 | + return count; |
---|
| 2043 | +} |
---|
| 2044 | + |
---|
| 2045 | +/* |
---|
| 2046 | + * Hwmon IDT sysfs attributes |
---|
| 2047 | + */ |
---|
| 2048 | +static SENSOR_DEVICE_ATTR(temp1_input, 0444, idt_sysfs_show_temp, NULL, |
---|
| 2049 | + IDT_TEMP_CUR); |
---|
| 2050 | +static SENSOR_DEVICE_ATTR(temp1_lowest, 0444, idt_sysfs_show_temp, NULL, |
---|
| 2051 | + IDT_TEMP_LOW); |
---|
| 2052 | +static SENSOR_DEVICE_ATTR(temp1_highest, 0444, idt_sysfs_show_temp, NULL, |
---|
| 2053 | + IDT_TEMP_HIGH); |
---|
| 2054 | +static SENSOR_DEVICE_ATTR(temp1_offset, 0644, idt_sysfs_show_temp, |
---|
| 2055 | + idt_sysfs_set_temp, IDT_TEMP_OFFSET); |
---|
| 2056 | +static DEVICE_ATTR(temp1_reset_history, 0200, NULL, idt_sysfs_reset_hist); |
---|
| 2057 | + |
---|
| 2058 | +/* |
---|
| 2059 | + * Hwmon IDT sysfs attributes group |
---|
| 2060 | + */ |
---|
| 2061 | +static struct attribute *idt_temp_attrs[] = { |
---|
| 2062 | + &sensor_dev_attr_temp1_input.dev_attr.attr, |
---|
| 2063 | + &sensor_dev_attr_temp1_lowest.dev_attr.attr, |
---|
| 2064 | + &sensor_dev_attr_temp1_highest.dev_attr.attr, |
---|
| 2065 | + &sensor_dev_attr_temp1_offset.dev_attr.attr, |
---|
| 2066 | + &dev_attr_temp1_reset_history.attr, |
---|
| 2067 | + NULL |
---|
| 2068 | +}; |
---|
| 2069 | +ATTRIBUTE_GROUPS(idt_temp); |
---|
| 2070 | + |
---|
| 2071 | +/* |
---|
| 2072 | + * idt_init_temp() - initialize temperature sensor interface |
---|
| 2073 | + * @ndev: IDT NTB hardware driver descriptor |
---|
| 2074 | + * |
---|
| 2075 | + * Simple sensor initializarion method is responsible for device switching |
---|
| 2076 | + * on and resource management based hwmon interface registration. Note, that |
---|
| 2077 | + * since the device is shared we won't disable it on remove, but leave it |
---|
| 2078 | + * working until the system is powered off. |
---|
| 2079 | + */ |
---|
| 2080 | +static void idt_init_temp(struct idt_ntb_dev *ndev) |
---|
| 2081 | +{ |
---|
| 2082 | + struct device *hwmon; |
---|
| 2083 | + |
---|
| 2084 | + /* Enable sensor if it hasn't been already */ |
---|
| 2085 | + idt_sw_write(ndev, IDT_SW_TMPCTL, 0x0); |
---|
| 2086 | + |
---|
| 2087 | + /* Initialize hwmon interface fields */ |
---|
| 2088 | + mutex_init(&ndev->hwmon_mtx); |
---|
| 2089 | + |
---|
| 2090 | + hwmon = devm_hwmon_device_register_with_groups(&ndev->ntb.pdev->dev, |
---|
| 2091 | + ndev->swcfg->name, ndev, idt_temp_groups); |
---|
| 2092 | + if (IS_ERR(hwmon)) { |
---|
| 2093 | + dev_err(&ndev->ntb.pdev->dev, "Couldn't create hwmon device"); |
---|
| 2094 | + return; |
---|
| 2095 | + } |
---|
| 2096 | + |
---|
| 2097 | + dev_dbg(&ndev->ntb.pdev->dev, "Temperature HWmon interface registered"); |
---|
1879 | 2098 | } |
---|
1880 | 2099 | |
---|
1881 | 2100 | /*============================================================================= |
---|
.. | .. |
---|
1931 | 2150 | goto err_free_vectors; |
---|
1932 | 2151 | } |
---|
1933 | 2152 | |
---|
1934 | | - /* Unmask Message/Doorbell/SE/Temperature interrupts */ |
---|
| 2153 | + /* Unmask Message/Doorbell/SE interrupts */ |
---|
1935 | 2154 | ntint_mask = idt_nt_read(ndev, IDT_NT_NTINTMSK) & ~IDT_NTINTMSK_ALL; |
---|
1936 | 2155 | idt_nt_write(ndev, IDT_NT_NTINTMSK, ntint_mask); |
---|
1937 | 2156 | |
---|
.. | .. |
---|
1945 | 2164 | |
---|
1946 | 2165 | return ret; |
---|
1947 | 2166 | } |
---|
1948 | | - |
---|
1949 | 2167 | |
---|
1950 | 2168 | /* |
---|
1951 | 2169 | * idt_deinit_ist() - deinitialize PCIe interrupt handler |
---|
.. | .. |
---|
2004 | 2222 | /* Handle switch event interrupts */ |
---|
2005 | 2223 | if (ntint_sts & IDT_NTINTSTS_SEVENT) { |
---|
2006 | 2224 | idt_se_isr(ndev, ntint_sts); |
---|
2007 | | - handled = true; |
---|
2008 | | - } |
---|
2009 | | - |
---|
2010 | | - /* Handle temperature sensor interrupt */ |
---|
2011 | | - if (ntint_sts & IDT_NTINTSTS_TMPSENSOR) { |
---|
2012 | | - idt_temp_isr(ndev, ntint_sts); |
---|
2013 | 2225 | handled = true; |
---|
2014 | 2226 | } |
---|
2015 | 2227 | |
---|
.. | .. |
---|
2123 | 2335 | size_t count, loff_t *offp) |
---|
2124 | 2336 | { |
---|
2125 | 2337 | struct idt_ntb_dev *ndev = filp->private_data; |
---|
2126 | | - unsigned char temp, frac, idx, pidx, cnt; |
---|
| 2338 | + unsigned char idx, pidx, cnt; |
---|
| 2339 | + unsigned long irqflags, mdeg; |
---|
2127 | 2340 | ssize_t ret = 0, off = 0; |
---|
2128 | | - unsigned long irqflags; |
---|
2129 | 2341 | enum ntb_speed speed; |
---|
2130 | 2342 | enum ntb_width width; |
---|
2131 | 2343 | char *strbuf; |
---|
.. | .. |
---|
2274 | 2486 | off += scnprintf(strbuf + off, size - off, "\n"); |
---|
2275 | 2487 | |
---|
2276 | 2488 | /* Current temperature */ |
---|
2277 | | - idt_read_temp(ndev, &temp, &frac); |
---|
| 2489 | + idt_read_temp(ndev, IDT_TEMP_CUR, &mdeg); |
---|
2278 | 2490 | off += scnprintf(strbuf + off, size - off, |
---|
2279 | | - "Switch temperature\t\t- %hhu.%hhuC\n", temp, frac); |
---|
| 2491 | + "Switch temperature\t\t- %hhd.%hhuC\n", |
---|
| 2492 | + idt_get_deg(mdeg), idt_get_deg_frac(mdeg)); |
---|
2280 | 2493 | |
---|
2281 | 2494 | /* Copy the buffer to the User Space */ |
---|
2282 | 2495 | ret = simple_read_from_buffer(ubuf, count, offp, strbuf, off); |
---|
.. | .. |
---|
2447 | 2660 | dev_warn(&pdev->dev, |
---|
2448 | 2661 | "Cannot set consistent DMA highmem bit mask\n"); |
---|
2449 | 2662 | } |
---|
2450 | | - ret = dma_coerce_mask_and_coherent(&ndev->ntb.dev, |
---|
2451 | | - dma_get_mask(&pdev->dev)); |
---|
2452 | | - if (ret != 0) { |
---|
2453 | | - dev_err(&pdev->dev, "Failed to set NTB device DMA bit mask\n"); |
---|
2454 | | - return ret; |
---|
2455 | | - } |
---|
2456 | 2663 | |
---|
2457 | 2664 | /* |
---|
2458 | 2665 | * Enable the device advanced error reporting. It's not critical to |
---|
.. | .. |
---|
2461 | 2668 | ret = pci_enable_pcie_error_reporting(pdev); |
---|
2462 | 2669 | if (ret != 0) |
---|
2463 | 2670 | dev_warn(&pdev->dev, "PCIe AER capability disabled\n"); |
---|
2464 | | - else /* Cleanup uncorrectable error status before getting to init */ |
---|
2465 | | - pci_cleanup_aer_uncorrect_error_status(pdev); |
---|
| 2671 | + else /* Cleanup nonfatal error status before getting to init */ |
---|
| 2672 | + pci_aer_clear_nonfatal_status(pdev); |
---|
2466 | 2673 | |
---|
2467 | 2674 | /* First enable the PCI device */ |
---|
2468 | 2675 | ret = pcim_enable_device(pdev); |
---|
.. | .. |
---|
2570 | 2777 | |
---|
2571 | 2778 | /* Initialize Messaging subsystem */ |
---|
2572 | 2779 | idt_init_msg(ndev); |
---|
| 2780 | + |
---|
| 2781 | + /* Initialize hwmon interface */ |
---|
| 2782 | + idt_init_temp(ndev); |
---|
2573 | 2783 | |
---|
2574 | 2784 | /* Initialize IDT interrupts handler */ |
---|
2575 | 2785 | ret = idt_init_isr(ndev); |
---|
.. | .. |
---|
2692 | 2902 | |
---|
2693 | 2903 | static int __init idt_pci_driver_init(void) |
---|
2694 | 2904 | { |
---|
| 2905 | + int ret; |
---|
2695 | 2906 | pr_info("%s %s\n", NTB_DESC, NTB_VER); |
---|
2696 | 2907 | |
---|
2697 | 2908 | /* Create the top DebugFS directory if the FS is initialized */ |
---|
.. | .. |
---|
2699 | 2910 | dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL); |
---|
2700 | 2911 | |
---|
2701 | 2912 | /* Register the NTB hardware driver to handle the PCI device */ |
---|
2702 | | - return pci_register_driver(&idt_pci_driver); |
---|
| 2913 | + ret = pci_register_driver(&idt_pci_driver); |
---|
| 2914 | + if (ret) |
---|
| 2915 | + debugfs_remove_recursive(dbgfs_topdir); |
---|
| 2916 | + |
---|
| 2917 | + return ret; |
---|
2703 | 2918 | } |
---|
2704 | 2919 | module_init(idt_pci_driver_init); |
---|
2705 | 2920 | |
---|