Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | USERSPACE MAD ACCESS |
| 2 | |
| 3 | Device files |
| 4 | |
| 5 | Each port of each InfiniBand device has a "umad" device and an |
| 6 | "issm" device attached. For example, a two-port HCA will have two |
| 7 | umad devices and two issm devices, while a switch will have one |
| 8 | device of each type (for switch port 0). |
| 9 | |
| 10 | Creating MAD agents |
| 11 | |
| 12 | A MAD agent can be created by filling in a struct ib_user_mad_reg_req |
| 13 | and then calling the IB_USER_MAD_REGISTER_AGENT ioctl on a file |
| 14 | descriptor for the appropriate device file. If the registration |
| 15 | request succeeds, a 32-bit id will be returned in the structure. |
| 16 | For example: |
| 17 | |
| 18 | struct ib_user_mad_reg_req req = { /* ... */ }; |
| 19 | ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req); |
| 20 | if (!ret) |
| 21 | my_agent = req.id; |
| 22 | else |
| 23 | perror("agent register"); |
| 24 | |
| 25 | Agents can be unregistered with the IB_USER_MAD_UNREGISTER_AGENT |
| 26 | ioctl. Also, all agents registered through a file descriptor will |
| 27 | be unregistered when the descriptor is closed. |
| 28 | |
| 29 | Receiving MADs |
| 30 | |
| 31 | MADs are received using read(). The buffer passed to read() must be |
| 32 | large enough to hold at least one struct ib_user_mad. For example: |
| 33 | |
| 34 | struct ib_user_mad mad; |
| 35 | ret = read(fd, &mad, sizeof mad); |
| 36 | if (ret != sizeof mad) |
| 37 | perror("read"); |
| 38 | |
| 39 | In addition to the actual MAD contents, the other struct ib_user_mad |
| 40 | fields will be filled in with information on the received MAD. For |
| 41 | example, the remote LID will be in mad.lid. |
| 42 | |
| 43 | If a send times out, a receive will be generated with mad.status set |
| 44 | to ETIMEDOUT. Otherwise when a MAD has been successfully received, |
| 45 | mad.status will be 0. |
| 46 | |
| 47 | poll()/select() may be used to wait until a MAD can be read. |
| 48 | |
| 49 | Sending MADs |
| 50 | |
| 51 | MADs are sent using write(). The agent ID for sending should be |
| 52 | filled into the id field of the MAD, the destination LID should be |
| 53 | filled into the lid field, and so on. For example: |
| 54 | |
| 55 | struct ib_user_mad mad; |
| 56 | |
| 57 | /* fill in mad.data */ |
| 58 | |
| 59 | mad.id = my_agent; /* req.id from agent registration */ |
| 60 | mad.lid = my_dest; /* in network byte order... */ |
| 61 | /* etc. */ |
| 62 | |
| 63 | ret = write(fd, &mad, sizeof mad); |
| 64 | if (ret != sizeof mad) |
| 65 | perror("write"); |
| 66 | |
| 67 | Setting IsSM Capability Bit |
| 68 | |
| 69 | To set the IsSM capability bit for a port, simply open the |
| 70 | corresponding issm device file. If the IsSM bit is already set, |
| 71 | then the open call will block until the bit is cleared (or return |
| 72 | immediately with errno set to EAGAIN if the O_NONBLOCK flag is |
| 73 | passed to open()). The IsSM bit will be cleared when the issm file |
| 74 | is closed. No read, write or other operations can be performed on |
| 75 | the issm file. |
| 76 | |
| 77 | /dev files |
| 78 | |
| 79 | To create the appropriate character device files automatically with |
| 80 | udev, a rule like |
| 81 | |
| 82 | KERNEL="umad*", NAME="infiniband/%k" |
| 83 | KERNEL="issm*", NAME="infiniband/%k" |
| 84 | |
| 85 | can be used. This will create device nodes named |
| 86 | |
| 87 | /dev/infiniband/umad0 |
| 88 | /dev/infiniband/issm0 |
| 89 | |
| 90 | for the first port, and so on. The InfiniBand device and port |
| 91 | associated with these devices can be determined from the files |
| 92 | |
| 93 | /sys/class/infiniband_mad/umad0/ibdev |
| 94 | /sys/class/infiniband_mad/umad0/port |
| 95 | |
| 96 | and |
| 97 | |
| 98 | /sys/class/infiniband_mad/issm0/ibdev |
| 99 | /sys/class/infiniband_mad/issm0/port |