diff options
author | Bryan O'Sullivan <bos@pathscale.com> | 2006-09-28 11:59:59 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-09-28 14:16:25 -0400 |
commit | 9929b0fb0f35f54371e9364bab809bcd753f9d3a (patch) | |
tree | 1722f36becc47589bb7b0d98ad00c10dece2a95e | |
parent | 221e31985b490309eb9ae33ac815deae3b5aa021 (diff) |
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: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_common.h | 45 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_file_ops.c | 901 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 30 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_sysfs.c | 12 |
5 files changed, 754 insertions, 241 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h index f577905e3aca..46b7b20d8a91 100644 --- a/drivers/infiniband/hw/ipath/ipath_common.h +++ b/drivers/infiniband/hw/ipath/ipath_common.h | |||
@@ -185,6 +185,7 @@ typedef enum _ipath_ureg { | |||
185 | #define IPATH_RUNTIME_PCIE 0x2 | 185 | #define IPATH_RUNTIME_PCIE 0x2 |
186 | #define IPATH_RUNTIME_FORCE_WC_ORDER 0x4 | 186 | #define IPATH_RUNTIME_FORCE_WC_ORDER 0x4 |
187 | #define IPATH_RUNTIME_RCVHDR_COPY 0x8 | 187 | #define IPATH_RUNTIME_RCVHDR_COPY 0x8 |
188 | #define IPATH_RUNTIME_MASTER 0x10 | ||
188 | 189 | ||
189 | /* | 190 | /* |
190 | * This structure is returned by ipath_userinit() immediately after | 191 | * This structure is returned by ipath_userinit() immediately after |
@@ -202,7 +203,8 @@ struct ipath_base_info { | |||
202 | /* version of software, for feature checking. */ | 203 | /* version of software, for feature checking. */ |
203 | __u32 spi_sw_version; | 204 | __u32 spi_sw_version; |
204 | /* InfiniPath port assigned, goes into sent packets */ | 205 | /* InfiniPath port assigned, goes into sent packets */ |
205 | __u32 spi_port; | 206 | __u16 spi_port; |
207 | __u16 spi_subport; | ||
206 | /* | 208 | /* |
207 | * IB MTU, packets IB data must be less than this. | 209 | * IB MTU, packets IB data must be less than this. |
208 | * The MTU is in bytes, and will be a multiple of 4 bytes. | 210 | * The MTU is in bytes, and will be a multiple of 4 bytes. |
@@ -218,7 +220,7 @@ struct ipath_base_info { | |||
218 | __u32 spi_tidcnt; | 220 | __u32 spi_tidcnt; |
219 | /* size of the TID Eager list in infinipath, in entries */ | 221 | /* size of the TID Eager list in infinipath, in entries */ |
220 | __u32 spi_tidegrcnt; | 222 | __u32 spi_tidegrcnt; |
221 | /* size of a single receive header queue entry. */ | 223 | /* size of a single receive header queue entry in words. */ |
222 | __u32 spi_rcvhdrent_size; | 224 | __u32 spi_rcvhdrent_size; |
223 | /* | 225 | /* |
224 | * Count of receive header queue entries allocated. | 226 | * Count of receive header queue entries allocated. |
@@ -310,6 +312,12 @@ struct ipath_base_info { | |||
310 | __u32 spi_filler_for_align; | 312 | __u32 spi_filler_for_align; |
311 | /* address of readonly memory copy of the rcvhdrq tail register. */ | 313 | /* address of readonly memory copy of the rcvhdrq tail register. */ |
312 | __u64 spi_rcvhdr_tailaddr; | 314 | __u64 spi_rcvhdr_tailaddr; |
315 | |||
316 | /* shared memory pages for subports if IPATH_RUNTIME_MASTER is set */ | ||
317 | __u64 spi_subport_uregbase; | ||
318 | __u64 spi_subport_rcvegrbuf; | ||
319 | __u64 spi_subport_rcvhdr_base; | ||
320 | |||
313 | } __attribute__ ((aligned(8))); | 321 | } __attribute__ ((aligned(8))); |
314 | 322 | ||
315 | 323 | ||
@@ -328,12 +336,12 @@ struct ipath_base_info { | |||
328 | 336 | ||
329 | /* | 337 | /* |
330 | * Minor version differences are always compatible | 338 | * Minor version differences are always compatible |
331 | * a within a major version, however if if user software is larger | 339 | * a within a major version, however if user software is larger |
332 | * than driver software, some new features and/or structure fields | 340 | * than driver software, some new features and/or structure fields |
333 | * may not be implemented; the user code must deal with this if it | 341 | * may not be implemented; the user code must deal with this if it |
334 | * cares, or it must abort after initialization reports the difference | 342 | * cares, or it must abort after initialization reports the difference. |
335 | */ | 343 | */ |
336 | #define IPATH_USER_SWMINOR 2 | 344 | #define IPATH_USER_SWMINOR 3 |
337 | 345 | ||
338 | #define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR) | 346 | #define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR) |
339 | 347 | ||
@@ -379,7 +387,16 @@ struct ipath_user_info { | |||
379 | */ | 387 | */ |
380 | __u32 spu_rcvhdrsize; | 388 | __u32 spu_rcvhdrsize; |
381 | 389 | ||
382 | __u64 spu_unused; /* kept for compatible layout */ | 390 | /* |
391 | * If two or more processes wish to share a port, each process | ||
392 | * must set the spu_subport_cnt and spu_subport_id to the same | ||
393 | * values. The only restriction on the spu_subport_id is that | ||
394 | * it be unique for a given node. | ||
395 | */ | ||
396 | __u16 spu_subport_cnt; | ||
397 | __u16 spu_subport_id; | ||
398 | |||
399 | __u32 spu_unused; /* kept for compatible layout */ | ||
383 | 400 | ||
384 | /* | 401 | /* |
385 | * address of struct base_info to write to | 402 | * address of struct base_info to write to |
@@ -398,13 +415,17 @@ struct ipath_user_info { | |||
398 | #define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */ | 415 | #define IPATH_CMD_TID_UPDATE 19 /* update expected TID entries */ |
399 | #define IPATH_CMD_TID_FREE 20 /* free expected TID entries */ | 416 | #define IPATH_CMD_TID_FREE 20 /* free expected TID entries */ |
400 | #define IPATH_CMD_SET_PART_KEY 21 /* add partition key */ | 417 | #define IPATH_CMD_SET_PART_KEY 21 /* add partition key */ |
418 | #define IPATH_CMD_SLAVE_INFO 22 /* return info on slave processes */ | ||
401 | 419 | ||
402 | #define IPATH_CMD_MAX 21 | 420 | #define IPATH_CMD_MAX 22 |
403 | 421 | ||
404 | struct ipath_port_info { | 422 | struct ipath_port_info { |
405 | __u32 num_active; /* number of active units */ | 423 | __u32 num_active; /* number of active units */ |
406 | __u32 unit; /* unit (chip) assigned to caller */ | 424 | __u32 unit; /* unit (chip) assigned to caller */ |
407 | __u32 port; /* port on unit assigned to caller */ | 425 | __u16 port; /* port on unit assigned to caller */ |
426 | __u16 subport; /* subport on unit assigned to caller */ | ||
427 | __u16 num_ports; /* number of ports available on unit */ | ||
428 | __u16 num_subports; /* number of subport slaves opened on port */ | ||
408 | }; | 429 | }; |
409 | 430 | ||
410 | struct ipath_tid_info { | 431 | struct ipath_tid_info { |
@@ -435,6 +456,8 @@ struct ipath_cmd { | |||
435 | __u32 recv_ctrl; | 456 | __u32 recv_ctrl; |
436 | /* partition key to set */ | 457 | /* partition key to set */ |
437 | __u16 part_key; | 458 | __u16 part_key; |
459 | /* user address of __u32 bitmask of active slaves */ | ||
460 | __u64 slave_mask_addr; | ||
438 | } cmd; | 461 | } cmd; |
439 | }; | 462 | }; |
440 | 463 | ||
@@ -596,6 +619,10 @@ struct infinipath_counters { | |||
596 | 619 | ||
597 | /* K_PktFlags bits */ | 620 | /* K_PktFlags bits */ |
598 | #define INFINIPATH_KPF_INTR 0x1 | 621 | #define INFINIPATH_KPF_INTR 0x1 |
622 | #define INFINIPATH_KPF_SUBPORT_MASK 0x3 | ||
623 | #define INFINIPATH_KPF_SUBPORT_SHIFT 1 | ||
624 | |||
625 | #define INFINIPATH_MAX_SUBPORT 4 | ||
599 | 626 | ||
600 | /* SendPIO per-buffer control */ | 627 | /* SendPIO per-buffer control */ |
601 | #define INFINIPATH_SP_TEST 0x40 | 628 | #define INFINIPATH_SP_TEST 0x40 |
@@ -610,7 +637,7 @@ struct ipath_header { | |||
610 | /* | 637 | /* |
611 | * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset - | 638 | * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset - |
612 | * 14 bits before ECO change ~28 Dec 03. After that, Vers 4, | 639 | * 14 bits before ECO change ~28 Dec 03. After that, Vers 4, |
613 | * Port 3, TID 11, offset 14. | 640 | * Port 4, TID 11, offset 13. |
614 | */ | 641 | */ |
615 | __le32 ver_port_tid_offset; | 642 | __le32 ver_port_tid_offset; |
616 | __le16 chksum; | 643 | __le16 chksum; |
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index a01301d0753c..0fe37c5467ac 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -1827,9 +1827,9 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd) | |||
1827 | dma_free_coherent(&dd->pcidev->dev, size, | 1827 | dma_free_coherent(&dd->pcidev->dev, size, |
1828 | base, pd->port_rcvegrbuf_phys[e]); | 1828 | base, pd->port_rcvegrbuf_phys[e]); |
1829 | } | 1829 | } |
1830 | vfree(pd->port_rcvegrbuf); | 1830 | kfree(pd->port_rcvegrbuf); |
1831 | pd->port_rcvegrbuf = NULL; | 1831 | pd->port_rcvegrbuf = NULL; |
1832 | vfree(pd->port_rcvegrbuf_phys); | 1832 | kfree(pd->port_rcvegrbuf_phys); |
1833 | pd->port_rcvegrbuf_phys = NULL; | 1833 | pd->port_rcvegrbuf_phys = NULL; |
1834 | pd->port_rcvegrbuf_chunks = 0; | 1834 | pd->port_rcvegrbuf_chunks = 0; |
1835 | } else if (pd->port_port == 0 && dd->ipath_port0_skbs) { | 1835 | } 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 | vfree(skbs); | 1845 | vfree(skbs); |
1846 | } | 1846 | } |
1847 | kfree(pd->port_tid_pg_list); | 1847 | kfree(pd->port_tid_pg_list); |
1848 | vfree(pd->subport_uregbase); | ||
1849 | vfree(pd->subport_rcvegrbuf); | ||
1850 | vfree(pd->subport_rcvhdr_base); | ||
1848 | kfree(pd); | 1851 | kfree(pd); |
1849 | } | 1852 | } |
1850 | 1853 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 29930e22318e..caf8cb891da4 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -41,6 +41,12 @@ | |||
41 | #include "ipath_kernel.h" | 41 | #include "ipath_kernel.h" |
42 | #include "ipath_common.h" | 42 | #include "ipath_common.h" |
43 | 43 | ||
44 | /* | ||
45 | * mmap64 doesn't allow all 64 bits for 32-bit applications | ||
46 | * so only use the low 43 bits. | ||
47 | */ | ||
48 | #define MMAP64_MASK 0x7FFFFFFFFFFUL | ||
49 | |||
44 | static int ipath_open(struct inode *, struct file *); | 50 | static int ipath_open(struct inode *, struct file *); |
45 | static int ipath_close(struct inode *, struct file *); | 51 | static int ipath_close(struct inode *, struct file *); |
46 | static ssize_t ipath_write(struct file *, const char __user *, size_t, | 52 | static ssize_t ipath_write(struct file *, const char __user *, size_t, |
@@ -57,18 +63,35 @@ static struct file_operations ipath_file_ops = { | |||
57 | .mmap = ipath_mmap | 63 | .mmap = ipath_mmap |
58 | }; | 64 | }; |
59 | 65 | ||
60 | static int ipath_get_base_info(struct ipath_portdata *pd, | 66 | static int ipath_get_base_info(struct file *fp, |
61 | void __user *ubase, size_t ubase_size) | 67 | void __user *ubase, size_t ubase_size) |
62 | { | 68 | { |
69 | struct ipath_portdata *pd = port_fp(fp); | ||
63 | int ret = 0; | 70 | int ret = 0; |
64 | struct ipath_base_info *kinfo = NULL; | 71 | struct ipath_base_info *kinfo = NULL; |
65 | struct ipath_devdata *dd = pd->port_dd; | 72 | struct ipath_devdata *dd = pd->port_dd; |
73 | unsigned subport_cnt; | ||
74 | int shared, master; | ||
75 | size_t sz; | ||
76 | |||
77 | subport_cnt = pd->port_subport_cnt; | ||
78 | if (!subport_cnt) { | ||
79 | shared = 0; | ||
80 | master = 0; | ||
81 | subport_cnt = 1; | ||
82 | } else { | ||
83 | shared = 1; | ||
84 | master = !subport_fp(fp); | ||
85 | } | ||
66 | 86 | ||
67 | if (ubase_size < sizeof(*kinfo)) { | 87 | sz = sizeof(*kinfo); |
88 | /* If port sharing is not requested, allow the old size structure */ | ||
89 | if (!shared) | ||
90 | sz -= 3 * sizeof(u64); | ||
91 | if (ubase_size < sz) { | ||
68 | ipath_cdbg(PROC, | 92 | ipath_cdbg(PROC, |
69 | "Base size %lu, need %lu (version mismatch?)\n", | 93 | "Base size %zu, need %zu (version mismatch?)\n", |
70 | (unsigned long) ubase_size, | 94 | ubase_size, sz); |
71 | (unsigned long) sizeof(*kinfo)); | ||
72 | ret = -EINVAL; | 95 | ret = -EINVAL; |
73 | goto bail; | 96 | goto bail; |
74 | } | 97 | } |
@@ -95,7 +118,9 @@ static int ipath_get_base_info(struct ipath_portdata *pd, | |||
95 | kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk; | 118 | kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk; |
96 | kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen / | 119 | kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen / |
97 | pd->port_rcvegrbuf_chunks; | 120 | pd->port_rcvegrbuf_chunks; |
98 | kinfo->spi_tidcnt = dd->ipath_rcvtidcnt; | 121 | kinfo->spi_tidcnt = dd->ipath_rcvtidcnt / subport_cnt; |
122 | if (master) | ||
123 | kinfo->spi_tidcnt += dd->ipath_rcvtidcnt % subport_cnt; | ||
99 | /* | 124 | /* |
100 | * for this use, may be ipath_cfgports summed over all chips that | 125 | * for this use, may be ipath_cfgports summed over all chips that |
101 | * are are configured and present | 126 | * are are configured and present |
@@ -118,31 +143,76 @@ static int ipath_get_base_info(struct ipath_portdata *pd, | |||
118 | * page_address() macro worked, but in 2.6.11, even that returns the | 143 | * page_address() macro worked, but in 2.6.11, even that returns the |
119 | * full 64 bit address (upper bits all 1's). So far, using the | 144 | * full 64 bit address (upper bits all 1's). So far, using the |
120 | * physical addresses (or chip offsets, for chip mapping) works, but | 145 | * physical addresses (or chip offsets, for chip mapping) works, but |
121 | * no doubt some future kernel release will chang that, and we'll be | 146 | * no doubt some future kernel release will change that, and we'll be |
122 | * on to yet another method of dealing with this | 147 | * on to yet another method of dealing with this. |
123 | */ | 148 | */ |
124 | kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys; | 149 | kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys; |
125 | kinfo->spi_rcvhdr_tailaddr = (u64)pd->port_rcvhdrqtailaddr_phys; | 150 | kinfo->spi_rcvhdr_tailaddr = (u64) pd->port_rcvhdrqtailaddr_phys; |
126 | kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys; | 151 | kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys; |
127 | kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys; | 152 | kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys; |
128 | kinfo->spi_status = (u64) kinfo->spi_pioavailaddr + | 153 | kinfo->spi_status = (u64) kinfo->spi_pioavailaddr + |
129 | (void *) dd->ipath_statusp - | 154 | (void *) dd->ipath_statusp - |
130 | (void *) dd->ipath_pioavailregs_dma; | 155 | (void *) dd->ipath_pioavailregs_dma; |
131 | kinfo->spi_piobufbase = (u64) pd->port_piobufs; | 156 | if (!shared) { |
132 | kinfo->__spi_uregbase = | 157 | kinfo->spi_piocnt = dd->ipath_pbufsport; |
133 | dd->ipath_uregbase + dd->ipath_palign * pd->port_port; | 158 | kinfo->spi_piobufbase = (u64) pd->port_piobufs; |
159 | kinfo->__spi_uregbase = (u64) dd->ipath_uregbase + | ||
160 | dd->ipath_palign * pd->port_port; | ||
161 | } else if (master) { | ||
162 | kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) + | ||
163 | (dd->ipath_pbufsport % subport_cnt); | ||
164 | /* Master's PIO buffers are after all the slave's */ | ||
165 | kinfo->spi_piobufbase = (u64) pd->port_piobufs + | ||
166 | dd->ipath_palign * | ||
167 | (dd->ipath_pbufsport - kinfo->spi_piocnt); | ||
168 | kinfo->__spi_uregbase = (u64) dd->ipath_uregbase + | ||
169 | dd->ipath_palign * pd->port_port; | ||
170 | } else { | ||
171 | unsigned slave = subport_fp(fp) - 1; | ||
134 | 172 | ||
135 | kinfo->spi_pioindex = dd->ipath_pbufsport * (pd->port_port - 1); | 173 | kinfo->spi_piocnt = dd->ipath_pbufsport / subport_cnt; |
136 | kinfo->spi_piocnt = dd->ipath_pbufsport; | 174 | kinfo->spi_piobufbase = (u64) pd->port_piobufs + |
175 | dd->ipath_palign * kinfo->spi_piocnt * slave; | ||
176 | kinfo->__spi_uregbase = ((u64) pd->subport_uregbase + | ||
177 | PAGE_SIZE * slave) & MMAP64_MASK; | ||
178 | |||
179 | kinfo->spi_rcvhdr_base = ((u64) pd->subport_rcvhdr_base + | ||
180 | pd->port_rcvhdrq_size * slave) & MMAP64_MASK; | ||
181 | kinfo->spi_rcvhdr_tailaddr = | ||
182 | (u64) pd->port_rcvhdrqtailaddr_phys & MMAP64_MASK; | ||
183 | kinfo->spi_rcv_egrbufs = ((u64) pd->subport_rcvegrbuf + | ||
184 | dd->ipath_rcvegrcnt * dd->ipath_rcvegrbufsize * slave) & | ||
185 | MMAP64_MASK; | ||
186 | } | ||
187 | |||
188 | kinfo->spi_pioindex = (kinfo->spi_piobufbase - dd->ipath_piobufbase) / | ||
189 | dd->ipath_palign; | ||
137 | kinfo->spi_pioalign = dd->ipath_palign; | 190 | kinfo->spi_pioalign = dd->ipath_palign; |
138 | 191 | ||
139 | kinfo->spi_qpair = IPATH_KD_QP; | 192 | kinfo->spi_qpair = IPATH_KD_QP; |
140 | kinfo->spi_piosize = dd->ipath_ibmaxlen; | 193 | kinfo->spi_piosize = dd->ipath_ibmaxlen; |
141 | kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */ | 194 | kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */ |
142 | kinfo->spi_port = pd->port_port; | 195 | kinfo->spi_port = pd->port_port; |
196 | kinfo->spi_subport = subport_fp(fp); | ||
143 | kinfo->spi_sw_version = IPATH_KERN_SWVERSION; | 197 | kinfo->spi_sw_version = IPATH_KERN_SWVERSION; |
144 | kinfo->spi_hw_version = dd->ipath_revision; | 198 | kinfo->spi_hw_version = dd->ipath_revision; |
145 | 199 | ||
200 | if (master) { | ||
201 | kinfo->spi_runtime_flags |= IPATH_RUNTIME_MASTER; | ||
202 | kinfo->spi_subport_uregbase = | ||
203 | (u64) pd->subport_uregbase & MMAP64_MASK; | ||
204 | kinfo->spi_subport_rcvegrbuf = | ||
205 | (u64) pd->subport_rcvegrbuf & MMAP64_MASK; | ||
206 | kinfo->spi_subport_rcvhdr_base = | ||
207 | (u64) pd->subport_rcvhdr_base & MMAP64_MASK; | ||
208 | ipath_cdbg(PROC, "port %u flags %x %llx %llx %llx\n", | ||
209 | kinfo->spi_port, | ||
210 | kinfo->spi_runtime_flags, | ||
211 | kinfo->spi_subport_uregbase, | ||
212 | kinfo->spi_subport_rcvegrbuf, | ||
213 | kinfo->spi_subport_rcvhdr_base); | ||
214 | } | ||
215 | |||
146 | if (copy_to_user(ubase, kinfo, sizeof(*kinfo))) | 216 | if (copy_to_user(ubase, kinfo, sizeof(*kinfo))) |
147 | ret = -EFAULT; | 217 | ret = -EFAULT; |
148 | 218 | ||
@@ -154,6 +224,7 @@ bail: | |||
154 | /** | 224 | /** |
155 | * ipath_tid_update - update a port TID | 225 | * ipath_tid_update - update a port TID |
156 | * @pd: the port | 226 | * @pd: the port |
227 | * @fp: the ipath device file | ||
157 | * @ti: the TID information | 228 | * @ti: the TID information |
158 | * | 229 | * |
159 | * The new implementation as of Oct 2004 is that the driver assigns | 230 | * The new implementation as of Oct 2004 is that the driver assigns |
@@ -176,11 +247,11 @@ bail: | |||
176 | * virtually contiguous pages, that should change to improve | 247 | * virtually contiguous pages, that should change to improve |
177 | * performance. | 248 | * performance. |
178 | */ | 249 | */ |
179 | static int ipath_tid_update(struct ipath_portdata *pd, | 250 | static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp, |
180 | const struct ipath_tid_info *ti) | 251 | const struct ipath_tid_info *ti) |
181 | { | 252 | { |
182 | int ret = 0, ntids; | 253 | int ret = 0, ntids; |
183 | u32 tid, porttid, cnt, i, tidcnt; | 254 | u32 tid, porttid, cnt, i, tidcnt, tidoff; |
184 | u16 *tidlist; | 255 | u16 *tidlist; |
185 | struct ipath_devdata *dd = pd->port_dd; | 256 | struct ipath_devdata *dd = pd->port_dd; |
186 | u64 physaddr; | 257 | u64 physaddr; |
@@ -188,6 +259,7 @@ static int ipath_tid_update(struct ipath_portdata *pd, | |||
188 | u64 __iomem *tidbase; | 259 | u64 __iomem *tidbase; |
189 | unsigned long tidmap[8]; | 260 | unsigned long tidmap[8]; |
190 | struct page **pagep = NULL; | 261 | struct page **pagep = NULL; |
262 | unsigned subport = subport_fp(fp); | ||
191 | 263 | ||
192 | if (!dd->ipath_pageshadow) { | 264 | if (!dd->ipath_pageshadow) { |
193 | ret = -ENOMEM; | 265 | ret = -ENOMEM; |
@@ -204,20 +276,34 @@ static int ipath_tid_update(struct ipath_portdata *pd, | |||
204 | ret = -EFAULT; | 276 | ret = -EFAULT; |
205 | goto done; | 277 | goto done; |
206 | } | 278 | } |
207 | tidcnt = dd->ipath_rcvtidcnt; | 279 | porttid = pd->port_port * dd->ipath_rcvtidcnt; |
208 | if (cnt >= tidcnt) { | 280 | if (!pd->port_subport_cnt) { |
281 | tidcnt = dd->ipath_rcvtidcnt; | ||
282 | tid = pd->port_tidcursor; | ||
283 | tidoff = 0; | ||
284 | } else if (!subport) { | ||
285 | tidcnt = (dd->ipath_rcvtidcnt / pd->port_subport_cnt) + | ||
286 | (dd->ipath_rcvtidcnt % pd->port_subport_cnt); | ||
287 | tidoff = dd->ipath_rcvtidcnt - tidcnt; | ||
288 | porttid += tidoff; | ||
289 | tid = tidcursor_fp(fp); | ||
290 | } else { | ||
291 | tidcnt = dd->ipath_rcvtidcnt / pd->port_subport_cnt; | ||
292 | tidoff = tidcnt * (subport - 1); | ||
293 | porttid += tidoff; | ||
294 | tid = tidcursor_fp(fp); | ||
295 | } | ||
296 | if (cnt > tidcnt) { | ||
209 | /* make sure it all fits in port_tid_pg_list */ | 297 | /* make sure it all fits in port_tid_pg_list */ |
210 | dev_info(&dd->pcidev->dev, "Process tried to allocate %u " | 298 | dev_info(&dd->pcidev->dev, "Process tried to allocate %u " |
211 | "TIDs, only trying max (%u)\n", cnt, tidcnt); | 299 | "TIDs, only trying max (%u)\n", cnt, tidcnt); |
212 | cnt = tidcnt; | 300 | cnt = tidcnt; |
213 | } | 301 | } |
214 | pagep = (struct page **)pd->port_tid_pg_list; | 302 | pagep = &((struct page **) pd->port_tid_pg_list)[tidoff]; |
215 | tidlist = (u16 *) (&pagep[cnt]); | 303 | tidlist = &((u16 *) &pagep[dd->ipath_rcvtidcnt])[tidoff]; |
216 | 304 | ||
217 | memset(tidmap, 0, sizeof(tidmap)); | 305 | memset(tidmap, 0, sizeof(tidmap)); |
218 | tid = pd->port_tidcursor; | ||
219 | /* before decrement; chip actual # */ | 306 | /* before decrement; chip actual # */ |
220 | porttid = pd->port_port * tidcnt; | ||
221 | ntids = tidcnt; | 307 | ntids = tidcnt; |
222 | tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) + | 308 | tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) + |
223 | dd->ipath_rcvtidbase + | 309 | dd->ipath_rcvtidbase + |
@@ -274,9 +360,9 @@ static int ipath_tid_update(struct ipath_portdata *pd, | |||
274 | ret = -ENOMEM; | 360 | ret = -ENOMEM; |
275 | break; | 361 | break; |
276 | } | 362 | } |
277 | tidlist[i] = tid; | 363 | tidlist[i] = tid + tidoff; |
278 | ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, " | 364 | ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, " |
279 | "vaddr %lx\n", i, tid, vaddr); | 365 | "vaddr %lx\n", i, tid + tidoff, vaddr); |
280 | /* we "know" system pages and TID pages are same size */ | 366 | /* we "know" system pages and TID pages are same size */ |
281 | dd->ipath_pageshadow[porttid + tid] = pagep[i]; | 367 | dd->ipath_pageshadow[porttid + tid] = pagep[i]; |
282 | /* | 368 | /* |
@@ -341,7 +427,10 @@ static int ipath_tid_update(struct ipath_portdata *pd, | |||
341 | } | 427 | } |
342 | if (tid == tidcnt) | 428 | if (tid == tidcnt) |
343 | tid = 0; | 429 | tid = 0; |
344 | pd->port_tidcursor = tid; | 430 | if (!pd->port_subport_cnt) |
431 | pd->port_tidcursor = tid; | ||
432 | else | ||
433 | tidcursor_fp(fp) = tid; | ||
345 | } | 434 | } |
346 | 435 | ||
347 | done: | 436 | done: |
@@ -354,6 +443,7 @@ done: | |||
354 | /** | 443 | /** |
355 | * ipath_tid_free - free a port TID | 444 | * ipath_tid_free - free a port TID |
356 | * @pd: the port | 445 | * @pd: the port |
446 | * @subport: the subport | ||
357 | * @ti: the TID info | 447 | * @ti: the TID info |
358 | * | 448 | * |
359 | * right now we are unlocking one page at a time, but since | 449 | * right now we are unlocking one page at a time, but since |
@@ -367,7 +457,7 @@ done: | |||
367 | * they pass in to us. | 457 | * they pass in to us. |
368 | */ | 458 | */ |
369 | 459 | ||
370 | static int ipath_tid_free(struct ipath_portdata *pd, | 460 | static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport, |
371 | const struct ipath_tid_info *ti) | 461 | const struct ipath_tid_info *ti) |
372 | { | 462 | { |
373 | int ret = 0; | 463 | int ret = 0; |
@@ -388,11 +478,20 @@ static int ipath_tid_free(struct ipath_portdata *pd, | |||
388 | } | 478 | } |
389 | 479 | ||
390 | porttid = pd->port_port * dd->ipath_rcvtidcnt; | 480 | porttid = pd->port_port * dd->ipath_rcvtidcnt; |
481 | if (!pd->port_subport_cnt) | ||
482 | tidcnt = dd->ipath_rcvtidcnt; | ||
483 | else if (!subport) { | ||
484 | tidcnt = (dd->ipath_rcvtidcnt / pd->port_subport_cnt) + | ||
485 | (dd->ipath_rcvtidcnt % pd->port_subport_cnt); | ||
486 | porttid += dd->ipath_rcvtidcnt - tidcnt; | ||
487 | } else { | ||
488 | tidcnt = dd->ipath_rcvtidcnt / pd->port_subport_cnt; | ||
489 | porttid += tidcnt * (subport - 1); | ||
490 | } | ||
391 | tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + | 491 | tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) + |
392 | dd->ipath_rcvtidbase + | 492 | dd->ipath_rcvtidbase + |
393 | porttid * sizeof(*tidbase)); | 493 | porttid * sizeof(*tidbase)); |
394 | 494 | ||
395 | tidcnt = dd->ipath_rcvtidcnt; | ||
396 | limit = sizeof(tidmap) * BITS_PER_BYTE; | 495 | limit = sizeof(tidmap) * BITS_PER_BYTE; |
397 | if (limit > tidcnt) | 496 | if (limit > tidcnt) |
398 | /* just in case size changes in future */ | 497 | /* just in case size changes in future */ |
@@ -581,20 +680,24 @@ bail: | |||
581 | /** | 680 | /** |
582 | * ipath_manage_rcvq - manage a port's receive queue | 681 | * ipath_manage_rcvq - manage a port's receive queue |
583 | * @pd: the port | 682 | * @pd: the port |
683 | * @subport: the subport | ||
584 | * @start_stop: action to carry out | 684 | * @start_stop: action to carry out |
585 | * | 685 | * |
586 | * start_stop == 0 disables receive on the port, for use in queue | 686 | * start_stop == 0 disables receive on the port, for use in queue |
587 | * overflow conditions. start_stop==1 re-enables, to be used to | 687 | * overflow conditions. start_stop==1 re-enables, to be used to |
588 | * re-init the software copy of the head register | 688 | * re-init the software copy of the head register |
589 | */ | 689 | */ |
590 | static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop) | 690 | static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport, |
691 | int start_stop) | ||
591 | { | 692 | { |
592 | struct ipath_devdata *dd = pd->port_dd; | 693 | struct ipath_devdata *dd = pd->port_dd; |
593 | u64 tval; | 694 | u64 tval; |
594 | 695 | ||
595 | ipath_cdbg(PROC, "%sabling rcv for unit %u port %u\n", | 696 | ipath_cdbg(PROC, "%sabling rcv for unit %u port %u:%u\n", |
596 | start_stop ? "en" : "dis", dd->ipath_unit, | 697 | start_stop ? "en" : "dis", dd->ipath_unit, |
597 | pd->port_port); | 698 | pd->port_port, subport); |
699 | if (subport) | ||
700 | goto bail; | ||
598 | /* atomically clear receive enable port. */ | 701 | /* atomically clear receive enable port. */ |
599 | if (start_stop) { | 702 | if (start_stop) { |
600 | /* | 703 | /* |
@@ -630,6 +733,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop) | |||
630 | tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); | 733 | tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); |
631 | } | 734 | } |
632 | /* always; new head should be equal to new tail; see above */ | 735 | /* always; new head should be equal to new tail; see above */ |
736 | bail: | ||
633 | return 0; | 737 | return 0; |
634 | } | 738 | } |
635 | 739 | ||
@@ -687,6 +791,36 @@ static void ipath_clean_part_key(struct ipath_portdata *pd, | |||
687 | } | 791 | } |
688 | } | 792 | } |
689 | 793 | ||
794 | /* | ||
795 | * Initialize the port data with the receive buffer sizes | ||
796 | * so this can be done while the master port is locked. | ||
797 | * Otherwise, there is a race with a slave opening the port | ||
798 | * and seeing these fields uninitialized. | ||
799 | */ | ||
800 | static void init_user_egr_sizes(struct ipath_portdata *pd) | ||
801 | { | ||
802 | struct ipath_devdata *dd = pd->port_dd; | ||
803 | unsigned egrperchunk, egrcnt, size; | ||
804 | |||
805 | /* | ||
806 | * to avoid wasting a lot of memory, we allocate 32KB chunks of | ||
807 | * physically contiguous memory, advance through it until used up | ||
808 | * and then allocate more. Of course, we need memory to store those | ||
809 | * extra pointers, now. Started out with 256KB, but under heavy | ||
810 | * memory pressure (creating large files and then copying them over | ||
811 | * NFS while doing lots of MPI jobs), we hit some allocation | ||
812 | * failures, even though we can sleep... (2.6.10) Still get | ||
813 | * failures at 64K. 32K is the lowest we can go without wasting | ||
814 | * additional memory. | ||
815 | */ | ||
816 | size = 0x8000; | ||
817 | egrperchunk = size / dd->ipath_rcvegrbufsize; | ||
818 | egrcnt = dd->ipath_rcvegrcnt; | ||
819 | pd->port_rcvegrbuf_chunks = (egrcnt + egrperchunk - 1) / egrperchunk; | ||
820 | pd->port_rcvegrbufs_perchunk = egrperchunk; | ||
821 | pd->port_rcvegrbuf_size = size; | ||
822 | } | ||
823 | |||
690 | /** | 824 | /** |
691 | * ipath_create_user_egr - allocate eager TID buffers | 825 | * ipath_create_user_egr - allocate eager TID buffers |
692 | * @pd: the port to allocate TID buffers for | 826 | * @pd: the port to allocate TID buffers for |
@@ -702,7 +836,7 @@ static void ipath_clean_part_key(struct ipath_portdata *pd, | |||
702 | static int ipath_create_user_egr(struct ipath_portdata *pd) | 836 | static int ipath_create_user_egr(struct ipath_portdata *pd) |
703 | { | 837 | { |
704 | struct ipath_devdata *dd = pd->port_dd; | 838 | struct ipath_devdata *dd = pd->port_dd; |
705 | unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff; | 839 | unsigned e, egrcnt, egrperchunk, chunk, egrsize, egroff; |
706 | size_t size; | 840 | size_t size; |
707 | int ret; | 841 | int ret; |
708 | gfp_t gfp_flags; | 842 | gfp_t gfp_flags; |
@@ -722,31 +856,18 @@ static int ipath_create_user_egr(struct ipath_portdata *pd) | |||
722 | ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid " | 856 | ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid " |
723 | "offset %x, egrsize %u\n", egrcnt, egroff, egrsize); | 857 | "offset %x, egrsize %u\n", egrcnt, egroff, egrsize); |
724 | 858 | ||
725 | /* | 859 | chunk = pd->port_rcvegrbuf_chunks; |
726 | * to avoid wasting a lot of memory, we allocate 32KB chunks of | 860 | egrperchunk = pd->port_rcvegrbufs_perchunk; |
727 | * physically contiguous memory, advance through it until used up | 861 | size = pd->port_rcvegrbuf_size; |
728 | * and then allocate more. Of course, we need memory to store those | 862 | pd->port_rcvegrbuf = kmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]), |
729 | * extra pointers, now. Started out with 256KB, but under heavy | 863 | GFP_KERNEL); |
730 | * memory pressure (creating large files and then copying them over | ||
731 | * NFS while doing lots of MPI jobs), we hit some allocation | ||
732 | * failures, even though we can sleep... (2.6.10) Still get | ||
733 | * failures at 64K. 32K is the lowest we can go without wasting | ||
734 | * additional memory. | ||
735 | */ | ||
736 | size = 0x8000; | ||
737 | alloced = ALIGN(egrsize * egrcnt, size); | ||
738 | egrperchunk = size / egrsize; | ||
739 | chunk = (egrcnt + egrperchunk - 1) / egrperchunk; | ||
740 | pd->port_rcvegrbuf_chunks = chunk; | ||
741 | pd->port_rcvegrbufs_perchunk = egrperchunk; | ||
742 | pd->port_rcvegrbuf_size = size; | ||
743 | pd->port_rcvegrbuf = vmalloc(chunk * sizeof(pd->port_rcvegrbuf[0])); | ||
744 | if (!pd->port_rcvegrbuf) { | 864 | if (!pd->port_rcvegrbuf) { |
745 | ret = -ENOMEM; | 865 | ret = -ENOMEM; |
746 | goto bail; | 866 | goto bail; |
747 | } | 867 | } |
748 | pd->port_rcvegrbuf_phys = | 868 | pd->port_rcvegrbuf_phys = |
749 | vmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0])); | 869 | kmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]), |
870 | GFP_KERNEL); | ||
750 | if (!pd->port_rcvegrbuf_phys) { | 871 | if (!pd->port_rcvegrbuf_phys) { |
751 | ret = -ENOMEM; | 872 | ret = -ENOMEM; |
752 | goto bail_rcvegrbuf; | 873 | goto bail_rcvegrbuf; |
@@ -791,97 +912,15 @@ bail_rcvegrbuf_phys: | |||
791 | pd->port_rcvegrbuf_phys[e]); | 912 | pd->port_rcvegrbuf_phys[e]); |
792 | 913 | ||
793 | } | 914 | } |
794 | vfree(pd->port_rcvegrbuf_phys); | 915 | kfree(pd->port_rcvegrbuf_phys); |
795 | pd->port_rcvegrbuf_phys = NULL; | 916 | pd->port_rcvegrbuf_phys = NULL; |
796 | bail_rcvegrbuf: | 917 | bail_rcvegrbuf: |
797 | vfree(pd->port_rcvegrbuf); | 918 | kfree(pd->port_rcvegrbuf); |
798 | pd->port_rcvegrbuf = NULL; | 919 | pd->port_rcvegrbuf = NULL; |
799 | bail: | 920 | bail: |
800 | return ret; | 921 | return ret; |
801 | } | 922 | } |
802 | 923 | ||
803 | static int ipath_do_user_init(struct ipath_portdata *pd, | ||
804 | const struct ipath_user_info *uinfo) | ||
805 | { | ||
806 | int ret = 0; | ||
807 | struct ipath_devdata *dd = pd->port_dd; | ||
808 | u32 head32; | ||
809 | |||
810 | /* for now, if major version is different, bail */ | ||
811 | if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) { | ||
812 | dev_info(&dd->pcidev->dev, | ||
813 | "User major version %d not same as driver " | ||
814 | "major %d\n", uinfo->spu_userversion >> 16, | ||
815 | IPATH_USER_SWMAJOR); | ||
816 | ret = -ENODEV; | ||
817 | goto done; | ||
818 | } | ||
819 | |||
820 | if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR) | ||
821 | ipath_dbg("User minor version %d not same as driver " | ||
822 | "minor %d\n", uinfo->spu_userversion & 0xffff, | ||
823 | IPATH_USER_SWMINOR); | ||
824 | |||
825 | if (uinfo->spu_rcvhdrsize) { | ||
826 | ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize); | ||
827 | if (ret) | ||
828 | goto done; | ||
829 | } | ||
830 | |||
831 | /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */ | ||
832 | |||
833 | /* for right now, kernel piobufs are at end, so port 1 is at 0 */ | ||
834 | pd->port_piobufs = dd->ipath_piobufbase + | ||
835 | dd->ipath_pbufsport * (pd->port_port - | ||
836 | 1) * dd->ipath_palign; | ||
837 | ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n", | ||
838 | pd->port_port, pd->port_piobufs); | ||
839 | |||
840 | /* | ||
841 | * Now allocate the rcvhdr Q and eager TIDs; skip the TID | ||
842 | * array for time being. If pd->port_port > chip-supported, | ||
843 | * we need to do extra stuff here to handle by handling overflow | ||
844 | * through port 0, someday | ||
845 | */ | ||
846 | ret = ipath_create_rcvhdrq(dd, pd); | ||
847 | if (!ret) | ||
848 | ret = ipath_create_user_egr(pd); | ||
849 | if (ret) | ||
850 | goto done; | ||
851 | |||
852 | /* | ||
853 | * set the eager head register for this port to the current values | ||
854 | * of the tail pointers, since we don't know if they were | ||
855 | * updated on last use of the port. | ||
856 | */ | ||
857 | head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port); | ||
858 | ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port); | ||
859 | dd->ipath_lastegrheads[pd->port_port] = -1; | ||
860 | dd->ipath_lastrcvhdrqtails[pd->port_port] = -1; | ||
861 | ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n", | ||
862 | pd->port_port, head32); | ||
863 | pd->port_tidcursor = 0; /* start at beginning after open */ | ||
864 | /* | ||
865 | * now enable the port; the tail registers will be written to memory | ||
866 | * by the chip as soon as it sees the write to | ||
867 | * dd->ipath_kregs->kr_rcvctrl. The update only happens on | ||
868 | * transition from 0 to 1, so clear it first, then set it as part of | ||
869 | * enabling the port. This will (very briefly) affect any other | ||
870 | * open ports, but it shouldn't be long enough to be an issue. | ||
871 | * We explictly set the in-memory copy to 0 beforehand, so we don't | ||
872 | * have to wait to be sure the DMA update has happened. | ||
873 | */ | ||
874 | *pd->port_rcvhdrtail_kvaddr = 0ULL; | ||
875 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, | ||
876 | &dd->ipath_rcvctrl); | ||
877 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
878 | dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD); | ||
879 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
880 | dd->ipath_rcvctrl); | ||
881 | done: | ||
882 | return ret; | ||
883 | } | ||
884 | |||
885 | 924 | ||
886 | /* common code for the mappings on dma_alloc_coherent mem */ | 925 | /* common code for the mappings on dma_alloc_coherent mem */ |
887 | static int ipath_mmap_mem(struct vm_area_struct *vma, | 926 | static int ipath_mmap_mem(struct vm_area_struct *vma, |
@@ -957,7 +996,8 @@ static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd, | |||
957 | 996 | ||
958 | static int mmap_piobufs(struct vm_area_struct *vma, | 997 | static int mmap_piobufs(struct vm_area_struct *vma, |
959 | struct ipath_devdata *dd, | 998 | struct ipath_devdata *dd, |
960 | struct ipath_portdata *pd) | 999 | struct ipath_portdata *pd, |
1000 | unsigned piobufs, unsigned piocnt) | ||
961 | { | 1001 | { |
962 | unsigned long phys; | 1002 | unsigned long phys; |
963 | int ret; | 1003 | int ret; |
@@ -968,16 +1008,15 @@ static int mmap_piobufs(struct vm_area_struct *vma, | |||
968 | * process data, and catches users who might try to read the i/o | 1008 | * process data, and catches users who might try to read the i/o |
969 | * space due to a bug. | 1009 | * space due to a bug. |
970 | */ | 1010 | */ |
971 | if ((vma->vm_end - vma->vm_start) > | 1011 | if ((vma->vm_end - vma->vm_start) > (piocnt * dd->ipath_palign)) { |
972 | (dd->ipath_pbufsport * dd->ipath_palign)) { | ||
973 | dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: " | 1012 | dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: " |
974 | "reqlen %lx > PAGE\n", | 1013 | "reqlen %lx > PAGE\n", |
975 | vma->vm_end - vma->vm_start); | 1014 | vma->vm_end - vma->vm_start); |
976 | ret = -EFAULT; | 1015 | ret = -EINVAL; |
977 | goto bail; | 1016 | goto bail; |
978 | } | 1017 | } |
979 | 1018 | ||
980 | phys = dd->ipath_physaddr + pd->port_piobufs; | 1019 | phys = dd->ipath_physaddr + piobufs; |
981 | 1020 | ||
982 | /* | 1021 | /* |
983 | * Don't mark this as non-cached, or we don't get the | 1022 | * Don't mark this as non-cached, or we don't get the |
@@ -1021,7 +1060,7 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma, | |||
1021 | "reqlen %lx > actual %lx\n", | 1060 | "reqlen %lx > actual %lx\n", |
1022 | vma->vm_end - vma->vm_start, | 1061 | vma->vm_end - vma->vm_start, |
1023 | (unsigned long) total_size); | 1062 | (unsigned long) total_size); |
1024 | ret = -EFAULT; | 1063 | ret = -EINVAL; |
1025 | goto bail; | 1064 | goto bail; |
1026 | } | 1065 | } |
1027 | 1066 | ||
@@ -1049,6 +1088,122 @@ bail: | |||
1049 | return ret; | 1088 | return ret; |
1050 | } | 1089 | } |
1051 | 1090 | ||
1091 | /* | ||
1092 | * ipath_file_vma_nopage - handle a VMA page fault. | ||
1093 | */ | ||
1094 | static struct page *ipath_file_vma_nopage(struct vm_area_struct *vma, | ||
1095 | unsigned long address, int *type) | ||
1096 | { | ||
1097 | unsigned long offset = address - vma->vm_start; | ||
1098 | struct page *page = NOPAGE_SIGBUS; | ||
1099 | void *pageptr; | ||
1100 | |||
1101 | /* | ||
1102 | * Convert the vmalloc address into a struct page. | ||
1103 | */ | ||
1104 | pageptr = (void *)(offset + (vma->vm_pgoff << PAGE_SHIFT)); | ||
1105 | page = vmalloc_to_page(pageptr); | ||
1106 | if (!page) | ||
1107 | goto out; | ||
1108 | |||
1109 | /* Increment the reference count. */ | ||
1110 | get_page(page); | ||
1111 | if (type) | ||
1112 | *type = VM_FAULT_MINOR; | ||
1113 | out: | ||
1114 | return page; | ||
1115 | } | ||
1116 | |||
1117 | static struct vm_operations_struct ipath_file_vm_ops = { | ||
1118 | .nopage = ipath_file_vma_nopage, | ||
1119 | }; | ||
1120 | |||
1121 | static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr, | ||
1122 | struct ipath_portdata *pd, unsigned subport) | ||
1123 | { | ||
1124 | unsigned long len; | ||
1125 | struct ipath_devdata *dd; | ||
1126 | void *addr; | ||
1127 | size_t size; | ||
1128 | int ret; | ||
1129 | |||
1130 | /* If the port is not shared, all addresses should be physical */ | ||
1131 | if (!pd->port_subport_cnt) { | ||
1132 | ret = -EINVAL; | ||
1133 | goto bail; | ||
1134 | } | ||
1135 | |||
1136 | dd = pd->port_dd; | ||
1137 | size = pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size; | ||
1138 | |||
1139 | /* | ||
1140 | * Master has all the slave uregbase, rcvhdrq, and | ||
1141 | * rcvegrbufs mmapped. | ||
1142 | */ | ||
1143 | if (subport == 0) { | ||
1144 | unsigned num_slaves = pd->port_subport_cnt - 1; | ||
1145 | |||
1146 | if (pgaddr == ((u64) pd->subport_uregbase & MMAP64_MASK)) { | ||
1147 | addr = pd->subport_uregbase; | ||
1148 | size = PAGE_SIZE * num_slaves; | ||
1149 | } else if (pgaddr == ((u64) pd->subport_rcvhdr_base & | ||
1150 | MMAP64_MASK)) { | ||
1151 | addr = pd->subport_rcvhdr_base; | ||
1152 | size = pd->port_rcvhdrq_size * num_slaves; | ||
1153 | } else if (pgaddr == ((u64) pd->subport_rcvegrbuf & | ||
1154 | MMAP64_MASK)) { | ||
1155 | addr = pd->subport_rcvegrbuf; | ||
1156 | size *= num_slaves; | ||
1157 | } else { | ||
1158 | ret = -EINVAL; | ||
1159 | goto bail; | ||
1160 | } | ||
1161 | } else if (pgaddr == (((u64) pd->subport_uregbase + | ||
1162 | PAGE_SIZE * (subport - 1)) & MMAP64_MASK)) { | ||
1163 | addr = pd->subport_uregbase + PAGE_SIZE * (subport - 1); | ||
1164 | size = PAGE_SIZE; | ||
1165 | } else if (pgaddr == (((u64) pd->subport_rcvhdr_base + | ||
1166 | pd->port_rcvhdrq_size * (subport - 1)) & | ||
1167 | MMAP64_MASK)) { | ||
1168 | addr = pd->subport_rcvhdr_base + | ||
1169 | pd->port_rcvhdrq_size * (subport - 1); | ||
1170 | size = pd->port_rcvhdrq_size; | ||
1171 | } else if (pgaddr == (((u64) pd->subport_rcvegrbuf + | ||
1172 | size * (subport - 1)) & MMAP64_MASK)) { | ||
1173 | addr = pd->subport_rcvegrbuf + size * (subport - 1); | ||
1174 | /* rcvegrbufs are read-only on the slave */ | ||
1175 | if (vma->vm_flags & VM_WRITE) { | ||
1176 | dev_info(&dd->pcidev->dev, | ||
1177 | "Can't map eager buffers as " | ||
1178 | "writable (flags=%lx)\n", vma->vm_flags); | ||
1179 | ret = -EPERM; | ||
1180 | goto bail; | ||
1181 | } | ||
1182 | /* | ||
1183 | * Don't allow permission to later change to writeable | ||
1184 | * with mprotect. | ||
1185 | */ | ||
1186 | vma->vm_flags &= ~VM_MAYWRITE; | ||
1187 | } else { | ||
1188 | ret = -EINVAL; | ||
1189 | goto bail; | ||
1190 | } | ||
1191 | len = vma->vm_end - vma->vm_start; | ||
1192 | if (len > size) { | ||
1193 | ipath_cdbg(MM, "FAIL: reqlen %lx > %zx\n", len, size); | ||
1194 | ret = -EINVAL; | ||
1195 | goto bail; | ||
1196 | } | ||
1197 | |||
1198 | vma->vm_pgoff = (unsigned long) addr >> PAGE_SHIFT; | ||
1199 | vma->vm_ops = &ipath_file_vm_ops; | ||
1200 | vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND; | ||
1201 | ret = 0; | ||
1202 | |||
1203 | bail: | ||
1204 | return ret; | ||
1205 | } | ||
1206 | |||
1052 | /** | 1207 | /** |
1053 | * ipath_mmap - mmap various structures into user space | 1208 | * ipath_mmap - mmap various structures into user space |
1054 | * @fp: the file pointer | 1209 | * @fp: the file pointer |
@@ -1064,73 +1219,99 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) | |||
1064 | struct ipath_portdata *pd; | 1219 | struct ipath_portdata *pd; |
1065 | struct ipath_devdata *dd; | 1220 | struct ipath_devdata *dd; |
1066 | u64 pgaddr, ureg; | 1221 | u64 pgaddr, ureg; |
1222 | unsigned piobufs, piocnt; | ||
1067 | int ret; | 1223 | int ret; |
1068 | 1224 | ||
1069 | pd = port_fp(fp); | 1225 | pd = port_fp(fp); |
1226 | if (!pd) { | ||
1227 | ret = -EINVAL; | ||
1228 | goto bail; | ||
1229 | } | ||
1070 | dd = pd->port_dd; | 1230 | dd = pd->port_dd; |
1071 | 1231 | ||
1072 | /* | 1232 | /* |
1073 | * This is the ipath_do_user_init() code, mapping the shared buffers | 1233 | * This is the ipath_do_user_init() code, mapping the shared buffers |
1074 | * into the user process. The address referred to by vm_pgoff is the | 1234 | * into the user process. The address referred to by vm_pgoff is the |
1075 | * virtual, not physical, address; we only do one mmap for each | 1235 | * file offset passed via mmap(). For shared ports, this is the |
1076 | * space mapped. | 1236 | * kernel vmalloc() address of the pages to share with the master. |
1237 | * For non-shared or master ports, this is a physical address. | ||
1238 | * We only do one mmap for each space mapped. | ||
1077 | */ | 1239 | */ |
1078 | pgaddr = vma->vm_pgoff << PAGE_SHIFT; | 1240 | pgaddr = vma->vm_pgoff << PAGE_SHIFT; |
1079 | 1241 | ||
1080 | /* | 1242 | /* |
1081 | * Must fit in 40 bits for our hardware; some checked elsewhere, | 1243 | * Check for 0 in case one of the allocations failed, but user |
1082 | * but we'll be paranoid. Check for 0 is mostly in case one of the | 1244 | * called mmap anyway. |
1083 | * allocations failed, but user called mmap anyway. We want to catch | ||
1084 | * that before it can match. | ||
1085 | */ | 1245 | */ |
1086 | if (!pgaddr || pgaddr >= (1ULL<<40)) { | 1246 | if (!pgaddr) { |
1087 | ipath_dev_err(dd, "Bad phys addr %llx, start %lx, end %lx\n", | 1247 | ret = -EINVAL; |
1088 | (unsigned long long)pgaddr, vma->vm_start, vma->vm_end); | 1248 | goto bail; |
1089 | return -EINVAL; | ||
1090 | } | 1249 | } |
1091 | 1250 | ||
1092 | /* just the offset of the port user registers, not physical addr */ | 1251 | ipath_cdbg(MM, "pgaddr %llx vm_start=%lx len %lx port %u:%u:%u\n", |
1093 | ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port; | ||
1094 | |||
1095 | ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n", | ||
1096 | (unsigned long long) pgaddr, vma->vm_start, | 1252 | (unsigned long long) pgaddr, vma->vm_start, |
1097 | vma->vm_end - vma->vm_start); | 1253 | vma->vm_end - vma->vm_start, dd->ipath_unit, |
1254 | pd->port_port, subport_fp(fp)); | ||
1098 | 1255 | ||
1099 | if (vma->vm_start & (PAGE_SIZE-1)) { | 1256 | /* |
1100 | ipath_dev_err(dd, | 1257 | * Physical addresses must fit in 40 bits for our hardware. |
1101 | "vm_start not aligned: %lx, end=%lx phys %lx\n", | 1258 | * Check for kernel virtual addresses first, anything else must |
1102 | vma->vm_start, vma->vm_end, (unsigned long)pgaddr); | 1259 | * match a HW or memory address. |
1103 | ret = -EINVAL; | 1260 | */ |
1261 | if (pgaddr >= (1ULL<<40)) { | ||
1262 | ret = mmap_kvaddr(vma, pgaddr, pd, subport_fp(fp)); | ||
1263 | goto bail; | ||
1264 | } | ||
1265 | |||
1266 | if (!pd->port_subport_cnt) { | ||
1267 | /* port is not shared */ | ||
1268 | ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port; | ||
1269 | piocnt = dd->ipath_pbufsport; | ||
1270 | piobufs = pd->port_piobufs; | ||
1271 | } else if (!subport_fp(fp)) { | ||
1272 | /* caller is the master */ | ||
1273 | ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port; | ||
1274 | piocnt = (dd->ipath_pbufsport / pd->port_subport_cnt) + | ||
1275 | (dd->ipath_pbufsport % pd->port_subport_cnt); | ||
1276 | piobufs = pd->port_piobufs + | ||
1277 | dd->ipath_palign * (dd->ipath_pbufsport - piocnt); | ||
1278 | } else { | ||
1279 | unsigned slave = subport_fp(fp) - 1; | ||
1280 | |||
1281 | /* caller is a slave */ | ||
1282 | ureg = 0; | ||
1283 | piocnt = dd->ipath_pbufsport / pd->port_subport_cnt; | ||
1284 | piobufs = pd->port_piobufs + dd->ipath_palign * piocnt * slave; | ||
1104 | } | 1285 | } |
1105 | else if (pgaddr == ureg) | 1286 | |
1287 | if (pgaddr == ureg) | ||
1106 | ret = mmap_ureg(vma, dd, ureg); | 1288 | ret = mmap_ureg(vma, dd, ureg); |
1107 | else if (pgaddr == pd->port_piobufs) | 1289 | else if (pgaddr == piobufs) |
1108 | ret = mmap_piobufs(vma, dd, pd); | 1290 | ret = mmap_piobufs(vma, dd, pd, piobufs, piocnt); |
1109 | else if (pgaddr == (u64) pd->port_rcvegr_phys) | 1291 | else if (pgaddr == dd->ipath_pioavailregs_phys) |
1292 | /* in-memory copy of pioavail registers */ | ||
1293 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | ||
1294 | dd->ipath_pioavailregs_phys, | ||
1295 | "pioavail registers"); | ||
1296 | else if (subport_fp(fp)) | ||
1297 | /* Subports don't mmap the physical receive buffers */ | ||
1298 | ret = -EINVAL; | ||
1299 | else if (pgaddr == pd->port_rcvegr_phys) | ||
1110 | ret = mmap_rcvegrbufs(vma, pd); | 1300 | ret = mmap_rcvegrbufs(vma, pd); |
1111 | else if (pgaddr == (u64) pd->port_rcvhdrq_phys) { | 1301 | else if (pgaddr == (u64) pd->port_rcvhdrq_phys) |
1112 | /* | 1302 | /* |
1113 | * The rcvhdrq itself; readonly except on HT (so have | 1303 | * The rcvhdrq itself; readonly except on HT (so have |
1114 | * to allow writable mapping), multiple pages, contiguous | 1304 | * to allow writable mapping), multiple pages, contiguous |
1115 | * from an i/o perspective. | 1305 | * from an i/o perspective. |
1116 | */ | 1306 | */ |
1117 | unsigned total_size = | 1307 | ret = ipath_mmap_mem(vma, pd, pd->port_rcvhdrq_size, 1, |
1118 | ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize | ||
1119 | * sizeof(u32), PAGE_SIZE); | ||
1120 | ret = ipath_mmap_mem(vma, pd, total_size, 1, | ||
1121 | pd->port_rcvhdrq_phys, | 1308 | pd->port_rcvhdrq_phys, |
1122 | "rcvhdrq"); | 1309 | "rcvhdrq"); |
1123 | } | 1310 | else if (pgaddr == (u64) pd->port_rcvhdrqtailaddr_phys) |
1124 | else if (pgaddr == (u64)pd->port_rcvhdrqtailaddr_phys) | ||
1125 | /* in-memory copy of rcvhdrq tail register */ | 1311 | /* in-memory copy of rcvhdrq tail register */ |
1126 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | 1312 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, |
1127 | pd->port_rcvhdrqtailaddr_phys, | 1313 | pd->port_rcvhdrqtailaddr_phys, |
1128 | "rcvhdrq tail"); | 1314 | "rcvhdrq tail"); |
1129 | else if (pgaddr == dd->ipath_pioavailregs_phys) | ||
1130 | /* in-memory copy of pioavail registers */ | ||
1131 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | ||
1132 | dd->ipath_pioavailregs_phys, | ||
1133 | "pioavail registers"); | ||
1134 | else | 1315 | else |
1135 | ret = -EINVAL; | 1316 | ret = -EINVAL; |
1136 | 1317 | ||
@@ -1138,9 +1319,10 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) | |||
1138 | 1319 | ||
1139 | if (ret < 0) | 1320 | if (ret < 0) |
1140 | dev_info(&dd->pcidev->dev, | 1321 | dev_info(&dd->pcidev->dev, |
1141 | "Failure %d on addr %lx, off %lx\n", | 1322 | "Failure %d on off %llx len %lx\n", |
1142 | -ret, vma->vm_start, vma->vm_pgoff); | 1323 | -ret, (unsigned long long)pgaddr, |
1143 | 1324 | vma->vm_end - vma->vm_start); | |
1325 | bail: | ||
1144 | return ret; | 1326 | return ret; |
1145 | } | 1327 | } |
1146 | 1328 | ||
@@ -1154,6 +1336,8 @@ static unsigned int ipath_poll(struct file *fp, | |||
1154 | struct ipath_devdata *dd; | 1336 | struct ipath_devdata *dd; |
1155 | 1337 | ||
1156 | pd = port_fp(fp); | 1338 | pd = port_fp(fp); |
1339 | if (!pd) | ||
1340 | goto bail; | ||
1157 | dd = pd->port_dd; | 1341 | dd = pd->port_dd; |
1158 | 1342 | ||
1159 | bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT; | 1343 | bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT; |
@@ -1176,7 +1360,7 @@ static unsigned int ipath_poll(struct file *fp, | |||
1176 | 1360 | ||
1177 | if (tail == head) { | 1361 | if (tail == head) { |
1178 | set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); | 1362 | set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); |
1179 | if(dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */ | 1363 | if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */ |
1180 | (void)ipath_write_ureg(dd, ur_rcvhdrhead, | 1364 | (void)ipath_write_ureg(dd, ur_rcvhdrhead, |
1181 | dd->ipath_rhdrhead_intr_off | 1365 | dd->ipath_rhdrhead_intr_off |
1182 | | head, pd->port_port); | 1366 | | head, pd->port_port); |
@@ -1200,18 +1384,80 @@ static unsigned int ipath_poll(struct file *fp, | |||
1200 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 1384 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, |
1201 | dd->ipath_rcvctrl); | 1385 | dd->ipath_rcvctrl); |
1202 | 1386 | ||
1387 | bail: | ||
1203 | return pollflag; | 1388 | return pollflag; |
1204 | } | 1389 | } |
1205 | 1390 | ||
1391 | static int init_subports(struct ipath_devdata *dd, | ||
1392 | struct ipath_portdata *pd, | ||
1393 | const struct ipath_user_info *uinfo) | ||
1394 | { | ||
1395 | int ret = 0; | ||
1396 | unsigned num_slaves; | ||
1397 | size_t size; | ||
1398 | |||
1399 | /* Old user binaries don't know about subports */ | ||
1400 | if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR) | ||
1401 | goto bail; | ||
1402 | /* | ||
1403 | * If the user is requesting zero or one port, | ||
1404 | * skip the subport allocation. | ||
1405 | */ | ||
1406 | if (uinfo->spu_subport_cnt <= 1) | ||
1407 | goto bail; | ||
1408 | if (uinfo->spu_subport_cnt > 4) { | ||
1409 | ret = -EINVAL; | ||
1410 | goto bail; | ||
1411 | } | ||
1412 | |||
1413 | num_slaves = uinfo->spu_subport_cnt - 1; | ||
1414 | pd->subport_uregbase = vmalloc(PAGE_SIZE * num_slaves); | ||
1415 | if (!pd->subport_uregbase) { | ||
1416 | ret = -ENOMEM; | ||
1417 | goto bail; | ||
1418 | } | ||
1419 | /* Note: pd->port_rcvhdrq_size isn't initialized yet. */ | ||
1420 | size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * | ||
1421 | sizeof(u32), PAGE_SIZE) * num_slaves; | ||
1422 | pd->subport_rcvhdr_base = vmalloc(size); | ||
1423 | if (!pd->subport_rcvhdr_base) { | ||
1424 | ret = -ENOMEM; | ||
1425 | goto bail_ureg; | ||
1426 | } | ||
1427 | |||
1428 | pd->subport_rcvegrbuf = vmalloc(pd->port_rcvegrbuf_chunks * | ||
1429 | pd->port_rcvegrbuf_size * | ||
1430 | num_slaves); | ||
1431 | if (!pd->subport_rcvegrbuf) { | ||
1432 | ret = -ENOMEM; | ||
1433 | goto bail_rhdr; | ||
1434 | } | ||
1435 | |||
1436 | pd->port_subport_cnt = uinfo->spu_subport_cnt; | ||
1437 | pd->port_subport_id = uinfo->spu_subport_id; | ||
1438 | pd->active_slaves = 1; | ||
1439 | goto bail; | ||
1440 | |||
1441 | bail_rhdr: | ||
1442 | vfree(pd->subport_rcvhdr_base); | ||
1443 | bail_ureg: | ||
1444 | vfree(pd->subport_uregbase); | ||
1445 | pd->subport_uregbase = NULL; | ||
1446 | bail: | ||
1447 | return ret; | ||
1448 | } | ||
1449 | |||
1206 | static int try_alloc_port(struct ipath_devdata *dd, int port, | 1450 | static int try_alloc_port(struct ipath_devdata *dd, int port, |
1207 | struct file *fp) | 1451 | struct file *fp, |
1452 | const struct ipath_user_info *uinfo) | ||
1208 | { | 1453 | { |
1454 | struct ipath_portdata *pd; | ||
1209 | int ret; | 1455 | int ret; |
1210 | 1456 | ||
1211 | if (!dd->ipath_pd[port]) { | 1457 | if (!(pd = dd->ipath_pd[port])) { |
1212 | void *p, *ptmp; | 1458 | void *ptmp; |
1213 | 1459 | ||
1214 | p = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL); | 1460 | pd = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL); |
1215 | 1461 | ||
1216 | /* | 1462 | /* |
1217 | * Allocate memory for use in ipath_tid_update() just once | 1463 | * Allocate memory for use in ipath_tid_update() just once |
@@ -1221,34 +1467,36 @@ static int try_alloc_port(struct ipath_devdata *dd, int port, | |||
1221 | ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) + | 1467 | ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) + |
1222 | dd->ipath_rcvtidcnt * sizeof(struct page **), | 1468 | dd->ipath_rcvtidcnt * sizeof(struct page **), |
1223 | GFP_KERNEL); | 1469 | GFP_KERNEL); |
1224 | if (!p || !ptmp) { | 1470 | if (!pd || !ptmp) { |
1225 | ipath_dev_err(dd, "Unable to allocate portdata " | 1471 | ipath_dev_err(dd, "Unable to allocate portdata " |
1226 | "memory, failing open\n"); | 1472 | "memory, failing open\n"); |
1227 | ret = -ENOMEM; | 1473 | ret = -ENOMEM; |
1228 | kfree(p); | 1474 | kfree(pd); |
1229 | kfree(ptmp); | 1475 | kfree(ptmp); |
1230 | goto bail; | 1476 | goto bail; |
1231 | } | 1477 | } |
1232 | dd->ipath_pd[port] = p; | 1478 | dd->ipath_pd[port] = pd; |
1233 | dd->ipath_pd[port]->port_port = port; | 1479 | dd->ipath_pd[port]->port_port = port; |
1234 | dd->ipath_pd[port]->port_dd = dd; | 1480 | dd->ipath_pd[port]->port_dd = dd; |
1235 | dd->ipath_pd[port]->port_tid_pg_list = ptmp; | 1481 | dd->ipath_pd[port]->port_tid_pg_list = ptmp; |
1236 | init_waitqueue_head(&dd->ipath_pd[port]->port_wait); | 1482 | init_waitqueue_head(&dd->ipath_pd[port]->port_wait); |
1237 | } | 1483 | } |
1238 | if (!dd->ipath_pd[port]->port_cnt) { | 1484 | if (!pd->port_cnt) { |
1239 | dd->ipath_pd[port]->port_cnt = 1; | 1485 | pd->userversion = uinfo->spu_userversion; |
1240 | fp->private_data = (void *) dd->ipath_pd[port]; | 1486 | init_user_egr_sizes(pd); |
1487 | if ((ret = init_subports(dd, pd, uinfo)) != 0) | ||
1488 | goto bail; | ||
1241 | ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n", | 1489 | ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n", |
1242 | current->comm, current->pid, dd->ipath_unit, | 1490 | current->comm, current->pid, dd->ipath_unit, |
1243 | port); | 1491 | port); |
1244 | dd->ipath_pd[port]->port_pid = current->pid; | 1492 | pd->port_cnt = 1; |
1245 | strncpy(dd->ipath_pd[port]->port_comm, current->comm, | 1493 | port_fp(fp) = pd; |
1246 | sizeof(dd->ipath_pd[port]->port_comm)); | 1494 | pd->port_pid = current->pid; |
1495 | strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm)); | ||
1247 | ipath_stats.sps_ports++; | 1496 | ipath_stats.sps_ports++; |
1248 | ret = 0; | 1497 | ret = 0; |
1249 | goto bail; | 1498 | } else |
1250 | } | 1499 | ret = -EBUSY; |
1251 | ret = -EBUSY; | ||
1252 | 1500 | ||
1253 | bail: | 1501 | bail: |
1254 | return ret; | 1502 | return ret; |
@@ -1264,7 +1512,8 @@ static inline int usable(struct ipath_devdata *dd) | |||
1264 | | IPATH_LINKUNK)); | 1512 | | IPATH_LINKUNK)); |
1265 | } | 1513 | } |
1266 | 1514 | ||
1267 | static int find_free_port(int unit, struct file *fp) | 1515 | static int find_free_port(int unit, struct file *fp, |
1516 | const struct ipath_user_info *uinfo) | ||
1268 | { | 1517 | { |
1269 | struct ipath_devdata *dd = ipath_lookup(unit); | 1518 | struct ipath_devdata *dd = ipath_lookup(unit); |
1270 | int ret, i; | 1519 | int ret, i; |
@@ -1279,8 +1528,8 @@ static int find_free_port(int unit, struct file *fp) | |||
1279 | goto bail; | 1528 | goto bail; |
1280 | } | 1529 | } |
1281 | 1530 | ||
1282 | for (i = 0; i < dd->ipath_cfgports; i++) { | 1531 | for (i = 1; i < dd->ipath_cfgports; i++) { |
1283 | ret = try_alloc_port(dd, i, fp); | 1532 | ret = try_alloc_port(dd, i, fp, uinfo); |
1284 | if (ret != -EBUSY) | 1533 | if (ret != -EBUSY) |
1285 | goto bail; | 1534 | goto bail; |
1286 | } | 1535 | } |
@@ -1290,13 +1539,14 @@ bail: | |||
1290 | return ret; | 1539 | return ret; |
1291 | } | 1540 | } |
1292 | 1541 | ||
1293 | static int find_best_unit(struct file *fp) | 1542 | static int find_best_unit(struct file *fp, |
1543 | const struct ipath_user_info *uinfo) | ||
1294 | { | 1544 | { |
1295 | int ret = 0, i, prefunit = -1, devmax; | 1545 | int ret = 0, i, prefunit = -1, devmax; |
1296 | int maxofallports, npresent, nup; | 1546 | int maxofallports, npresent, nup; |
1297 | int ndev; | 1547 | int ndev; |
1298 | 1548 | ||
1299 | (void) ipath_count_units(&npresent, &nup, &maxofallports); | 1549 | devmax = ipath_count_units(&npresent, &nup, &maxofallports); |
1300 | 1550 | ||
1301 | /* | 1551 | /* |
1302 | * This code is present to allow a knowledgeable person to | 1552 | * This code is present to allow a knowledgeable person to |
@@ -1343,8 +1593,6 @@ static int find_best_unit(struct file *fp) | |||
1343 | 1593 | ||
1344 | if (prefunit != -1) | 1594 | if (prefunit != -1) |
1345 | devmax = prefunit + 1; | 1595 | devmax = prefunit + 1; |
1346 | else | ||
1347 | devmax = ipath_count_units(NULL, NULL, NULL); | ||
1348 | recheck: | 1596 | recheck: |
1349 | for (i = 1; i < maxofallports; i++) { | 1597 | for (i = 1; i < maxofallports; i++) { |
1350 | for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax; | 1598 | for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax; |
@@ -1359,7 +1607,7 @@ recheck: | |||
1359 | * next. | 1607 | * next. |
1360 | */ | 1608 | */ |
1361 | continue; | 1609 | continue; |
1362 | ret = try_alloc_port(dd, i, fp); | 1610 | ret = try_alloc_port(dd, i, fp, uinfo); |
1363 | if (!ret) | 1611 | if (!ret) |
1364 | goto done; | 1612 | goto done; |
1365 | } | 1613 | } |
@@ -1395,22 +1643,174 @@ done: | |||
1395 | return ret; | 1643 | return ret; |
1396 | } | 1644 | } |
1397 | 1645 | ||
1646 | static int find_shared_port(struct file *fp, | ||
1647 | const struct ipath_user_info *uinfo) | ||
1648 | { | ||
1649 | int devmax, ndev, i; | ||
1650 | int ret = 0; | ||
1651 | |||
1652 | devmax = ipath_count_units(NULL, NULL, NULL); | ||
1653 | |||
1654 | for (ndev = 0; ndev < devmax; ndev++) { | ||
1655 | struct ipath_devdata *dd = ipath_lookup(ndev); | ||
1656 | |||
1657 | if (!dd) | ||
1658 | continue; | ||
1659 | for (i = 1; i < dd->ipath_cfgports; i++) { | ||
1660 | struct ipath_portdata *pd = dd->ipath_pd[i]; | ||
1661 | |||
1662 | /* Skip ports which are not yet open */ | ||
1663 | if (!pd || !pd->port_cnt) | ||
1664 | continue; | ||
1665 | /* Skip port if it doesn't match the requested one */ | ||
1666 | if (pd->port_subport_id != uinfo->spu_subport_id) | ||
1667 | continue; | ||
1668 | /* Verify the sharing process matches the master */ | ||
1669 | if (pd->port_subport_cnt != uinfo->spu_subport_cnt || | ||
1670 | pd->userversion != uinfo->spu_userversion || | ||
1671 | pd->port_cnt >= pd->port_subport_cnt) { | ||
1672 | ret = -EINVAL; | ||
1673 | goto done; | ||
1674 | } | ||
1675 | port_fp(fp) = pd; | ||
1676 | subport_fp(fp) = pd->port_cnt++; | ||
1677 | tidcursor_fp(fp) = 0; | ||
1678 | pd->active_slaves |= 1 << subport_fp(fp); | ||
1679 | ipath_cdbg(PROC, | ||
1680 | "%s[%u] %u sharing %s[%u] unit:port %u:%u\n", | ||
1681 | current->comm, current->pid, | ||
1682 | subport_fp(fp), | ||
1683 | pd->port_comm, pd->port_pid, | ||
1684 | dd->ipath_unit, pd->port_port); | ||
1685 | ret = 1; | ||
1686 | goto done; | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | done: | ||
1691 | return ret; | ||
1692 | } | ||
1693 | |||
1398 | static int ipath_open(struct inode *in, struct file *fp) | 1694 | static int ipath_open(struct inode *in, struct file *fp) |
1399 | { | 1695 | { |
1400 | int ret, user_minor; | 1696 | /* The real work is performed later in ipath_do_user_init() */ |
1697 | fp->private_data = kzalloc(sizeof(struct ipath_filedata), GFP_KERNEL); | ||
1698 | return fp->private_data ? 0 : -ENOMEM; | ||
1699 | } | ||
1700 | |||
1701 | static int ipath_do_user_init(struct file *fp, | ||
1702 | const struct ipath_user_info *uinfo) | ||
1703 | { | ||
1704 | int ret; | ||
1705 | struct ipath_portdata *pd; | ||
1706 | struct ipath_devdata *dd; | ||
1707 | u32 head32; | ||
1708 | int i_minor; | ||
1709 | unsigned swminor; | ||
1710 | |||
1711 | /* Check to be sure we haven't already initialized this file */ | ||
1712 | if (port_fp(fp)) { | ||
1713 | ret = -EINVAL; | ||
1714 | goto done; | ||
1715 | } | ||
1716 | |||
1717 | /* for now, if major version is different, bail */ | ||
1718 | if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) { | ||
1719 | ipath_dbg("User major version %d not same as driver " | ||
1720 | "major %d\n", uinfo->spu_userversion >> 16, | ||
1721 | IPATH_USER_SWMAJOR); | ||
1722 | ret = -ENODEV; | ||
1723 | goto done; | ||
1724 | } | ||
1725 | |||
1726 | swminor = uinfo->spu_userversion & 0xffff; | ||
1727 | if (swminor != IPATH_USER_SWMINOR) | ||
1728 | ipath_dbg("User minor version %d not same as driver " | ||
1729 | "minor %d\n", swminor, IPATH_USER_SWMINOR); | ||
1401 | 1730 | ||
1402 | mutex_lock(&ipath_mutex); | 1731 | mutex_lock(&ipath_mutex); |
1403 | 1732 | ||
1404 | user_minor = iminor(in) - IPATH_USER_MINOR_BASE; | 1733 | if (swminor == IPATH_USER_SWMINOR && uinfo->spu_subport_cnt && |
1734 | (ret = find_shared_port(fp, uinfo))) { | ||
1735 | mutex_unlock(&ipath_mutex); | ||
1736 | if (ret > 0) | ||
1737 | ret = 0; | ||
1738 | goto done; | ||
1739 | } | ||
1740 | |||
1741 | i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE; | ||
1405 | ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", | 1742 | ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", |
1406 | (long)in->i_rdev, user_minor); | 1743 | (long)fp->f_dentry->d_inode->i_rdev, i_minor); |
1407 | 1744 | ||
1408 | if (user_minor) | 1745 | if (i_minor) |
1409 | ret = find_free_port(user_minor - 1, fp); | 1746 | ret = find_free_port(i_minor - 1, fp, uinfo); |
1410 | else | 1747 | else |
1411 | ret = find_best_unit(fp); | 1748 | ret = find_best_unit(fp, uinfo); |
1412 | 1749 | ||
1413 | mutex_unlock(&ipath_mutex); | 1750 | mutex_unlock(&ipath_mutex); |
1751 | |||
1752 | if (ret) | ||
1753 | goto done; | ||
1754 | |||
1755 | pd = port_fp(fp); | ||
1756 | dd = pd->port_dd; | ||
1757 | |||
1758 | if (uinfo->spu_rcvhdrsize) { | ||
1759 | ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize); | ||
1760 | if (ret) | ||
1761 | goto done; | ||
1762 | } | ||
1763 | |||
1764 | /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */ | ||
1765 | |||
1766 | /* for right now, kernel piobufs are at end, so port 1 is at 0 */ | ||
1767 | pd->port_piobufs = dd->ipath_piobufbase + | ||
1768 | dd->ipath_pbufsport * (pd->port_port - 1) * dd->ipath_palign; | ||
1769 | ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n", | ||
1770 | pd->port_port, pd->port_piobufs); | ||
1771 | |||
1772 | /* | ||
1773 | * Now allocate the rcvhdr Q and eager TIDs; skip the TID | ||
1774 | * array for time being. If pd->port_port > chip-supported, | ||
1775 | * we need to do extra stuff here to handle by handling overflow | ||
1776 | * through port 0, someday | ||
1777 | */ | ||
1778 | ret = ipath_create_rcvhdrq(dd, pd); | ||
1779 | if (!ret) | ||
1780 | ret = ipath_create_user_egr(pd); | ||
1781 | if (ret) | ||
1782 | goto done; | ||
1783 | |||
1784 | /* | ||
1785 | * set the eager head register for this port to the current values | ||
1786 | * of the tail pointers, since we don't know if they were | ||
1787 | * updated on last use of the port. | ||
1788 | */ | ||
1789 | head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port); | ||
1790 | ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port); | ||
1791 | dd->ipath_lastegrheads[pd->port_port] = -1; | ||
1792 | dd->ipath_lastrcvhdrqtails[pd->port_port] = -1; | ||
1793 | ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n", | ||
1794 | pd->port_port, head32); | ||
1795 | pd->port_tidcursor = 0; /* start at beginning after open */ | ||
1796 | /* | ||
1797 | * now enable the port; the tail registers will be written to memory | ||
1798 | * by the chip as soon as it sees the write to | ||
1799 | * dd->ipath_kregs->kr_rcvctrl. The update only happens on | ||
1800 | * transition from 0 to 1, so clear it first, then set it as part of | ||
1801 | * enabling the port. This will (very briefly) affect any other | ||
1802 | * open ports, but it shouldn't be long enough to be an issue. | ||
1803 | * We explictly set the in-memory copy to 0 beforehand, so we don't | ||
1804 | * have to wait to be sure the DMA update has happened. | ||
1805 | */ | ||
1806 | *pd->port_rcvhdrtail_kvaddr = 0ULL; | ||
1807 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, | ||
1808 | &dd->ipath_rcvctrl); | ||
1809 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
1810 | dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD); | ||
1811 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
1812 | dd->ipath_rcvctrl); | ||
1813 | done: | ||
1414 | return ret; | 1814 | return ret; |
1415 | } | 1815 | } |
1416 | 1816 | ||
@@ -1453,6 +1853,7 @@ static void unlock_expected_tids(struct ipath_portdata *pd) | |||
1453 | static int ipath_close(struct inode *in, struct file *fp) | 1853 | static int ipath_close(struct inode *in, struct file *fp) |
1454 | { | 1854 | { |
1455 | int ret = 0; | 1855 | int ret = 0; |
1856 | struct ipath_filedata *fd; | ||
1456 | struct ipath_portdata *pd; | 1857 | struct ipath_portdata *pd; |
1457 | struct ipath_devdata *dd; | 1858 | struct ipath_devdata *dd; |
1458 | unsigned port; | 1859 | unsigned port; |
@@ -1462,9 +1863,24 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
1462 | 1863 | ||
1463 | mutex_lock(&ipath_mutex); | 1864 | mutex_lock(&ipath_mutex); |
1464 | 1865 | ||
1465 | pd = port_fp(fp); | 1866 | fd = (struct ipath_filedata *) fp->private_data; |
1466 | port = pd->port_port; | ||
1467 | fp->private_data = NULL; | 1867 | fp->private_data = NULL; |
1868 | pd = fd->pd; | ||
1869 | if (!pd) { | ||
1870 | mutex_unlock(&ipath_mutex); | ||
1871 | goto bail; | ||
1872 | } | ||
1873 | if (--pd->port_cnt) { | ||
1874 | /* | ||
1875 | * XXX If the master closes the port before the slave(s), | ||
1876 | * revoke the mmap for the eager receive queue so | ||
1877 | * the slave(s) don't wait for receive data forever. | ||
1878 | */ | ||
1879 | pd->active_slaves &= ~(1 << fd->subport); | ||
1880 | mutex_unlock(&ipath_mutex); | ||
1881 | goto bail; | ||
1882 | } | ||
1883 | port = pd->port_port; | ||
1468 | dd = pd->port_dd; | 1884 | dd = pd->port_dd; |
1469 | 1885 | ||
1470 | if (pd->port_hdrqfull) { | 1886 | if (pd->port_hdrqfull) { |
@@ -1503,8 +1919,6 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
1503 | 1919 | ||
1504 | /* clean up the pkeys for this port user */ | 1920 | /* clean up the pkeys for this port user */ |
1505 | ipath_clean_part_key(pd, dd); | 1921 | ipath_clean_part_key(pd, dd); |
1506 | |||
1507 | |||
1508 | /* | 1922 | /* |
1509 | * be paranoid, and never write 0's to these, just use an | 1923 | * be paranoid, and never write 0's to these, just use an |
1510 | * unused part of the port 0 tail page. Of course, | 1924 | * unused part of the port 0 tail page. Of course, |
@@ -1533,29 +1947,39 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
1533 | dd->ipath_f_clear_tids(dd, pd->port_port); | 1947 | dd->ipath_f_clear_tids(dd, pd->port_port); |
1534 | } | 1948 | } |
1535 | 1949 | ||
1536 | pd->port_cnt = 0; | ||
1537 | pd->port_pid = 0; | 1950 | pd->port_pid = 0; |
1538 | |||
1539 | dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */ | 1951 | dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */ |
1540 | mutex_unlock(&ipath_mutex); | 1952 | mutex_unlock(&ipath_mutex); |
1541 | ipath_free_pddata(dd, pd); /* after releasing the mutex */ | 1953 | ipath_free_pddata(dd, pd); /* after releasing the mutex */ |
1542 | 1954 | ||
1955 | bail: | ||
1956 | kfree(fd); | ||
1543 | return ret; | 1957 | return ret; |
1544 | } | 1958 | } |
1545 | 1959 | ||
1546 | static int ipath_port_info(struct ipath_portdata *pd, | 1960 | static int ipath_port_info(struct ipath_portdata *pd, u16 subport, |
1547 | struct ipath_port_info __user *uinfo) | 1961 | struct ipath_port_info __user *uinfo) |
1548 | { | 1962 | { |
1549 | struct ipath_port_info info; | 1963 | struct ipath_port_info info; |
1550 | int nup; | 1964 | int nup; |
1551 | int ret; | 1965 | int ret; |
1966 | size_t sz; | ||
1552 | 1967 | ||
1553 | (void) ipath_count_units(NULL, &nup, NULL); | 1968 | (void) ipath_count_units(NULL, &nup, NULL); |
1554 | info.num_active = nup; | 1969 | info.num_active = nup; |
1555 | info.unit = pd->port_dd->ipath_unit; | 1970 | info.unit = pd->port_dd->ipath_unit; |
1556 | info.port = pd->port_port; | 1971 | info.port = pd->port_port; |
1972 | info.subport = subport; | ||
1973 | /* Don't return new fields if old library opened the port. */ | ||
1974 | if ((pd->userversion & 0xffff) == IPATH_USER_SWMINOR) { | ||
1975 | /* Number of user ports available for this device. */ | ||
1976 | info.num_ports = pd->port_dd->ipath_cfgports - 1; | ||
1977 | info.num_subports = pd->port_subport_cnt; | ||
1978 | sz = sizeof(info); | ||
1979 | } else | ||
1980 | sz = sizeof(info) - 2 * sizeof(u16); | ||
1557 | 1981 | ||
1558 | if (copy_to_user(uinfo, &info, sizeof(info))) { | 1982 | if (copy_to_user(uinfo, &info, sz)) { |
1559 | ret = -EFAULT; | 1983 | ret = -EFAULT; |
1560 | goto bail; | 1984 | goto bail; |
1561 | } | 1985 | } |
@@ -1565,6 +1989,16 @@ bail: | |||
1565 | return ret; | 1989 | return ret; |
1566 | } | 1990 | } |
1567 | 1991 | ||
1992 | static int ipath_get_slave_info(struct ipath_portdata *pd, | ||
1993 | void __user *slave_mask_addr) | ||
1994 | { | ||
1995 | int ret = 0; | ||
1996 | |||
1997 | if (copy_to_user(slave_mask_addr, &pd->active_slaves, sizeof(u32))) | ||
1998 | ret = -EFAULT; | ||
1999 | return ret; | ||
2000 | } | ||
2001 | |||
1568 | static ssize_t ipath_write(struct file *fp, const char __user *data, | 2002 | static ssize_t ipath_write(struct file *fp, const char __user *data, |
1569 | size_t count, loff_t *off) | 2003 | size_t count, loff_t *off) |
1570 | { | 2004 | { |
@@ -1617,6 +2051,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data, | |||
1617 | dest = &cmd.cmd.part_key; | 2051 | dest = &cmd.cmd.part_key; |
1618 | src = &ucmd->cmd.part_key; | 2052 | src = &ucmd->cmd.part_key; |
1619 | break; | 2053 | break; |
2054 | case IPATH_CMD_SLAVE_INFO: | ||
2055 | copy = sizeof(cmd.cmd.slave_mask_addr); | ||
2056 | dest = &cmd.cmd.slave_mask_addr; | ||
2057 | src = &ucmd->cmd.slave_mask_addr; | ||
2058 | break; | ||
1620 | default: | 2059 | default: |
1621 | ret = -EINVAL; | 2060 | ret = -EINVAL; |
1622 | goto bail; | 2061 | goto bail; |
@@ -1634,34 +2073,43 @@ static ssize_t ipath_write(struct file *fp, const char __user *data, | |||
1634 | 2073 | ||
1635 | consumed += copy; | 2074 | consumed += copy; |
1636 | pd = port_fp(fp); | 2075 | pd = port_fp(fp); |
2076 | if (!pd && cmd.type != IPATH_CMD_USER_INIT) { | ||
2077 | ret = -EINVAL; | ||
2078 | goto bail; | ||
2079 | } | ||
1637 | 2080 | ||
1638 | switch (cmd.type) { | 2081 | switch (cmd.type) { |
1639 | case IPATH_CMD_USER_INIT: | 2082 | case IPATH_CMD_USER_INIT: |
1640 | ret = ipath_do_user_init(pd, &cmd.cmd.user_info); | 2083 | ret = ipath_do_user_init(fp, &cmd.cmd.user_info); |
1641 | if (ret < 0) | 2084 | if (ret) |
1642 | goto bail; | 2085 | goto bail; |
1643 | ret = ipath_get_base_info( | 2086 | ret = ipath_get_base_info( |
1644 | pd, (void __user *) (unsigned long) | 2087 | fp, (void __user *) (unsigned long) |
1645 | cmd.cmd.user_info.spu_base_info, | 2088 | cmd.cmd.user_info.spu_base_info, |
1646 | cmd.cmd.user_info.spu_base_info_size); | 2089 | cmd.cmd.user_info.spu_base_info_size); |
1647 | break; | 2090 | break; |
1648 | case IPATH_CMD_RECV_CTRL: | 2091 | case IPATH_CMD_RECV_CTRL: |
1649 | ret = ipath_manage_rcvq(pd, cmd.cmd.recv_ctrl); | 2092 | ret = ipath_manage_rcvq(pd, subport_fp(fp), cmd.cmd.recv_ctrl); |
1650 | break; | 2093 | break; |
1651 | case IPATH_CMD_PORT_INFO: | 2094 | case IPATH_CMD_PORT_INFO: |
1652 | ret = ipath_port_info(pd, | 2095 | ret = ipath_port_info(pd, subport_fp(fp), |
1653 | (struct ipath_port_info __user *) | 2096 | (struct ipath_port_info __user *) |
1654 | (unsigned long) cmd.cmd.port_info); | 2097 | (unsigned long) cmd.cmd.port_info); |
1655 | break; | 2098 | break; |
1656 | case IPATH_CMD_TID_UPDATE: | 2099 | case IPATH_CMD_TID_UPDATE: |
1657 | ret = ipath_tid_update(pd, &cmd.cmd.tid_info); | 2100 | ret = ipath_tid_update(pd, fp, &cmd.cmd.tid_info); |
1658 | break; | 2101 | break; |
1659 | case IPATH_CMD_TID_FREE: | 2102 | case IPATH_CMD_TID_FREE: |
1660 | ret = ipath_tid_free(pd, &cmd.cmd.tid_info); | 2103 | ret = ipath_tid_free(pd, subport_fp(fp), &cmd.cmd.tid_info); |
1661 | break; | 2104 | break; |
1662 | case IPATH_CMD_SET_PART_KEY: | 2105 | case IPATH_CMD_SET_PART_KEY: |
1663 | ret = ipath_set_part_key(pd, cmd.cmd.part_key); | 2106 | ret = ipath_set_part_key(pd, cmd.cmd.part_key); |
1664 | break; | 2107 | break; |
2108 | case IPATH_CMD_SLAVE_INFO: | ||
2109 | ret = ipath_get_slave_info(pd, | ||
2110 | (void __user *) (unsigned long) | ||
2111 | cmd.cmd.slave_mask_addr); | ||
2112 | break; | ||
1665 | } | 2113 | } |
1666 | 2114 | ||
1667 | if (ret >= 0) | 2115 | if (ret >= 0) |
@@ -1858,4 +2306,3 @@ void ipath_user_remove(struct ipath_devdata *dd) | |||
1858 | bail: | 2306 | bail: |
1859 | return; | 2307 | return; |
1860 | } | 2308 | } |
1861 | |||
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index a8a56276ff1d..0cabd4f16234 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -79,8 +79,8 @@ struct ipath_portdata { | |||
79 | dma_addr_t port_rcvhdrq_phys; | 79 | dma_addr_t port_rcvhdrq_phys; |
80 | dma_addr_t port_rcvhdrqtailaddr_phys; | 80 | dma_addr_t port_rcvhdrqtailaddr_phys; |
81 | /* | 81 | /* |
82 | * number of opens on this instance (0 or 1; ignoring forks, dup, | 82 | * number of opens (including slave subports) on this instance |
83 | * etc. for now) | 83 | * (ignoring forks, dup, etc. for now) |
84 | */ | 84 | */ |
85 | int port_cnt; | 85 | int port_cnt; |
86 | /* | 86 | /* |
@@ -89,6 +89,10 @@ struct ipath_portdata { | |||
89 | */ | 89 | */ |
90 | /* instead of calculating it */ | 90 | /* instead of calculating it */ |
91 | unsigned port_port; | 91 | unsigned port_port; |
92 | /* non-zero if port is being shared. */ | ||
93 | u16 port_subport_cnt; | ||
94 | /* non-zero if port is being shared. */ | ||
95 | u16 port_subport_id; | ||
92 | /* chip offset of PIO buffers for this port */ | 96 | /* chip offset of PIO buffers for this port */ |
93 | u32 port_piobufs; | 97 | u32 port_piobufs; |
94 | /* how many alloc_pages() chunks in port_rcvegrbuf_pages */ | 98 | /* how many alloc_pages() chunks in port_rcvegrbuf_pages */ |
@@ -121,6 +125,16 @@ struct ipath_portdata { | |||
121 | u16 port_pkeys[4]; | 125 | u16 port_pkeys[4]; |
122 | /* so file ops can get at unit */ | 126 | /* so file ops can get at unit */ |
123 | struct ipath_devdata *port_dd; | 127 | struct ipath_devdata *port_dd; |
128 | /* A page of memory for rcvhdrhead, rcvegrhead, rcvegrtail * N */ | ||
129 | void *subport_uregbase; | ||
130 | /* An array of pages for the eager receive buffers * N */ | ||
131 | void *subport_rcvegrbuf; | ||
132 | /* An array of pages for the eager header queue entries * N */ | ||
133 | void *subport_rcvhdr_base; | ||
134 | /* The version of the library which opened this port */ | ||
135 | u32 userversion; | ||
136 | /* Bitmask of active slaves */ | ||
137 | u32 active_slaves; | ||
124 | }; | 138 | }; |
125 | 139 | ||
126 | struct sk_buff; | 140 | struct sk_buff; |
@@ -512,6 +526,12 @@ struct ipath_devdata { | |||
512 | u32 ipath_lli_errors; | 526 | u32 ipath_lli_errors; |
513 | }; | 527 | }; |
514 | 528 | ||
529 | /* Private data for file operations */ | ||
530 | struct ipath_filedata { | ||
531 | struct ipath_portdata *pd; | ||
532 | unsigned subport; | ||
533 | unsigned tidcursor; | ||
534 | }; | ||
515 | extern struct list_head ipath_dev_list; | 535 | extern struct list_head ipath_dev_list; |
516 | extern spinlock_t ipath_devs_lock; | 536 | extern spinlock_t ipath_devs_lock; |
517 | extern struct ipath_devdata *ipath_lookup(int unit); | 537 | extern struct ipath_devdata *ipath_lookup(int unit); |
@@ -572,7 +592,11 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8); | |||
572 | int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv); | 592 | int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv); |
573 | 593 | ||
574 | /* for use in system calls, where we want to know device type, etc. */ | 594 | /* for use in system calls, where we want to know device type, etc. */ |
575 | #define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data) | 595 | #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd |
596 | #define subport_fp(fp) \ | ||
597 | ((struct ipath_filedata *)(fp)->private_data)->subport | ||
598 | #define tidcursor_fp(fp) \ | ||
599 | ((struct ipath_filedata *)(fp)->private_data)->tidcursor | ||
576 | 600 | ||
577 | /* | 601 | /* |
578 | * values for ipath_flags | 602 | * values for ipath_flags |
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index e299148c4b68..b48ebf62e5dd 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c | |||
@@ -297,6 +297,16 @@ static ssize_t show_nguid(struct device *dev, | |||
297 | return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid); | 297 | return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid); |
298 | } | 298 | } |
299 | 299 | ||
300 | static ssize_t show_nports(struct device *dev, | ||
301 | struct device_attribute *attr, | ||
302 | char *buf) | ||
303 | { | ||
304 | struct ipath_devdata *dd = dev_get_drvdata(dev); | ||
305 | |||
306 | /* Return the number of user ports available. */ | ||
307 | return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1); | ||
308 | } | ||
309 | |||
300 | static ssize_t show_serial(struct device *dev, | 310 | static ssize_t show_serial(struct device *dev, |
301 | struct device_attribute *attr, | 311 | struct device_attribute *attr, |
302 | char *buf) | 312 | char *buf) |
@@ -608,6 +618,7 @@ static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid); | |||
608 | static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu); | 618 | static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu); |
609 | static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled); | 619 | static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled); |
610 | static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL); | 620 | static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL); |
621 | static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL); | ||
611 | static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset); | 622 | static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset); |
612 | static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); | 623 | static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); |
613 | static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); | 624 | static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); |
@@ -623,6 +634,7 @@ static struct attribute *dev_attributes[] = { | |||
623 | &dev_attr_mlid.attr, | 634 | &dev_attr_mlid.attr, |
624 | &dev_attr_mtu.attr, | 635 | &dev_attr_mtu.attr, |
625 | &dev_attr_nguid.attr, | 636 | &dev_attr_nguid.attr, |
637 | &dev_attr_nports.attr, | ||
626 | &dev_attr_serial.attr, | 638 | &dev_attr_serial.attr, |
627 | &dev_attr_status.attr, | 639 | &dev_attr_status.attr, |
628 | &dev_attr_status_str.attr, | 640 | &dev_attr_status_str.attr, |