Skip to content

Commit

Permalink
IB/ipath: Correct checking of swminor version field when using subports
Browse files Browse the repository at this point in the history
When subports are required to run a program, this patch checks that
the driver and the userspace library have compatible subport
implementations.  This is achieved through checks on the swminor
version field built into the driver and userspace library.  Bad
combinations are reported through syslog and result in an error when
opening the port.

Signed-off-by: Mark Debbage <mark.debbage@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Mark Debbage authored and Roland Dreier committed Jul 10, 2007
1 parent d781b12 commit 0df6291
Showing 1 changed file with 55 additions and 9 deletions.
64 changes: 55 additions & 9 deletions drivers/infiniband/hw/ipath/ipath_file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,38 @@ static unsigned int ipath_poll(struct file *fp,
return pollflag;
}

static int ipath_supports_subports(int user_swmajor, int user_swminor)
{
/* no subport implementation prior to software version 1.3 */
return (user_swmajor > 1) || (user_swminor >= 3);
}

static int ipath_compatible_subports(int user_swmajor, int user_swminor)
{
/* this code is written long-hand for clarity */
if (IPATH_USER_SWMAJOR != user_swmajor) {
/* no promise of compatibility if major mismatch */
return 0;
}
if (IPATH_USER_SWMAJOR == 1) {
switch (IPATH_USER_SWMINOR) {
case 0:
case 1:
case 2:
/* no subport implementation so cannot be compatible */
return 0;
case 3:
/* 3 is only compatible with itself */
return user_swminor == 3;
default:
/* >= 4 are compatible (or are expected to be) */
return user_swminor >= 4;
}
}
/* make no promises yet for future major versions */
return 0;
}

static int init_subports(struct ipath_devdata *dd,
struct ipath_portdata *pd,
const struct ipath_user_info *uinfo)
Expand All @@ -1418,14 +1450,26 @@ static int init_subports(struct ipath_devdata *dd,
if (uinfo->spu_subport_cnt <= 1)
goto bail;

/* Old user binaries don't know about new subport implementation */
if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR) {
/* Self-consistency check for ipath_compatible_subports() */
if (ipath_supports_subports(IPATH_USER_SWMAJOR, IPATH_USER_SWMINOR) &&
!ipath_compatible_subports(IPATH_USER_SWMAJOR,
IPATH_USER_SWMINOR)) {
dev_info(&dd->pcidev->dev,
"Mismatched user minor version (%d) and driver "
"minor version (%d) while port sharing. Ensure "
"Inconsistent ipath_compatible_subports()\n");
goto bail;
}

/* Check for subport compatibility */
if (!ipath_compatible_subports(uinfo->spu_userversion >> 16,
uinfo->spu_userversion & 0xffff)) {
dev_info(&dd->pcidev->dev,
"Mismatched user version (%d.%d) and driver "
"version (%d.%d) while port sharing. Ensure "
"that driver and library are from the same "
"release.\n",
(int) (uinfo->spu_userversion >> 16),
(int) (uinfo->spu_userversion & 0xffff),
IPATH_USER_SWMAJOR,
IPATH_USER_SWMINOR);
goto bail;
}
Expand Down Expand Up @@ -1729,14 +1773,13 @@ static int ipath_open(struct inode *in, struct file *fp)
return fp->private_data ? 0 : -ENOMEM;
}


/* Get port early, so can set affinity prior to memory allocation */
static int ipath_assign_port(struct file *fp,
const struct ipath_user_info *uinfo)
{
int ret;
int i_minor;
unsigned swminor;
unsigned swmajor, swminor;

/* Check to be sure we haven't already initialized this file */
if (port_fp(fp)) {
Expand All @@ -1745,7 +1788,8 @@ static int ipath_assign_port(struct file *fp,
}

/* for now, if major version is different, bail */
if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
swmajor = uinfo->spu_userversion >> 16;
if (swmajor != IPATH_USER_SWMAJOR) {
ipath_dbg("User major version %d not same as driver "
"major %d\n", uinfo->spu_userversion >> 16,
IPATH_USER_SWMAJOR);
Expand All @@ -1760,7 +1804,8 @@ static int ipath_assign_port(struct file *fp,

mutex_lock(&ipath_mutex);

if (swminor == IPATH_USER_SWMINOR && uinfo->spu_subport_cnt &&
if (ipath_compatible_subports(swmajor, swminor) &&
uinfo->spu_subport_cnt &&
(ret = find_shared_port(fp, uinfo))) {
mutex_unlock(&ipath_mutex);
if (ret > 0)
Expand Down Expand Up @@ -2024,7 +2069,8 @@ static int ipath_port_info(struct ipath_portdata *pd, u16 subport,
info.port = pd->port_port;
info.subport = subport;
/* Don't return new fields if old library opened the port. */
if ((pd->userversion & 0xffff) == IPATH_USER_SWMINOR) {
if (ipath_supports_subports(pd->userversion >> 16,
pd->userversion & 0xffff)) {
/* Number of user ports available for this device. */
info.num_ports = pd->port_dd->ipath_cfgports - 1;
info.num_subports = pd->port_subport_cnt;
Expand Down

0 comments on commit 0df6291

Please sign in to comment.