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

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
...@@ -185,6 +185,7 @@ typedef enum _ipath_ureg { ...@@ -185,6 +185,7 @@ typedef enum _ipath_ureg {
#define IPATH_RUNTIME_PCIE 0x2 #define IPATH_RUNTIME_PCIE 0x2
#define IPATH_RUNTIME_FORCE_WC_ORDER 0x4 #define IPATH_RUNTIME_FORCE_WC_ORDER 0x4
#define IPATH_RUNTIME_RCVHDR_COPY 0x8 #define IPATH_RUNTIME_RCVHDR_COPY 0x8
#define IPATH_RUNTIME_MASTER 0x10
/* /*
* This structure is returned by ipath_userinit() immediately after * This structure is returned by ipath_userinit() immediately after
...@@ -202,7 +203,8 @@ struct ipath_base_info { ...@@ -202,7 +203,8 @@ struct ipath_base_info {
/* version of software, for feature checking. */ /* version of software, for feature checking. */
__u32 spi_sw_version; __u32 spi_sw_version;
/* InfiniPath port assigned, goes into sent packets */ /* 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. * IB MTU, packets IB data must be less than this.
* The MTU is in bytes, and will be a multiple of 4 bytes. * The MTU is in bytes, and will be a multiple of 4 bytes.
...@@ -218,7 +220,7 @@ struct ipath_base_info { ...@@ -218,7 +220,7 @@ struct ipath_base_info {
__u32 spi_tidcnt; __u32 spi_tidcnt;
/* size of the TID Eager list in infinipath, in entries */ /* size of the TID Eager list in infinipath, in entries */
__u32 spi_tidegrcnt; __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; __u32 spi_rcvhdrent_size;
/* /*
* Count of receive header queue entries allocated. * Count of receive header queue entries allocated.
...@@ -310,6 +312,12 @@ struct ipath_base_info { ...@@ -310,6 +312,12 @@ struct ipath_base_info {
__u32 spi_filler_for_align; __u32 spi_filler_for_align;
/* address of readonly memory copy of the rcvhdrq tail register. */ /* address of readonly memory copy of the rcvhdrq tail register. */
__u64 spi_rcvhdr_tailaddr; __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))); } __attribute__ ((aligned(8)));
...@@ -328,12 +336,12 @@ struct ipath_base_info { ...@@ -328,12 +336,12 @@ struct ipath_base_info {
/* /*
* Minor version differences are always compatible * 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 * than driver software, some new features and/or structure fields
* may not be implemented; the user code must deal with this if it * 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) #define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
...@@ -379,7 +387,16 @@ struct ipath_user_info { ...@@ -379,7 +387,16 @@ struct ipath_user_info {
*/ */
__u32 spu_rcvhdrsize; __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 * address of struct base_info to write to
...@@ -398,13 +415,17 @@ struct ipath_user_info { ...@@ -398,13 +415,17 @@ struct ipath_user_info {
#define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */ #define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */
#define IPATH_CMD_TID_FREE 20 /* free 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_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 { struct ipath_port_info {
__u32 num_active; /* number of active units */ __u32 num_active; /* number of active units */
__u32 unit; /* unit (chip) assigned to caller */ __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 { struct ipath_tid_info {
...@@ -435,6 +456,8 @@ struct ipath_cmd { ...@@ -435,6 +456,8 @@ struct ipath_cmd {
__u32 recv_ctrl; __u32 recv_ctrl;
/* partition key to set */ /* partition key to set */
__u16 part_key; __u16 part_key;
/* user address of __u32 bitmask of active slaves */
__u64 slave_mask_addr;
} cmd; } cmd;
}; };
...@@ -596,6 +619,10 @@ struct infinipath_counters { ...@@ -596,6 +619,10 @@ struct infinipath_counters {
/* K_PktFlags bits */ /* K_PktFlags bits */
#define INFINIPATH_KPF_INTR 0x1 #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 */ /* SendPIO per-buffer control */
#define INFINIPATH_SP_TEST 0x40 #define INFINIPATH_SP_TEST 0x40
...@@ -610,7 +637,7 @@ struct ipath_header { ...@@ -610,7 +637,7 @@ struct ipath_header {
/* /*
* Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset - * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset -
* 14 bits before ECO change ~28 Dec 03. After that, Vers 4, * 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; __le32 ver_port_tid_offset;
__le16 chksum; __le16 chksum;
......
...@@ -1827,9 +1827,9 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd) ...@@ -1827,9 +1827,9 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
dma_free_coherent(&dd->pcidev->dev, size, dma_free_coherent(&dd->pcidev->dev, size,
base, pd->port_rcvegrbuf_phys[e]); base, pd->port_rcvegrbuf_phys[e]);
} }
vfree(pd->port_rcvegrbuf); kfree(pd->port_rcvegrbuf);
pd->port_rcvegrbuf = NULL; pd->port_rcvegrbuf = NULL;
vfree(pd->port_rcvegrbuf_phys); kfree(pd->port_rcvegrbuf_phys);
pd->port_rcvegrbuf_phys = NULL; pd->port_rcvegrbuf_phys = NULL;
pd->port_rcvegrbuf_chunks = 0; pd->port_rcvegrbuf_chunks = 0;
} else if (pd->port_port == 0 && dd->ipath_port0_skbs) { } 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) ...@@ -1845,6 +1845,9 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
vfree(skbs); vfree(skbs);
} }
kfree(pd->port_tid_pg_list); kfree(pd->port_tid_pg_list);
vfree(pd->subport_uregbase);
vfree(pd->subport_rcvegrbuf);
vfree(pd->subport_rcvhdr_base);
kfree(pd); kfree(pd);
} }
......
...@@ -79,8 +79,8 @@ struct ipath_portdata { ...@@ -79,8 +79,8 @@ struct ipath_portdata {
dma_addr_t port_rcvhdrq_phys; dma_addr_t port_rcvhdrq_phys;
dma_addr_t port_rcvhdrqtailaddr_phys; dma_addr_t port_rcvhdrqtailaddr_phys;
/* /*
* number of opens on this instance (0 or 1; ignoring forks, dup, * number of opens (including slave subports) on this instance
* etc. for now) * (ignoring forks, dup, etc. for now)
*/ */
int port_cnt; int port_cnt;
/* /*
...@@ -89,6 +89,10 @@ struct ipath_portdata { ...@@ -89,6 +89,10 @@ struct ipath_portdata {
*/ */
/* instead of calculating it */ /* instead of calculating it */
unsigned port_port; 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 */ /* chip offset of PIO buffers for this port */
u32 port_piobufs; u32 port_piobufs;
/* how many alloc_pages() chunks in port_rcvegrbuf_pages */ /* how many alloc_pages() chunks in port_rcvegrbuf_pages */
...@@ -121,6 +125,16 @@ struct ipath_portdata { ...@@ -121,6 +125,16 @@ struct ipath_portdata {
u16 port_pkeys[4]; u16 port_pkeys[4];
/* so file ops can get at unit */ /* so file ops can get at unit */
struct ipath_devdata *port_dd; 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; struct sk_buff;
...@@ -512,6 +526,12 @@ struct ipath_devdata { ...@@ -512,6 +526,12 @@ struct ipath_devdata {
u32 ipath_lli_errors; 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 struct list_head ipath_dev_list;
extern spinlock_t ipath_devs_lock; extern spinlock_t ipath_devs_lock;
extern struct ipath_devdata *ipath_lookup(int unit); extern struct ipath_devdata *ipath_lookup(int unit);
...@@ -572,7 +592,11 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8); ...@@ -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); 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. */ /* 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 * values for ipath_flags
......
...@@ -297,6 +297,16 @@ static ssize_t show_nguid(struct device *dev, ...@@ -297,6 +297,16 @@ static ssize_t show_nguid(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid); 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, static ssize_t show_serial(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -608,6 +618,7 @@ static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid); ...@@ -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(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled); static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL); 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(reset, S_IWUSR, NULL, store_reset);
static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
...@@ -623,6 +634,7 @@ static struct attribute *dev_attributes[] = { ...@@ -623,6 +634,7 @@ static struct attribute *dev_attributes[] = {
&dev_attr_mlid.attr, &dev_attr_mlid.attr,
&dev_attr_mtu.attr, &dev_attr_mtu.attr,
&dev_attr_nguid.attr, &dev_attr_nguid.attr,
&dev_attr_nports.attr,
&dev_attr_serial.attr, &dev_attr_serial.attr,
&dev_attr_status.attr, &dev_attr_status.attr,
&dev_attr_status_str.attr, &dev_attr_status_str.attr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment