summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-01-06 10:02:14 +0000
committerhselasky <hselasky@FreeBSD.org>2015-01-06 10:02:14 +0000
commitff9d81bf5b98e98550d75c454cbd7b6d5002e628 (patch)
treef5c0366ac2a1cb4aa81c464bb330af4079c5561b
parent18328f686ae182dc43496ef6a7a7cc0a2e9212c4 (diff)
downloadFreeBSD-src-ff9d81bf5b98e98550d75c454cbd7b6d5002e628.zip
FreeBSD-src-ff9d81bf5b98e98550d75c454cbd7b6d5002e628.tar.gz
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
-rw-r--r--sys/ofed/drivers/infiniband/hw/mlx4/main.c8
-rw-r--r--sys/ofed/drivers/net/mlx4/main.c4
-rw-r--r--sys/ofed/include/linux/file.h15
-rw-r--r--sys/ofed/include/linux/kernel.h82
-rw-r--r--sys/ofed/include/linux/linux_compat.c8
-rw-r--r--sys/ofed/include/linux/linux_idr.c1
-rw-r--r--sys/ofed/include/linux/list.h1
-rw-r--r--sys/ofed/include/linux/pci.h13
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 343b193..3a78502 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 12c5836..b92626d 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 6576cd0..b76a408 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 e1bc220..d9d1ab6 100644
--- a/sys/ofed/include/linux/kernel.h
+++ b/sys/ofed/include/linux/kernel.h
@@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <sys/smp.h>
#include <sys/stddef.h>
+#include <sys/syslog.h>
#include <linux/bitops.h>
#include <linux/compiler.h>
@@ -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 39dfeaf..0434183 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 0238c8e..273f2ea 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 60a3f8e..fe06cf3 100644
--- a/sys/ofed/include/linux/list.h
+++ b/sys/ofed/include/linux/list.h
@@ -58,6 +58,7 @@
#include <netinet/in.h>
#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
diff --git a/sys/ofed/include/linux/pci.h b/sys/ofed/include/linux/pci.h
index fd91a5c..ae141b5 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 *
@@ -581,6 +580,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;
OpenPOWER on IntegriCloud