Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9929b0fb authored by Bryan O'Sullivan's avatar Bryan O'Sullivan Committed by Roland Dreier
Browse files

IB/ipath: Driver support for userspace sharing of HW contexts



This allows multiple userspace processes to share a single hardware
context in a master/slave arrangement.  It is backwards binary compatible
with existing userspace.

Signed-off-by: default avatarBryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 221e3198
Loading
Loading
Loading
Loading
+36 −9
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ typedef enum _ipath_ureg {
#define IPATH_RUNTIME_PCIE	0x2
#define IPATH_RUNTIME_FORCE_WC_ORDER	0x4
#define IPATH_RUNTIME_RCVHDR_COPY	0x8
#define IPATH_RUNTIME_MASTER	0x10

/*
 * This structure is returned by ipath_userinit() immediately after
@@ -202,7 +203,8 @@ struct ipath_base_info {
	/* version of software, for feature checking. */
	__u32 spi_sw_version;
	/* InfiniPath port assigned, goes into sent packets */
	__u32 spi_port;
	__u16 spi_port;
	__u16 spi_subport;
	/*
	 * IB MTU, packets IB data must be less than this.
	 * The MTU is in bytes, and will be a multiple of 4 bytes.
@@ -218,7 +220,7 @@ struct ipath_base_info {
	__u32 spi_tidcnt;
	/* size of the TID Eager list in infinipath, in entries */
	__u32 spi_tidegrcnt;
	/* size of a single receive header queue entry. */
	/* size of a single receive header queue entry in words. */
	__u32 spi_rcvhdrent_size;
	/*
	 * Count of receive header queue entries allocated.
@@ -310,6 +312,12 @@ struct ipath_base_info {
	__u32 spi_filler_for_align;
	/* address of readonly memory copy of the rcvhdrq tail register. */
	__u64 spi_rcvhdr_tailaddr;

	/* shared memory pages for subports if IPATH_RUNTIME_MASTER is set */
	__u64 spi_subport_uregbase;
	__u64 spi_subport_rcvegrbuf;
	__u64 spi_subport_rcvhdr_base;

} __attribute__ ((aligned(8)));


@@ -328,12 +336,12 @@ struct ipath_base_info {

/*
 * Minor version differences are always compatible
 * a within a major version, however if if user software is larger
 * a within a major version, however if user software is larger
 * than driver software, some new features and/or structure fields
 * may not be implemented; the user code must deal with this if it
 * cares, or it must abort after initialization reports the difference
 * cares, or it must abort after initialization reports the difference.
 */
#define IPATH_USER_SWMINOR 2
#define IPATH_USER_SWMINOR 3

#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)

@@ -379,7 +387,16 @@ struct ipath_user_info {
	 */
	__u32 spu_rcvhdrsize;

	__u64 spu_unused; /* kept for compatible layout */
	/*
	 * If two or more processes wish to share a port, each process
	 * must set the spu_subport_cnt and spu_subport_id to the same
	 * values.  The only restriction on the spu_subport_id is that
	 * it be unique for a given node.
	 */
	__u16 spu_subport_cnt;
	__u16 spu_subport_id;

	__u32 spu_unused; /* kept for compatible layout */

	/*
	 * address of struct base_info to write to
@@ -398,13 +415,17 @@ struct ipath_user_info {
#define IPATH_CMD_TID_UPDATE	19	/* update expected TID entries */
#define IPATH_CMD_TID_FREE	20	/* free expected TID entries */
#define IPATH_CMD_SET_PART_KEY	21	/* add partition key */
#define IPATH_CMD_SLAVE_INFO	22	/* return info on slave processes */

#define IPATH_CMD_MAX		21
#define IPATH_CMD_MAX		22

struct ipath_port_info {
	__u32 num_active;	/* number of active units */
	__u32 unit;		/* unit (chip) assigned to caller */
	__u32 port;		/* port on unit assigned to caller */
	__u16 port;		/* port on unit assigned to caller */
	__u16 subport;		/* subport on unit assigned to caller */
	__u16 num_ports;	/* number of ports available on unit */
	__u16 num_subports;	/* number of subport slaves opened on port */
};

struct ipath_tid_info {
@@ -435,6 +456,8 @@ struct ipath_cmd {
		__u32 recv_ctrl;
		/* partition key to set */
		__u16 part_key;
		/* user address of __u32 bitmask of active slaves */
		__u64 slave_mask_addr;
	} cmd;
};

@@ -596,6 +619,10 @@ struct infinipath_counters {

/* K_PktFlags bits */
#define INFINIPATH_KPF_INTR 0x1
#define INFINIPATH_KPF_SUBPORT_MASK 0x3
#define INFINIPATH_KPF_SUBPORT_SHIFT 1

#define INFINIPATH_MAX_SUBPORT	4

/* SendPIO per-buffer control */
#define INFINIPATH_SP_TEST    0x40
@@ -610,7 +637,7 @@ struct ipath_header {
	/*
	 * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset -
	 * 14 bits before ECO change ~28 Dec 03.  After that, Vers 4,
	 * Port 3, TID 11, offset 14.
	 * Port 4, TID 11, offset 13.
	 */
	__le32 ver_port_tid_offset;
	__le16 chksum;
+5 −2
Original line number Diff line number Diff line
@@ -1827,9 +1827,9 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
			dma_free_coherent(&dd->pcidev->dev, size,
				base, pd->port_rcvegrbuf_phys[e]);
		}
		vfree(pd->port_rcvegrbuf);
		kfree(pd->port_rcvegrbuf);
		pd->port_rcvegrbuf = NULL;
		vfree(pd->port_rcvegrbuf_phys);
		kfree(pd->port_rcvegrbuf_phys);
		pd->port_rcvegrbuf_phys = NULL;
		pd->port_rcvegrbuf_chunks = 0;
	} else if (pd->port_port == 0 && dd->ipath_port0_skbs) {
@@ -1845,6 +1845,9 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
		vfree(skbs);
	}
	kfree(pd->port_tid_pg_list);
	vfree(pd->subport_uregbase);
	vfree(pd->subport_rcvegrbuf);
	vfree(pd->subport_rcvhdr_base);
	kfree(pd);
}

+674 −227

File changed.

Preview size limit exceeded, changes collapsed.

+27 −3
Original line number Diff line number Diff line
@@ -79,8 +79,8 @@ struct ipath_portdata {
	dma_addr_t port_rcvhdrq_phys;
	dma_addr_t port_rcvhdrqtailaddr_phys;
	/*
	 * number of opens on this instance (0 or 1; ignoring forks, dup,
	 * etc. for now)
	 * number of opens (including slave subports) on this instance
	 * (ignoring forks, dup, etc. for now)
	 */
	int port_cnt;
	/*
@@ -89,6 +89,10 @@ struct ipath_portdata {
	 */
	/* instead of calculating it */
	unsigned port_port;
	/* non-zero if port is being shared. */
	u16 port_subport_cnt;
	/* non-zero if port is being shared. */
	u16 port_subport_id;
	/* chip offset of PIO buffers for this port */
	u32 port_piobufs;
	/* how many alloc_pages() chunks in port_rcvegrbuf_pages */
@@ -121,6 +125,16 @@ struct ipath_portdata {
	u16 port_pkeys[4];
	/* so file ops can get at unit */
	struct ipath_devdata *port_dd;
	/* A page of memory for rcvhdrhead, rcvegrhead, rcvegrtail * N */
	void *subport_uregbase;
	/* An array of pages for the eager receive buffers * N */
	void *subport_rcvegrbuf;
	/* An array of pages for the eager header queue entries * N */
	void *subport_rcvhdr_base;
	/* The version of the library which opened this port */
	u32 userversion;
	/* Bitmask of active slaves */
	u32 active_slaves;
};

struct sk_buff;
@@ -512,6 +526,12 @@ struct ipath_devdata {
	u32 ipath_lli_errors;
};

/* Private data for file operations */
struct ipath_filedata {
	struct ipath_portdata *pd;
	unsigned subport;
	unsigned tidcursor;
};
extern struct list_head ipath_dev_list;
extern spinlock_t ipath_devs_lock;
extern struct ipath_devdata *ipath_lookup(int unit);
@@ -572,7 +592,11 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8);
int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);

/* for use in system calls, where we want to know device type, etc. */
#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
#define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
#define subport_fp(fp) \
	((struct ipath_filedata *)(fp)->private_data)->subport
#define tidcursor_fp(fp) \
	((struct ipath_filedata *)(fp)->private_data)->tidcursor

/*
 * values for ipath_flags
+12 −0
Original line number Diff line number Diff line
@@ -297,6 +297,16 @@ static ssize_t show_nguid(struct device *dev,
	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
}

static ssize_t show_nports(struct device *dev,
			   struct device_attribute *attr,
			   char *buf)
{
	struct ipath_devdata *dd = dev_get_drvdata(dev);

	/* Return the number of user ports available. */
	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1);
}

static ssize_t show_serial(struct device *dev,
			   struct device_attribute *attr,
			   char *buf)
@@ -608,6 +618,7 @@ static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL);
static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
@@ -623,6 +634,7 @@ static struct attribute *dev_attributes[] = {
	&dev_attr_mlid.attr,
	&dev_attr_mtu.attr,
	&dev_attr_nguid.attr,
	&dev_attr_nports.attr,
	&dev_attr_serial.attr,
	&dev_attr_status.attr,
	&dev_attr_status_str.attr,