From 2efdc2c662715f5b2b87794d531169878d7fd497 Mon Sep 17 00:00:00 2001 From: hselasky Date: Tue, 13 Jan 2015 17:07:30 +0000 Subject: [PATCH] MFC r276749: Fixes and updates for the Linux compatibility layer: - Remove unsupported "bus" field from "struct pci_dev". - Fix logic inside "pci_enable_msix()" when the number of allocated interrupts are less than the number of available interrupts. - Update header files included from "list.h". - Ensure that "idr_destroy()" removes all entries before destroying the IDR root node(s). - Set the "device->release" function so that we don't leak memory at device destruction. - Use FreeBSD's "log()" function for certain debug printouts. - Put parenthesis around arguments inside the min, max, min_t and max_t macros. - Make sure we don't leak file descriptors by dropping the extra file reference counts done by the FreeBSD kernel when calling falloc() and fget_unlocked(). MFC after: 1 week Sponsored by: Mellanox Technologies git-svn-id: svn://svn.freebsd.org/base/stable/10@277139 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/ofed/drivers/infiniband/hw/mlx4/main.c | 8 ++- sys/ofed/drivers/net/mlx4/main.c | 4 -- sys/ofed/include/linux/file.h | 15 +++- sys/ofed/include/linux/kernel.h | 82 +++++++++++++--------- sys/ofed/include/linux/linux_compat.c | 8 +++ sys/ofed/include/linux/linux_idr.c | 1 + sys/ofed/include/linux/list.h | 1 + sys/ofed/include/linux/pci.h | 13 +++- 8 files changed, 90 insertions(+), 42 deletions(-) diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/main.c b/sys/ofed/drivers/infiniband/hw/mlx4/main.c index 343b193e8..3a78502ea 100644 --- a/sys/ofed/drivers/infiniband/hw/mlx4/main.c +++ b/sys/ofed/drivers/infiniband/hw/mlx4/main.c @@ -1613,8 +1613,12 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) eq = 0; mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) { for (j = 0; j < eq_per_port; j++) { - //sprintf(name, "mlx4-ib-%d-%d@%s", - // i, j, dev->pdev->bus->conf.pd_name); + snprintf(name, sizeof(name), "mlx4-ib-%d-%d@%d:%d:%d:%d", i, j, + pci_get_domain(dev->pdev->dev.bsddev), + pci_get_bus(dev->pdev->dev.bsddev), + PCI_SLOT(dev->pdev->devfn), + PCI_FUNC(dev->pdev->devfn)); + /* Set IRQ for specific name (per ring) */ if (mlx4_assign_eq(dev, name, &ibdev->eq_table[eq])) { diff --git a/sys/ofed/drivers/net/mlx4/main.c b/sys/ofed/drivers/net/mlx4/main.c index 12c583601..b92626d09 100644 --- a/sys/ofed/drivers/net/mlx4/main.c +++ b/sys/ofed/drivers/net/mlx4/main.c @@ -504,10 +504,6 @@ int mlx4_get_val(struct mlx4_dbdf2val *tbl, struct pci_dev *pdev, int idx, if (!pdev) return -EINVAL; - if (!pdev->bus) { - return -EINVAL; - } - dbdf = dbdf_to_u64(pci_get_domain(pdev->dev.bsddev), pci_get_bus(pdev->dev.bsddev), PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); diff --git a/sys/ofed/include/linux/file.h b/sys/ofed/include/linux/file.h index 6576cd029..b76a40865 100644 --- a/sys/ofed/include/linux/file.h +++ b/sys/ofed/include/linux/file.h @@ -77,7 +77,15 @@ put_unused_fd(unsigned int fd) NULL) != 0) { return; } + /* + * NOTE: We should only get here when the "fd" has not been + * installed, so no need to free the associated Linux file + * structure. + */ fdclose(curthread->td_proc->p_fd, file, fd, curthread); + + /* drop extra reference */ + fdrop(file, curthread); } static inline void @@ -90,7 +98,10 @@ fd_install(unsigned int fd, struct linux_file *filp) file = NULL; } filp->_file = file; - finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); + finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); + + /* drop the extra reference */ + fput(filp); } static inline int @@ -103,6 +114,8 @@ get_unused_fd(void) error = falloc(curthread, &file, &fd, 0); if (error) return -error; + /* drop the extra reference */ + fdrop(file, curthread); return fd; } diff --git a/sys/ofed/include/linux/kernel.h b/sys/ofed/include/linux/kernel.h index e1bc220ec..d9d1ab661 100644 --- a/sys/ofed/include/linux/kernel.h +++ b/sys/ofed/include/linux/kernel.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,23 @@ #define DIV_ROUND_UP howmany #define printk(X...) printf(X) -#define pr_debug(fmt, ...) printk(KERN_DEBUG # fmt, ##__VA_ARGS__) + +/* + * The "pr_debug()" and "pr_devel()" macros should produce zero code + * unless DEBUG is defined: + */ +#ifdef DEBUG +#define pr_debug(fmt, ...) \ + log(LOG_DEBUG, fmt, ##__VA_ARGS__) +#define pr_devel(fmt, ...) \ + log(LOG_DEBUG, pr_fmt(fmt), ##__VA_ARGS__) +#else +#define pr_debug(fmt, ...) \ + ({ if (0) log(LOG_DEBUG, fmt, ##__VA_ARGS__); 0; }) +#define pr_devel(fmt, ...) \ + ({ if (0) log(LOG_DEBUG, pr_fmt(fmt), ##__VA_ARGS__); 0; }) +#endif + #define udelay(t) DELAY(t) #ifndef pr_fmt @@ -75,45 +92,46 @@ /* * Print a one-time message (analogous to WARN_ONCE() et al): */ -#define printk_once(x...) ({ \ - static bool __print_once; \ - \ - if (!__print_once) { \ - __print_once = true; \ - printk(x); \ - } \ -}) - +#define printk_once(...) do { \ + static bool __print_once; \ + \ + if (!__print_once) { \ + __print_once = true; \ + printk(__VA_ARGS__); \ + } \ +} while (0) +/* + * Log a one-time message (analogous to WARN_ONCE() et al): + */ +#define log_once(level,...) do { \ + static bool __log_once; \ + \ + if (!__log_once) { \ + __log_once = true; \ + log(level, __VA_ARGS__); \ + } \ +} while (0) #define pr_emerg(fmt, ...) \ - printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_EMERG, pr_fmt(fmt), ##__VA_ARGS__) #define pr_alert(fmt, ...) \ - printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_ALERT, pr_fmt(fmt), ##__VA_ARGS__) #define pr_crit(fmt, ...) \ - printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_CRIT, pr_fmt(fmt), ##__VA_ARGS__) #define pr_err(fmt, ...) \ - printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_ERR, pr_fmt(fmt), ##__VA_ARGS__) #define pr_warning(fmt, ...) \ - printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_WARNING, pr_fmt(fmt), ##__VA_ARGS__) #define pr_warn pr_warning #define pr_notice(fmt, ...) \ - printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_NOTICE, pr_fmt(fmt), ##__VA_ARGS__) #define pr_info(fmt, ...) \ - printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) + log(LOG_INFO, pr_fmt(fmt), ##__VA_ARGS__) #define pr_info_once(fmt, ...) \ - printk_once(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) + log_once(LOG_INFO, pr_fmt(fmt), ##__VA_ARGS__) #define pr_cont(fmt, ...) \ - printk(KERN_CONT fmt, ##__VA_ARGS__) - -/* pr_devel() should produce zero code unless DEBUG is defined */ -#ifdef DEBUG -#define pr_devel(fmt, ...) \ - printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) -#else -#define pr_devel(fmt, ...) \ - ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; }) -#endif + printk(KERN_CONT fmt, ##__VA_ARGS__) #ifndef WARN #define WARN(condition, format...) ({ \ @@ -136,10 +154,10 @@ #define simple_strtol strtol #define kstrtol(a,b,c) ({*(c) = strtol(a,0,b);}) -#define min(x, y) (x < y ? x : y) -#define max(x, y) (x > y ? x : y) -#define min_t(type, _x, _y) (type)(_x) < (type)(_y) ? (type)(_x) : (_y) -#define max_t(type, _x, _y) (type)(_x) > (type)(_y) ? (type)(_x) : (_y) +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) +#define min_t(type, _x, _y) ((type)(_x) < (type)(_y) ? (type)(_x) : (type)(_y)) +#define max_t(type, _x, _y) ((type)(_x) > (type)(_y) ? (type)(_x) : (type)(_y)) /* * This looks more complex than it should be. But we need to diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c index 5ac7dd628..db617bbcc 100644 --- a/sys/ofed/include/linux/linux_compat.c +++ b/sys/ofed/include/linux/linux_compat.c @@ -174,6 +174,13 @@ kobject_kfree_name(struct kobject *kobj) struct kobj_type kfree_type = { .release = kobject_kfree }; +static void +dev_release(struct device *dev) +{ + pr_debug("dev_release: %s\n", dev_name(dev)); + kfree(dev); +} + struct device * device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) @@ -186,6 +193,7 @@ device_create(struct class *class, struct device *parent, dev_t devt, dev->class = class; dev->devt = devt; dev->driver_data = drvdata; + dev->release = dev_release; va_start(args, fmt); kobject_set_name_vargs(&dev->kobj, fmt, args); va_end(args); diff --git a/sys/ofed/include/linux/linux_idr.c b/sys/ofed/include/linux/linux_idr.c index 0238c8e3c..273f2ea5d 100644 --- a/sys/ofed/include/linux/linux_idr.c +++ b/sys/ofed/include/linux/linux_idr.c @@ -77,6 +77,7 @@ idr_destroy(struct idr *idr) { struct idr_layer *il, *iln; + idr_remove_all(idr); mtx_lock(&idr->lock); for (il = idr->free; il != NULL; il = iln) { iln = il->ary[0]; diff --git a/sys/ofed/include/linux/list.h b/sys/ofed/include/linux/list.h index b939ba5e2..4e9337bc5 100644 --- a/sys/ofed/include/linux/list.h +++ b/sys/ofed/include/linux/list.h @@ -57,6 +57,7 @@ #include #include +#include #include #include diff --git a/sys/ofed/include/linux/pci.h b/sys/ofed/include/linux/pci.h index c348832f8..3e574f08f 100644 --- a/sys/ofed/include/linux/pci.h +++ b/sys/ofed/include/linux/pci.h @@ -149,9 +149,8 @@ struct pci_dev { uint16_t device; uint16_t vendor; unsigned int irq; - unsigned int devfn; - u8 revision; - struct pci_devinfo *bus; /* bus this device is on, equivalent to linux struct pci_bus */ + unsigned int devfn; + u8 revision; }; static inline struct resource_list_entry * @@ -577,6 +576,14 @@ pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq) avail = nreq; if ((error = -pci_alloc_msix(pdev->dev.bsddev, &avail)) != 0) return error; + /* + * Handle case where "pci_alloc_msix()" may allocate less + * interrupts than available and return with no error: + */ + if (avail < nreq) { + pci_release_msi(pdev->dev.bsddev); + return avail; + } rle = _pci_get_rle(pdev, SYS_RES_IRQ, 1); pdev->dev.msix = rle->start; pdev->dev.msix_max = rle->start + avail; -- 2.45.0