diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-04 11:12:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-04 11:12:44 -0500 |
commit | 04578e8441c5420259a71eff9fede535858bfc6a (patch) | |
tree | dddc3123bffdd48c872ed05af5cbad80368b4029 | |
parent | 71e56028173bc84f01456a5679d8be9d681b49f1 (diff) | |
parent | a662315d8ad9e687fe648b6eea9bd35017f565dd (diff) |
Merge tag 'ntb-4.20' of git://github.com/jonmason/ntb
Pull NTB updates from Jon Mason:
"Fairly minor changes and bug fixes:
NTB IDT thermal changes and hook into hwmon, ntb_netdev clean-up of
private struct, and a few bug fixes"
* tag 'ntb-4.20' of git://github.com/jonmason/ntb:
ntb: idt: Alter the driver info comments
ntb: idt: Discard temperature sensor IRQ handler
ntb: idt: Add basic hwmon sysfs interface
ntb: idt: Alter temperature read method
ntb_netdev: Simplify remove with client device drvdata
NTB: transport: Try harder to alloc an aligned MW buffer
ntb: ntb_transport: Mark expected switch fall-throughs
ntb: idt: Set PCIe bus address to BARLIMITx
NTB: ntb_hw_idt: replace IS_ERR_OR_NULL with regular NULL checks
ntb: intel: fix return value for ndev_vec_mask()
ntb_netdev: fix sleep time mismatch
-rw-r--r-- | drivers/net/ntb_netdev.c | 30 | ||||
-rw-r--r-- | drivers/ntb/hw/idt/Kconfig | 5 | ||||
-rw-r--r-- | drivers/ntb/hw/idt/ntb_hw_idt.c | 327 | ||||
-rw-r--r-- | drivers/ntb/hw/idt/ntb_hw_idt.h | 87 | ||||
-rw-r--r-- | drivers/ntb/hw/intel/ntb_hw_gen1.c | 2 | ||||
-rw-r--r-- | drivers/ntb/ntb_transport.c | 88 |
6 files changed, 429 insertions, 110 deletions
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index b12023bc2cab..a5bab614ff84 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c | |||
@@ -71,7 +71,6 @@ static unsigned int tx_start = 10; | |||
71 | static unsigned int tx_stop = 5; | 71 | static unsigned int tx_stop = 5; |
72 | 72 | ||
73 | struct ntb_netdev { | 73 | struct ntb_netdev { |
74 | struct list_head list; | ||
75 | struct pci_dev *pdev; | 74 | struct pci_dev *pdev; |
76 | struct net_device *ndev; | 75 | struct net_device *ndev; |
77 | struct ntb_transport_qp *qp; | 76 | struct ntb_transport_qp *qp; |
@@ -81,8 +80,6 @@ struct ntb_netdev { | |||
81 | #define NTB_TX_TIMEOUT_MS 1000 | 80 | #define NTB_TX_TIMEOUT_MS 1000 |
82 | #define NTB_RXQ_SIZE 100 | 81 | #define NTB_RXQ_SIZE 100 |
83 | 82 | ||
84 | static LIST_HEAD(dev_list); | ||
85 | |||
86 | static void ntb_netdev_event_handler(void *data, int link_is_up) | 83 | static void ntb_netdev_event_handler(void *data, int link_is_up) |
87 | { | 84 | { |
88 | struct net_device *ndev = data; | 85 | struct net_device *ndev = data; |
@@ -236,7 +233,7 @@ static void ntb_netdev_tx_timer(struct timer_list *t) | |||
236 | struct net_device *ndev = dev->ndev; | 233 | struct net_device *ndev = dev->ndev; |
237 | 234 | ||
238 | if (ntb_transport_tx_free_entry(dev->qp) < tx_stop) { | 235 | if (ntb_transport_tx_free_entry(dev->qp) < tx_stop) { |
239 | mod_timer(&dev->tx_timer, jiffies + msecs_to_jiffies(tx_time)); | 236 | mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time)); |
240 | } else { | 237 | } else { |
241 | /* Make sure anybody stopping the queue after this sees the new | 238 | /* Make sure anybody stopping the queue after this sees the new |
242 | * value of ntb_transport_tx_free_entry() | 239 | * value of ntb_transport_tx_free_entry() |
@@ -452,7 +449,7 @@ static int ntb_netdev_probe(struct device *client_dev) | |||
452 | if (rc) | 449 | if (rc) |
453 | goto err1; | 450 | goto err1; |
454 | 451 | ||
455 | list_add(&dev->list, &dev_list); | 452 | dev_set_drvdata(client_dev, ndev); |
456 | dev_info(&pdev->dev, "%s created\n", ndev->name); | 453 | dev_info(&pdev->dev, "%s created\n", ndev->name); |
457 | return 0; | 454 | return 0; |
458 | 455 | ||
@@ -465,27 +462,8 @@ err: | |||
465 | 462 | ||
466 | static void ntb_netdev_remove(struct device *client_dev) | 463 | static void ntb_netdev_remove(struct device *client_dev) |
467 | { | 464 | { |
468 | struct ntb_dev *ntb; | 465 | struct net_device *ndev = dev_get_drvdata(client_dev); |
469 | struct net_device *ndev; | 466 | struct ntb_netdev *dev = netdev_priv(ndev); |
470 | struct pci_dev *pdev; | ||
471 | struct ntb_netdev *dev; | ||
472 | bool found = false; | ||
473 | |||
474 | ntb = dev_ntb(client_dev->parent); | ||
475 | pdev = ntb->pdev; | ||
476 | |||
477 | list_for_each_entry(dev, &dev_list, list) { | ||
478 | if (dev->pdev == pdev) { | ||
479 | found = true; | ||
480 | break; | ||
481 | } | ||
482 | } | ||
483 | if (!found) | ||
484 | return; | ||
485 | |||
486 | list_del(&dev->list); | ||
487 | |||
488 | ndev = dev->ndev; | ||
489 | 467 | ||
490 | unregister_netdev(ndev); | 468 | unregister_netdev(ndev); |
491 | ntb_transport_free_queue(dev->qp); | 469 | ntb_transport_free_queue(dev->qp); |
diff --git a/drivers/ntb/hw/idt/Kconfig b/drivers/ntb/hw/idt/Kconfig index b360e5613b9f..f8948cf515ce 100644 --- a/drivers/ntb/hw/idt/Kconfig +++ b/drivers/ntb/hw/idt/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config NTB_IDT | 1 | config NTB_IDT |
2 | tristate "IDT PCIe-switch Non-Transparent Bridge support" | 2 | tristate "IDT PCIe-switch Non-Transparent Bridge support" |
3 | depends on PCI | 3 | depends on PCI |
4 | select HWMON | ||
4 | help | 5 | help |
5 | This driver supports NTB of cappable IDT PCIe-switches. | 6 | This driver supports NTB of cappable IDT PCIe-switches. |
6 | 7 | ||
@@ -23,9 +24,7 @@ config NTB_IDT | |||
23 | BAR settings of peer NT-functions, the BAR setups can't be done over | 24 | BAR settings of peer NT-functions, the BAR setups can't be done over |
24 | kernel PCI fixups. That's why the alternative pre-initialization | 25 | kernel PCI fixups. That's why the alternative pre-initialization |
25 | techniques like BIOS using SMBus interface or EEPROM should be | 26 | techniques like BIOS using SMBus interface or EEPROM should be |
26 | utilized. Additionally if one needs to have temperature sensor | 27 | utilized. |
27 | information printed to system log, the corresponding registers must | ||
28 | be initialized within BIOS/EEPROM as well. | ||
29 | 28 | ||
30 | If unsure, say N. | 29 | If unsure, say N. |
31 | 30 | ||
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index dbe72f116017..1dede87dd54f 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * GPL LICENSE SUMMARY | 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 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms and conditions of the GNU General Public License, | 10 | * under the terms and conditions of the GNU General Public License, |
@@ -49,11 +49,14 @@ | |||
49 | #include <linux/init.h> | 49 | #include <linux/init.h> |
50 | #include <linux/interrupt.h> | 50 | #include <linux/interrupt.h> |
51 | #include <linux/spinlock.h> | 51 | #include <linux/spinlock.h> |
52 | #include <linux/mutex.h> | ||
52 | #include <linux/pci.h> | 53 | #include <linux/pci.h> |
53 | #include <linux/aer.h> | 54 | #include <linux/aer.h> |
54 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
55 | #include <linux/list.h> | 56 | #include <linux/list.h> |
56 | #include <linux/debugfs.h> | 57 | #include <linux/debugfs.h> |
58 | #include <linux/hwmon.h> | ||
59 | #include <linux/hwmon-sysfs.h> | ||
57 | #include <linux/ntb.h> | 60 | #include <linux/ntb.h> |
58 | 61 | ||
59 | #include "ntb_hw_idt.h" | 62 | #include "ntb_hw_idt.h" |
@@ -1105,9 +1108,9 @@ static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, | |||
1105 | } | 1108 | } |
1106 | 1109 | ||
1107 | /* Allocate memory for memory window descriptors */ | 1110 | /* Allocate memory for memory window descriptors */ |
1108 | ret_mws = devm_kcalloc(&ndev->ntb.pdev->dev, *mw_cnt, | 1111 | ret_mws = devm_kcalloc(&ndev->ntb.pdev->dev, *mw_cnt, sizeof(*ret_mws), |
1109 | sizeof(*ret_mws), GFP_KERNEL); | 1112 | GFP_KERNEL); |
1110 | if (IS_ERR_OR_NULL(ret_mws)) | 1113 | if (!ret_mws) |
1111 | return ERR_PTR(-ENOMEM); | 1114 | return ERR_PTR(-ENOMEM); |
1112 | 1115 | ||
1113 | /* Copy the info of detected memory windows */ | 1116 | /* Copy the info of detected memory windows */ |
@@ -1320,7 +1323,7 @@ static int idt_ntb_peer_mw_set_trans(struct ntb_dev *ntb, int pidx, int widx, | |||
1320 | idt_nt_write(ndev, bar->ltbase, (u32)addr); | 1323 | idt_nt_write(ndev, bar->ltbase, (u32)addr); |
1321 | idt_nt_write(ndev, bar->utbase, (u32)(addr >> 32)); | 1324 | idt_nt_write(ndev, bar->utbase, (u32)(addr >> 32)); |
1322 | /* Set the custom BAR aperture limit */ | 1325 | /* Set the custom BAR aperture limit */ |
1323 | limit = pci_resource_start(ntb->pdev, mw_cfg->bar) + size; | 1326 | limit = pci_bus_address(ntb->pdev, mw_cfg->bar) + size; |
1324 | idt_nt_write(ndev, bar->limit, (u32)limit); | 1327 | idt_nt_write(ndev, bar->limit, (u32)limit); |
1325 | if (IS_FLD_SET(BARSETUP_TYPE, data, 64)) | 1328 | if (IS_FLD_SET(BARSETUP_TYPE, data, 64)) |
1326 | idt_nt_write(ndev, (bar + 1)->limit, (limit >> 32)); | 1329 | idt_nt_write(ndev, (bar + 1)->limit, (limit >> 32)); |
@@ -1821,61 +1824,284 @@ static int idt_ntb_peer_msg_write(struct ntb_dev *ntb, int pidx, int midx, | |||
1821 | * 7. Temperature sensor operations | 1824 | * 7. Temperature sensor operations |
1822 | * | 1825 | * |
1823 | * IDT PCIe-switch has an embedded temperature sensor, which can be used to | 1826 | * 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 | 1827 | * check current chip core temperature. Since a workload environment can be |
1825 | * can be different on different platforms, temperature thresholds as well as | 1828 | * different on different platforms, an offset and ADC/filter settings can be |
1826 | * general sensor settings must be setup in the framework of BIOS/EEPROM | 1829 | * specified. Although the offset configuration is only exposed to the sysfs |
1827 | * initializations. It includes the actual sensor enabling as well. | 1830 | * hwmon interface at the moment. The rest of the settings can be adjusted |
1831 | * for instance by the BIOS/EEPROM firmware. | ||
1828 | *============================================================================= | 1832 | *============================================================================= |
1829 | */ | 1833 | */ |
1830 | 1834 | ||
1831 | /* | 1835 | /* |
1836 | * idt_get_deg() - convert millidegree Celsius value to just degree | ||
1837 | * @mdegC: IN - millidegree Celsius value | ||
1838 | * | ||
1839 | * Return: Degree corresponding to the passed millidegree value | ||
1840 | */ | ||
1841 | static inline s8 idt_get_deg(long mdegC) | ||
1842 | { | ||
1843 | return mdegC / 1000; | ||
1844 | } | ||
1845 | |||
1846 | /* | ||
1847 | * idt_get_frac() - retrieve 0/0.5 fraction of the millidegree Celsius value | ||
1848 | * @mdegC: IN - millidegree Celsius value | ||
1849 | * | ||
1850 | * Return: 0/0.5 degree fraction of the passed millidegree value | ||
1851 | */ | ||
1852 | static inline u8 idt_get_deg_frac(long mdegC) | ||
1853 | { | ||
1854 | return (mdegC % 1000) >= 500 ? 5 : 0; | ||
1855 | } | ||
1856 | |||
1857 | /* | ||
1858 | * idt_get_temp_fmt() - convert millidegree Celsius value to 0:7:1 format | ||
1859 | * @mdegC: IN - millidegree Celsius value | ||
1860 | * | ||
1861 | * Return: 0:7:1 format acceptable by the IDT temperature sensor | ||
1862 | */ | ||
1863 | static inline u8 idt_temp_get_fmt(long mdegC) | ||
1864 | { | ||
1865 | return (idt_get_deg(mdegC) << 1) | (idt_get_deg_frac(mdegC) ? 1 : 0); | ||
1866 | } | ||
1867 | |||
1868 | /* | ||
1869 | * idt_get_temp_sval() - convert temp sample to signed millidegree Celsius | ||
1870 | * @data: IN - shifted to LSB 8-bits temperature sample | ||
1871 | * | ||
1872 | * Return: signed millidegree Celsius | ||
1873 | */ | ||
1874 | static inline long idt_get_temp_sval(u32 data) | ||
1875 | { | ||
1876 | return ((s8)data / 2) * 1000 + (data & 0x1 ? 500 : 0); | ||
1877 | } | ||
1878 | |||
1879 | /* | ||
1880 | * idt_get_temp_sval() - convert temp sample to unsigned millidegree Celsius | ||
1881 | * @data: IN - shifted to LSB 8-bits temperature sample | ||
1882 | * | ||
1883 | * Return: unsigned millidegree Celsius | ||
1884 | */ | ||
1885 | static inline long idt_get_temp_uval(u32 data) | ||
1886 | { | ||
1887 | return (data / 2) * 1000 + (data & 0x1 ? 500 : 0); | ||
1888 | } | ||
1889 | |||
1890 | /* | ||
1832 | * idt_read_temp() - read temperature from chip sensor | 1891 | * idt_read_temp() - read temperature from chip sensor |
1833 | * @ntb: NTB device context. | 1892 | * @ntb: NTB device context. |
1834 | * @val: OUT - integer value of temperature | 1893 | * @type: IN - type of the temperature value to read |
1835 | * @frac: OUT - fraction | 1894 | * @val: OUT - integer value of temperature in millidegree Celsius |
1836 | */ | 1895 | */ |
1837 | static void idt_read_temp(struct idt_ntb_dev *ndev, unsigned char *val, | 1896 | static void idt_read_temp(struct idt_ntb_dev *ndev, |
1838 | unsigned char *frac) | 1897 | const enum idt_temp_val type, long *val) |
1839 | { | 1898 | { |
1840 | u32 data; | 1899 | u32 data; |
1841 | 1900 | ||
1842 | /* Read the data from TEMP field of the TMPSTS register */ | 1901 | /* Alter the temperature field in accordance with the passed type */ |
1843 | data = idt_sw_read(ndev, IDT_SW_TMPSTS); | 1902 | switch (type) { |
1844 | data = GET_FIELD(TMPSTS_TEMP, data); | 1903 | case IDT_TEMP_CUR: |
1845 | /* TEMP field has one fractional bit and seven integer bits */ | 1904 | data = GET_FIELD(TMPSTS_TEMP, |
1846 | *val = data >> 1; | 1905 | idt_sw_read(ndev, IDT_SW_TMPSTS)); |
1847 | *frac = ((data & 0x1) ? 5 : 0); | 1906 | break; |
1907 | case IDT_TEMP_LOW: | ||
1908 | data = GET_FIELD(TMPSTS_LTEMP, | ||
1909 | idt_sw_read(ndev, IDT_SW_TMPSTS)); | ||
1910 | break; | ||
1911 | case IDT_TEMP_HIGH: | ||
1912 | data = GET_FIELD(TMPSTS_HTEMP, | ||
1913 | idt_sw_read(ndev, IDT_SW_TMPSTS)); | ||
1914 | break; | ||
1915 | case IDT_TEMP_OFFSET: | ||
1916 | /* This is the only field with signed 0:7:1 format */ | ||
1917 | data = GET_FIELD(TMPADJ_OFFSET, | ||
1918 | idt_sw_read(ndev, IDT_SW_TMPADJ)); | ||
1919 | *val = idt_get_temp_sval(data); | ||
1920 | return; | ||
1921 | default: | ||
1922 | data = GET_FIELD(TMPSTS_TEMP, | ||
1923 | idt_sw_read(ndev, IDT_SW_TMPSTS)); | ||
1924 | break; | ||
1925 | } | ||
1926 | |||
1927 | /* The rest of the fields accept unsigned 0:7:1 format */ | ||
1928 | *val = idt_get_temp_uval(data); | ||
1848 | } | 1929 | } |
1849 | 1930 | ||
1850 | /* | 1931 | /* |
1851 | * idt_temp_isr() - temperature sensor alarm events ISR | 1932 | * idt_write_temp() - write temperature to the chip sensor register |
1852 | * @ndev: IDT NTB hardware driver descriptor | 1933 | * @ntb: NTB device context. |
1853 | * @ntint_sts: NT-function interrupt status | 1934 | * @type: IN - type of the temperature value to change |
1935 | * @val: IN - integer value of temperature in millidegree Celsius | ||
1936 | */ | ||
1937 | static void idt_write_temp(struct idt_ntb_dev *ndev, | ||
1938 | const enum idt_temp_val type, const long val) | ||
1939 | { | ||
1940 | unsigned int reg; | ||
1941 | u32 data; | ||
1942 | u8 fmt; | ||
1943 | |||
1944 | /* Retrieve the properly formatted temperature value */ | ||
1945 | fmt = idt_temp_get_fmt(val); | ||
1946 | |||
1947 | mutex_lock(&ndev->hwmon_mtx); | ||
1948 | switch (type) { | ||
1949 | case IDT_TEMP_LOW: | ||
1950 | reg = IDT_SW_TMPALARM; | ||
1951 | data = SET_FIELD(TMPALARM_LTEMP, idt_sw_read(ndev, reg), fmt) & | ||
1952 | ~IDT_TMPALARM_IRQ_MASK; | ||
1953 | break; | ||
1954 | case IDT_TEMP_HIGH: | ||
1955 | reg = IDT_SW_TMPALARM; | ||
1956 | data = SET_FIELD(TMPALARM_HTEMP, idt_sw_read(ndev, reg), fmt) & | ||
1957 | ~IDT_TMPALARM_IRQ_MASK; | ||
1958 | break; | ||
1959 | case IDT_TEMP_OFFSET: | ||
1960 | reg = IDT_SW_TMPADJ; | ||
1961 | data = SET_FIELD(TMPADJ_OFFSET, idt_sw_read(ndev, reg), fmt); | ||
1962 | break; | ||
1963 | default: | ||
1964 | goto inval_spin_unlock; | ||
1965 | } | ||
1966 | |||
1967 | idt_sw_write(ndev, reg, data); | ||
1968 | |||
1969 | inval_spin_unlock: | ||
1970 | mutex_unlock(&ndev->hwmon_mtx); | ||
1971 | } | ||
1972 | |||
1973 | /* | ||
1974 | * idt_sysfs_show_temp() - printout corresponding temperature value | ||
1975 | * @dev: Pointer to the NTB device structure | ||
1976 | * @da: Sensor device attribute structure | ||
1977 | * @buf: Buffer to print temperature out | ||
1854 | * | 1978 | * |
1855 | * It handles events of temperature crossing alarm thresholds. Since reading | 1979 | * Return: Number of written symbols or negative error |
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. | ||
1860 | */ | 1980 | */ |
1861 | static void idt_temp_isr(struct idt_ntb_dev *ndev, u32 ntint_sts) | 1981 | static ssize_t idt_sysfs_show_temp(struct device *dev, |
1982 | struct device_attribute *da, char *buf) | ||
1862 | { | 1983 | { |
1863 | unsigned char val, frac; | 1984 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
1985 | struct idt_ntb_dev *ndev = dev_get_drvdata(dev); | ||
1986 | enum idt_temp_val type = attr->index; | ||
1987 | long mdeg; | ||
1864 | 1988 | ||
1865 | /* Read the current temperature value */ | 1989 | idt_read_temp(ndev, type, &mdeg); |
1866 | idt_read_temp(ndev, &val, &frac); | 1990 | return sprintf(buf, "%ld\n", mdeg); |
1991 | } | ||
1867 | 1992 | ||
1868 | /* Read the temperature alarm to clean the alarm status out */ | 1993 | /* |
1869 | /*(void)idt_sw_read(ndev, IDT_SW_TMPALARM);*/ | 1994 | * idt_sysfs_set_temp() - set corresponding temperature value |
1995 | * @dev: Pointer to the NTB device structure | ||
1996 | * @da: Sensor device attribute structure | ||
1997 | * @buf: Buffer to print temperature out | ||
1998 | * @count: Size of the passed buffer | ||
1999 | * | ||
2000 | * Return: Number of written symbols or negative error | ||
2001 | */ | ||
2002 | static ssize_t idt_sysfs_set_temp(struct device *dev, | ||
2003 | struct device_attribute *da, const char *buf, | ||
2004 | size_t count) | ||
2005 | { | ||
2006 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
2007 | struct idt_ntb_dev *ndev = dev_get_drvdata(dev); | ||
2008 | enum idt_temp_val type = attr->index; | ||
2009 | long mdeg; | ||
2010 | int ret; | ||
1870 | 2011 | ||
1871 | /* Clean the corresponding interrupt bit */ | 2012 | ret = kstrtol(buf, 10, &mdeg); |
1872 | idt_nt_write(ndev, IDT_NT_NTINTSTS, IDT_NTINTSTS_TMPSENSOR); | 2013 | if (ret) |
2014 | return ret; | ||
2015 | |||
2016 | /* Clamp the passed value in accordance with the type */ | ||
2017 | if (type == IDT_TEMP_OFFSET) | ||
2018 | mdeg = clamp_val(mdeg, IDT_TEMP_MIN_OFFSET, | ||
2019 | IDT_TEMP_MAX_OFFSET); | ||
2020 | else | ||
2021 | mdeg = clamp_val(mdeg, IDT_TEMP_MIN_MDEG, IDT_TEMP_MAX_MDEG); | ||
2022 | |||
2023 | idt_write_temp(ndev, type, mdeg); | ||
2024 | |||
2025 | return count; | ||
2026 | } | ||
2027 | |||
2028 | /* | ||
2029 | * idt_sysfs_reset_hist() - reset temperature history | ||
2030 | * @dev: Pointer to the NTB device structure | ||
2031 | * @da: Sensor device attribute structure | ||
2032 | * @buf: Buffer to print temperature out | ||
2033 | * @count: Size of the passed buffer | ||
2034 | * | ||
2035 | * Return: Number of written symbols or negative error | ||
2036 | */ | ||
2037 | static ssize_t idt_sysfs_reset_hist(struct device *dev, | ||
2038 | struct device_attribute *da, | ||
2039 | const char *buf, size_t count) | ||
2040 | { | ||
2041 | struct idt_ntb_dev *ndev = dev_get_drvdata(dev); | ||
2042 | |||
2043 | /* Just set the maximal value to the lowest temperature field and | ||
2044 | * minimal value to the highest temperature field | ||
2045 | */ | ||
2046 | idt_write_temp(ndev, IDT_TEMP_LOW, IDT_TEMP_MAX_MDEG); | ||
2047 | idt_write_temp(ndev, IDT_TEMP_HIGH, IDT_TEMP_MIN_MDEG); | ||
1873 | 2048 | ||
1874 | dev_dbg(&ndev->ntb.pdev->dev, | 2049 | return count; |
1875 | "Temp sensor IRQ detected %#08x", ntint_sts); | 2050 | } |
2051 | |||
2052 | /* | ||
2053 | * Hwmon IDT sysfs attributes | ||
2054 | */ | ||
2055 | static SENSOR_DEVICE_ATTR(temp1_input, 0444, idt_sysfs_show_temp, NULL, | ||
2056 | IDT_TEMP_CUR); | ||
2057 | static SENSOR_DEVICE_ATTR(temp1_lowest, 0444, idt_sysfs_show_temp, NULL, | ||
2058 | IDT_TEMP_LOW); | ||
2059 | static SENSOR_DEVICE_ATTR(temp1_highest, 0444, idt_sysfs_show_temp, NULL, | ||
2060 | IDT_TEMP_HIGH); | ||
2061 | static SENSOR_DEVICE_ATTR(temp1_offset, 0644, idt_sysfs_show_temp, | ||
2062 | idt_sysfs_set_temp, IDT_TEMP_OFFSET); | ||
2063 | static DEVICE_ATTR(temp1_reset_history, 0200, NULL, idt_sysfs_reset_hist); | ||
1876 | 2064 | ||
1877 | /* Print temperature value to log */ | 2065 | /* |
1878 | dev_warn(&ndev->ntb.pdev->dev, "Temperature %hhu.%hhu", val, frac); | 2066 | * Hwmon IDT sysfs attributes group |
2067 | */ | ||
2068 | static struct attribute *idt_temp_attrs[] = { | ||
2069 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
2070 | &sensor_dev_attr_temp1_lowest.dev_attr.attr, | ||
2071 | &sensor_dev_attr_temp1_highest.dev_attr.attr, | ||
2072 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | ||
2073 | &dev_attr_temp1_reset_history.attr, | ||
2074 | NULL | ||
2075 | }; | ||
2076 | ATTRIBUTE_GROUPS(idt_temp); | ||
2077 | |||
2078 | /* | ||
2079 | * idt_init_temp() - initialize temperature sensor interface | ||
2080 | * @ndev: IDT NTB hardware driver descriptor | ||
2081 | * | ||
2082 | * Simple sensor initializarion method is responsible for device switching | ||
2083 | * on and resource management based hwmon interface registration. Note, that | ||
2084 | * since the device is shared we won't disable it on remove, but leave it | ||
2085 | * working until the system is powered off. | ||
2086 | */ | ||
2087 | static void idt_init_temp(struct idt_ntb_dev *ndev) | ||
2088 | { | ||
2089 | struct device *hwmon; | ||
2090 | |||
2091 | /* Enable sensor if it hasn't been already */ | ||
2092 | idt_sw_write(ndev, IDT_SW_TMPCTL, 0x0); | ||
2093 | |||
2094 | /* Initialize hwmon interface fields */ | ||
2095 | mutex_init(&ndev->hwmon_mtx); | ||
2096 | |||
2097 | hwmon = devm_hwmon_device_register_with_groups(&ndev->ntb.pdev->dev, | ||
2098 | ndev->swcfg->name, ndev, idt_temp_groups); | ||
2099 | if (IS_ERR(hwmon)) { | ||
2100 | dev_err(&ndev->ntb.pdev->dev, "Couldn't create hwmon device"); | ||
2101 | return; | ||
2102 | } | ||
2103 | |||
2104 | dev_dbg(&ndev->ntb.pdev->dev, "Temperature HWmon interface registered"); | ||
1879 | } | 2105 | } |
1880 | 2106 | ||
1881 | /*============================================================================= | 2107 | /*============================================================================= |
@@ -1931,7 +2157,7 @@ static int idt_init_isr(struct idt_ntb_dev *ndev) | |||
1931 | goto err_free_vectors; | 2157 | goto err_free_vectors; |
1932 | } | 2158 | } |
1933 | 2159 | ||
1934 | /* Unmask Message/Doorbell/SE/Temperature interrupts */ | 2160 | /* Unmask Message/Doorbell/SE interrupts */ |
1935 | ntint_mask = idt_nt_read(ndev, IDT_NT_NTINTMSK) & ~IDT_NTINTMSK_ALL; | 2161 | ntint_mask = idt_nt_read(ndev, IDT_NT_NTINTMSK) & ~IDT_NTINTMSK_ALL; |
1936 | idt_nt_write(ndev, IDT_NT_NTINTMSK, ntint_mask); | 2162 | idt_nt_write(ndev, IDT_NT_NTINTMSK, ntint_mask); |
1937 | 2163 | ||
@@ -1946,7 +2172,6 @@ err_free_vectors: | |||
1946 | return ret; | 2172 | return ret; |
1947 | } | 2173 | } |
1948 | 2174 | ||
1949 | |||
1950 | /* | 2175 | /* |
1951 | * idt_deinit_ist() - deinitialize PCIe interrupt handler | 2176 | * idt_deinit_ist() - deinitialize PCIe interrupt handler |
1952 | * @ndev: IDT NTB hardware driver descriptor | 2177 | * @ndev: IDT NTB hardware driver descriptor |
@@ -2007,12 +2232,6 @@ static irqreturn_t idt_thread_isr(int irq, void *devid) | |||
2007 | handled = true; | 2232 | handled = true; |
2008 | } | 2233 | } |
2009 | 2234 | ||
2010 | /* Handle temperature sensor interrupt */ | ||
2011 | if (ntint_sts & IDT_NTINTSTS_TMPSENSOR) { | ||
2012 | idt_temp_isr(ndev, ntint_sts); | ||
2013 | handled = true; | ||
2014 | } | ||
2015 | |||
2016 | dev_dbg(&ndev->ntb.pdev->dev, "IDT IRQs 0x%08x handled", ntint_sts); | 2235 | dev_dbg(&ndev->ntb.pdev->dev, "IDT IRQs 0x%08x handled", ntint_sts); |
2017 | 2236 | ||
2018 | return handled ? IRQ_HANDLED : IRQ_NONE; | 2237 | return handled ? IRQ_HANDLED : IRQ_NONE; |
@@ -2123,9 +2342,9 @@ static ssize_t idt_dbgfs_info_read(struct file *filp, char __user *ubuf, | |||
2123 | size_t count, loff_t *offp) | 2342 | size_t count, loff_t *offp) |
2124 | { | 2343 | { |
2125 | struct idt_ntb_dev *ndev = filp->private_data; | 2344 | struct idt_ntb_dev *ndev = filp->private_data; |
2126 | unsigned char temp, frac, idx, pidx, cnt; | 2345 | unsigned char idx, pidx, cnt; |
2346 | unsigned long irqflags, mdeg; | ||
2127 | ssize_t ret = 0, off = 0; | 2347 | ssize_t ret = 0, off = 0; |
2128 | unsigned long irqflags; | ||
2129 | enum ntb_speed speed; | 2348 | enum ntb_speed speed; |
2130 | enum ntb_width width; | 2349 | enum ntb_width width; |
2131 | char *strbuf; | 2350 | char *strbuf; |
@@ -2274,9 +2493,10 @@ static ssize_t idt_dbgfs_info_read(struct file *filp, char __user *ubuf, | |||
2274 | off += scnprintf(strbuf + off, size - off, "\n"); | 2493 | off += scnprintf(strbuf + off, size - off, "\n"); |
2275 | 2494 | ||
2276 | /* Current temperature */ | 2495 | /* Current temperature */ |
2277 | idt_read_temp(ndev, &temp, &frac); | 2496 | idt_read_temp(ndev, IDT_TEMP_CUR, &mdeg); |
2278 | off += scnprintf(strbuf + off, size - off, | 2497 | off += scnprintf(strbuf + off, size - off, |
2279 | "Switch temperature\t\t- %hhu.%hhuC\n", temp, frac); | 2498 | "Switch temperature\t\t- %hhd.%hhuC\n", |
2499 | idt_get_deg(mdeg), idt_get_deg_frac(mdeg)); | ||
2280 | 2500 | ||
2281 | /* Copy the buffer to the User Space */ | 2501 | /* Copy the buffer to the User Space */ |
2282 | ret = simple_read_from_buffer(ubuf, count, offp, strbuf, off); | 2502 | ret = simple_read_from_buffer(ubuf, count, offp, strbuf, off); |
@@ -2390,7 +2610,7 @@ static struct idt_ntb_dev *idt_create_dev(struct pci_dev *pdev, | |||
2390 | 2610 | ||
2391 | /* Allocate memory for the IDT PCIe-device descriptor */ | 2611 | /* Allocate memory for the IDT PCIe-device descriptor */ |
2392 | ndev = devm_kzalloc(&pdev->dev, sizeof(*ndev), GFP_KERNEL); | 2612 | ndev = devm_kzalloc(&pdev->dev, sizeof(*ndev), GFP_KERNEL); |
2393 | if (IS_ERR_OR_NULL(ndev)) { | 2613 | if (!ndev) { |
2394 | dev_err(&pdev->dev, "Memory allocation failed for descriptor"); | 2614 | dev_err(&pdev->dev, "Memory allocation failed for descriptor"); |
2395 | return ERR_PTR(-ENOMEM); | 2615 | return ERR_PTR(-ENOMEM); |
2396 | } | 2616 | } |
@@ -2571,6 +2791,9 @@ static int idt_pci_probe(struct pci_dev *pdev, | |||
2571 | /* Initialize Messaging subsystem */ | 2791 | /* Initialize Messaging subsystem */ |
2572 | idt_init_msg(ndev); | 2792 | idt_init_msg(ndev); |
2573 | 2793 | ||
2794 | /* Initialize hwmon interface */ | ||
2795 | idt_init_temp(ndev); | ||
2796 | |||
2574 | /* Initialize IDT interrupts handler */ | 2797 | /* Initialize IDT interrupts handler */ |
2575 | ret = idt_init_isr(ndev); | 2798 | ret = idt_init_isr(ndev); |
2576 | if (ret != 0) | 2799 | if (ret != 0) |
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.h b/drivers/ntb/hw/idt/ntb_hw_idt.h index 856fd182f6f4..2f1aa121b0cf 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.h +++ b/drivers/ntb/hw/idt/ntb_hw_idt.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * GPL LICENSE SUMMARY | 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 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms and conditions of the GNU General Public License, | 10 | * under the terms and conditions of the GNU General Public License, |
@@ -47,9 +47,9 @@ | |||
47 | #include <linux/pci_ids.h> | 47 | #include <linux/pci_ids.h> |
48 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
49 | #include <linux/spinlock.h> | 49 | #include <linux/spinlock.h> |
50 | #include <linux/mutex.h> | ||
50 | #include <linux/ntb.h> | 51 | #include <linux/ntb.h> |
51 | 52 | ||
52 | |||
53 | /* | 53 | /* |
54 | * Macro is used to create the struct pci_device_id that matches | 54 | * Macro is used to create the struct pci_device_id that matches |
55 | * the supported IDT PCIe-switches | 55 | * the supported IDT PCIe-switches |
@@ -688,15 +688,14 @@ | |||
688 | * @IDT_NTINTMSK_DBELL: Doorbell interrupt mask bit | 688 | * @IDT_NTINTMSK_DBELL: Doorbell interrupt mask bit |
689 | * @IDT_NTINTMSK_SEVENT: Switch Event interrupt mask bit | 689 | * @IDT_NTINTMSK_SEVENT: Switch Event interrupt mask bit |
690 | * @IDT_NTINTMSK_TMPSENSOR: Temperature sensor interrupt mask bit | 690 | * @IDT_NTINTMSK_TMPSENSOR: Temperature sensor interrupt mask bit |
691 | * @IDT_NTINTMSK_ALL: All the useful interrupts mask | 691 | * @IDT_NTINTMSK_ALL: NTB-related interrupts mask |
692 | */ | 692 | */ |
693 | #define IDT_NTINTMSK_MSG 0x00000001U | 693 | #define IDT_NTINTMSK_MSG 0x00000001U |
694 | #define IDT_NTINTMSK_DBELL 0x00000002U | 694 | #define IDT_NTINTMSK_DBELL 0x00000002U |
695 | #define IDT_NTINTMSK_SEVENT 0x00000008U | 695 | #define IDT_NTINTMSK_SEVENT 0x00000008U |
696 | #define IDT_NTINTMSK_TMPSENSOR 0x00000080U | 696 | #define IDT_NTINTMSK_TMPSENSOR 0x00000080U |
697 | #define IDT_NTINTMSK_ALL \ | 697 | #define IDT_NTINTMSK_ALL \ |
698 | (IDT_NTINTMSK_MSG | IDT_NTINTMSK_DBELL | \ | 698 | (IDT_NTINTMSK_MSG | IDT_NTINTMSK_DBELL | IDT_NTINTMSK_SEVENT) |
699 | IDT_NTINTMSK_SEVENT | IDT_NTINTMSK_TMPSENSOR) | ||
700 | 699 | ||
701 | /* | 700 | /* |
702 | * NTGSIGNAL register fields related constants | 701 | * NTGSIGNAL register fields related constants |
@@ -886,12 +885,60 @@ | |||
886 | #define IDT_SWPxMSGCTL_PART_FLD 4 | 885 | #define IDT_SWPxMSGCTL_PART_FLD 4 |
887 | 886 | ||
888 | /* | 887 | /* |
888 | * TMPCTL register fields related constants | ||
889 | * @IDT_TMPCTL_LTH_MASK: Low temperature threshold field mask | ||
890 | * @IDT_TMPCTL_LTH_FLD: Low temperature threshold field offset | ||
891 | * @IDT_TMPCTL_MTH_MASK: Middle temperature threshold field mask | ||
892 | * @IDT_TMPCTL_MTH_FLD: Middle temperature threshold field offset | ||
893 | * @IDT_TMPCTL_HTH_MASK: High temperature threshold field mask | ||
894 | * @IDT_TMPCTL_HTH_FLD: High temperature threshold field offset | ||
895 | * @IDT_TMPCTL_PDOWN: Temperature sensor power down | ||
896 | */ | ||
897 | #define IDT_TMPCTL_LTH_MASK 0x000000FFU | ||
898 | #define IDT_TMPCTL_LTH_FLD 0 | ||
899 | #define IDT_TMPCTL_MTH_MASK 0x0000FF00U | ||
900 | #define IDT_TMPCTL_MTH_FLD 8 | ||
901 | #define IDT_TMPCTL_HTH_MASK 0x00FF0000U | ||
902 | #define IDT_TMPCTL_HTH_FLD 16 | ||
903 | #define IDT_TMPCTL_PDOWN 0x80000000U | ||
904 | |||
905 | /* | ||
889 | * TMPSTS register fields related constants | 906 | * TMPSTS register fields related constants |
890 | * @IDT_TMPSTS_TEMP_MASK: Current temperature field mask | 907 | * @IDT_TMPSTS_TEMP_MASK: Current temperature field mask |
891 | * @IDT_TMPSTS_TEMP_FLD: Current temperature field offset | 908 | * @IDT_TMPSTS_TEMP_FLD: Current temperature field offset |
909 | * @IDT_TMPSTS_LTEMP_MASK: Lowest temperature field mask | ||
910 | * @IDT_TMPSTS_LTEMP_FLD: Lowest temperature field offset | ||
911 | * @IDT_TMPSTS_HTEMP_MASK: Highest temperature field mask | ||
912 | * @IDT_TMPSTS_HTEMP_FLD: Highest temperature field offset | ||
892 | */ | 913 | */ |
893 | #define IDT_TMPSTS_TEMP_MASK 0x000000FFU | 914 | #define IDT_TMPSTS_TEMP_MASK 0x000000FFU |
894 | #define IDT_TMPSTS_TEMP_FLD 0 | 915 | #define IDT_TMPSTS_TEMP_FLD 0 |
916 | #define IDT_TMPSTS_LTEMP_MASK 0x0000FF00U | ||
917 | #define IDT_TMPSTS_LTEMP_FLD 8 | ||
918 | #define IDT_TMPSTS_HTEMP_MASK 0x00FF0000U | ||
919 | #define IDT_TMPSTS_HTEMP_FLD 16 | ||
920 | |||
921 | /* | ||
922 | * TMPALARM register fields related constants | ||
923 | * @IDT_TMPALARM_LTEMP_MASK: Lowest temperature field mask | ||
924 | * @IDT_TMPALARM_LTEMP_FLD: Lowest temperature field offset | ||
925 | * @IDT_TMPALARM_HTEMP_MASK: Highest temperature field mask | ||
926 | * @IDT_TMPALARM_HTEMP_FLD: Highest temperature field offset | ||
927 | * @IDT_TMPALARM_IRQ_MASK: Alarm IRQ status mask | ||
928 | */ | ||
929 | #define IDT_TMPALARM_LTEMP_MASK 0x0000FF00U | ||
930 | #define IDT_TMPALARM_LTEMP_FLD 8 | ||
931 | #define IDT_TMPALARM_HTEMP_MASK 0x00FF0000U | ||
932 | #define IDT_TMPALARM_HTEMP_FLD 16 | ||
933 | #define IDT_TMPALARM_IRQ_MASK 0x3F000000U | ||
934 | |||
935 | /* | ||
936 | * TMPADJ register fields related constants | ||
937 | * @IDT_TMPADJ_OFFSET_MASK: Temperature value offset field mask | ||
938 | * @IDT_TMPADJ_OFFSET_FLD: Temperature value offset field offset | ||
939 | */ | ||
940 | #define IDT_TMPADJ_OFFSET_MASK 0x000000FFU | ||
941 | #define IDT_TMPADJ_OFFSET_FLD 0 | ||
895 | 942 | ||
896 | /* | 943 | /* |
897 | * Helper macro to get/set the corresponding field value | 944 | * Helper macro to get/set the corresponding field value |
@@ -951,6 +998,32 @@ | |||
951 | #define IDT_DIR_SIZE_ALIGN 1 | 998 | #define IDT_DIR_SIZE_ALIGN 1 |
952 | 999 | ||
953 | /* | 1000 | /* |
1001 | * IDT PCIe-switch temperature sensor value limits | ||
1002 | * @IDT_TEMP_MIN_MDEG: Minimal integer value of temperature | ||
1003 | * @IDT_TEMP_MAX_MDEG: Maximal integer value of temperature | ||
1004 | * @IDT_TEMP_MIN_OFFSET:Minimal integer value of temperature offset | ||
1005 | * @IDT_TEMP_MAX_OFFSET:Maximal integer value of temperature offset | ||
1006 | */ | ||
1007 | #define IDT_TEMP_MIN_MDEG 0 | ||
1008 | #define IDT_TEMP_MAX_MDEG 127500 | ||
1009 | #define IDT_TEMP_MIN_OFFSET -64000 | ||
1010 | #define IDT_TEMP_MAX_OFFSET 63500 | ||
1011 | |||
1012 | /* | ||
1013 | * Temperature sensor values enumeration | ||
1014 | * @IDT_TEMP_CUR: Current temperature | ||
1015 | * @IDT_TEMP_LOW: Lowest historical temperature | ||
1016 | * @IDT_TEMP_HIGH: Highest historical temperature | ||
1017 | * @IDT_TEMP_OFFSET: Current temperature offset | ||
1018 | */ | ||
1019 | enum idt_temp_val { | ||
1020 | IDT_TEMP_CUR, | ||
1021 | IDT_TEMP_LOW, | ||
1022 | IDT_TEMP_HIGH, | ||
1023 | IDT_TEMP_OFFSET | ||
1024 | }; | ||
1025 | |||
1026 | /* | ||
954 | * IDT Memory Windows type. Depending on the device settings, IDT supports | 1027 | * IDT Memory Windows type. Depending on the device settings, IDT supports |
955 | * Direct Address Translation MW registers and Lookup Table registers | 1028 | * Direct Address Translation MW registers and Lookup Table registers |
956 | * @IDT_MW_DIR: Direct address translation | 1029 | * @IDT_MW_DIR: Direct address translation |
@@ -1044,6 +1117,8 @@ struct idt_ntb_peer { | |||
1044 | * @msg_mask_lock: Message mask register lock | 1117 | * @msg_mask_lock: Message mask register lock |
1045 | * @gasa_lock: GASA registers access lock | 1118 | * @gasa_lock: GASA registers access lock |
1046 | * | 1119 | * |
1120 | * @hwmon_mtx: Temperature sensor interface update mutex | ||
1121 | * | ||
1047 | * @dbgfs_info: DebugFS info node | 1122 | * @dbgfs_info: DebugFS info node |
1048 | */ | 1123 | */ |
1049 | struct idt_ntb_dev { | 1124 | struct idt_ntb_dev { |
@@ -1071,6 +1146,8 @@ struct idt_ntb_dev { | |||
1071 | spinlock_t msg_mask_lock; | 1146 | spinlock_t msg_mask_lock; |
1072 | spinlock_t gasa_lock; | 1147 | spinlock_t gasa_lock; |
1073 | 1148 | ||
1149 | struct mutex hwmon_mtx; | ||
1150 | |||
1074 | struct dentry *dbgfs_info; | 1151 | struct dentry *dbgfs_info; |
1075 | }; | 1152 | }; |
1076 | #define to_ndev_ntb(__ntb) container_of(__ntb, struct idt_ntb_dev, ntb) | 1153 | #define to_ndev_ntb(__ntb) container_of(__ntb, struct idt_ntb_dev, ntb) |
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c index 6aa573227279..2ad263f708da 100644 --- a/drivers/ntb/hw/intel/ntb_hw_gen1.c +++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c | |||
@@ -265,7 +265,7 @@ static inline int ndev_db_clear_mask(struct intel_ntb_dev *ndev, u64 db_bits, | |||
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
268 | static inline int ndev_vec_mask(struct intel_ntb_dev *ndev, int db_vector) | 268 | static inline u64 ndev_vec_mask(struct intel_ntb_dev *ndev, int db_vector) |
269 | { | 269 | { |
270 | u64 shift, mask; | 270 | u64 shift, mask; |
271 | 271 | ||
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 939895966476..3bfdb4562408 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c | |||
@@ -194,6 +194,8 @@ struct ntb_transport_mw { | |||
194 | void __iomem *vbase; | 194 | void __iomem *vbase; |
195 | size_t xlat_size; | 195 | size_t xlat_size; |
196 | size_t buff_size; | 196 | size_t buff_size; |
197 | size_t alloc_size; | ||
198 | void *alloc_addr; | ||
197 | void *virt_addr; | 199 | void *virt_addr; |
198 | dma_addr_t dma_addr; | 200 | dma_addr_t dma_addr; |
199 | }; | 201 | }; |
@@ -672,13 +674,59 @@ static void ntb_free_mw(struct ntb_transport_ctx *nt, int num_mw) | |||
672 | return; | 674 | return; |
673 | 675 | ||
674 | ntb_mw_clear_trans(nt->ndev, PIDX, num_mw); | 676 | ntb_mw_clear_trans(nt->ndev, PIDX, num_mw); |
675 | dma_free_coherent(&pdev->dev, mw->buff_size, | 677 | dma_free_coherent(&pdev->dev, mw->alloc_size, |
676 | mw->virt_addr, mw->dma_addr); | 678 | mw->alloc_addr, mw->dma_addr); |
677 | mw->xlat_size = 0; | 679 | mw->xlat_size = 0; |
678 | mw->buff_size = 0; | 680 | mw->buff_size = 0; |
681 | mw->alloc_size = 0; | ||
682 | mw->alloc_addr = NULL; | ||
679 | mw->virt_addr = NULL; | 683 | mw->virt_addr = NULL; |
680 | } | 684 | } |
681 | 685 | ||
686 | static int ntb_alloc_mw_buffer(struct ntb_transport_mw *mw, | ||
687 | struct device *dma_dev, size_t align) | ||
688 | { | ||
689 | dma_addr_t dma_addr; | ||
690 | void *alloc_addr, *virt_addr; | ||
691 | int rc; | ||
692 | |||
693 | alloc_addr = dma_alloc_coherent(dma_dev, mw->alloc_size, | ||
694 | &dma_addr, GFP_KERNEL); | ||
695 | if (!alloc_addr) { | ||
696 | dev_err(dma_dev, "Unable to alloc MW buff of size %zu\n", | ||
697 | mw->alloc_size); | ||
698 | return -ENOMEM; | ||
699 | } | ||
700 | virt_addr = alloc_addr; | ||
701 | |||
702 | /* | ||
703 | * we must ensure that the memory address allocated is BAR size | ||
704 | * aligned in order for the XLAT register to take the value. This | ||
705 | * is a requirement of the hardware. It is recommended to setup CMA | ||
706 | * for BAR sizes equal or greater than 4MB. | ||
707 | */ | ||
708 | if (!IS_ALIGNED(dma_addr, align)) { | ||
709 | if (mw->alloc_size > mw->buff_size) { | ||
710 | virt_addr = PTR_ALIGN(alloc_addr, align); | ||
711 | dma_addr = ALIGN(dma_addr, align); | ||
712 | } else { | ||
713 | rc = -ENOMEM; | ||
714 | goto err; | ||
715 | } | ||
716 | } | ||
717 | |||
718 | mw->alloc_addr = alloc_addr; | ||
719 | mw->virt_addr = virt_addr; | ||
720 | mw->dma_addr = dma_addr; | ||
721 | |||
722 | return 0; | ||
723 | |||
724 | err: | ||
725 | dma_free_coherent(dma_dev, mw->alloc_size, alloc_addr, dma_addr); | ||
726 | |||
727 | return rc; | ||
728 | } | ||
729 | |||
682 | static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw, | 730 | static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw, |
683 | resource_size_t size) | 731 | resource_size_t size) |
684 | { | 732 | { |
@@ -710,28 +758,20 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw, | |||
710 | /* Alloc memory for receiving data. Must be aligned */ | 758 | /* Alloc memory for receiving data. Must be aligned */ |
711 | mw->xlat_size = xlat_size; | 759 | mw->xlat_size = xlat_size; |
712 | mw->buff_size = buff_size; | 760 | mw->buff_size = buff_size; |
761 | mw->alloc_size = buff_size; | ||
713 | 762 | ||
714 | mw->virt_addr = dma_alloc_coherent(&pdev->dev, buff_size, | 763 | rc = ntb_alloc_mw_buffer(mw, &pdev->dev, xlat_align); |
715 | &mw->dma_addr, GFP_KERNEL); | 764 | if (rc) { |
716 | if (!mw->virt_addr) { | 765 | mw->alloc_size *= 2; |
717 | mw->xlat_size = 0; | 766 | rc = ntb_alloc_mw_buffer(mw, &pdev->dev, xlat_align); |
718 | mw->buff_size = 0; | 767 | if (rc) { |
719 | dev_err(&pdev->dev, "Unable to alloc MW buff of size %zu\n", | 768 | dev_err(&pdev->dev, |
720 | buff_size); | 769 | "Unable to alloc aligned MW buff\n"); |
721 | return -ENOMEM; | 770 | mw->xlat_size = 0; |
722 | } | 771 | mw->buff_size = 0; |
723 | 772 | mw->alloc_size = 0; | |
724 | /* | 773 | return rc; |
725 | * we must ensure that the memory address allocated is BAR size | 774 | } |
726 | * aligned in order for the XLAT register to take the value. This | ||
727 | * is a requirement of the hardware. It is recommended to setup CMA | ||
728 | * for BAR sizes equal or greater than 4MB. | ||
729 | */ | ||
730 | if (!IS_ALIGNED(mw->dma_addr, xlat_align)) { | ||
731 | dev_err(&pdev->dev, "DMA memory %pad is not aligned\n", | ||
732 | &mw->dma_addr); | ||
733 | ntb_free_mw(nt, num_mw); | ||
734 | return -ENOMEM; | ||
735 | } | 775 | } |
736 | 776 | ||
737 | /* Notify HW the memory location of the receive buffer */ | 777 | /* Notify HW the memory location of the receive buffer */ |
@@ -1278,6 +1318,7 @@ static void ntb_rx_copy_callback(void *data, | |||
1278 | case DMA_TRANS_READ_FAILED: | 1318 | case DMA_TRANS_READ_FAILED: |
1279 | case DMA_TRANS_WRITE_FAILED: | 1319 | case DMA_TRANS_WRITE_FAILED: |
1280 | entry->errors++; | 1320 | entry->errors++; |
1321 | /* fall through */ | ||
1281 | case DMA_TRANS_ABORTED: | 1322 | case DMA_TRANS_ABORTED: |
1282 | { | 1323 | { |
1283 | struct ntb_transport_qp *qp = entry->qp; | 1324 | struct ntb_transport_qp *qp = entry->qp; |
@@ -1533,6 +1574,7 @@ static void ntb_tx_copy_callback(void *data, | |||
1533 | case DMA_TRANS_READ_FAILED: | 1574 | case DMA_TRANS_READ_FAILED: |
1534 | case DMA_TRANS_WRITE_FAILED: | 1575 | case DMA_TRANS_WRITE_FAILED: |
1535 | entry->errors++; | 1576 | entry->errors++; |
1577 | /* fall through */ | ||
1536 | case DMA_TRANS_ABORTED: | 1578 | case DMA_TRANS_ABORTED: |
1537 | { | 1579 | { |
1538 | void __iomem *offset = | 1580 | void __iomem *offset = |