]>
Commit | Line | Data |
---|---|---|
77241056 | 1 | /* |
05d6ac1d | 2 | * Copyright(c) 2015, 2016 Intel Corporation. |
77241056 MM |
3 | * |
4 | * This file is provided under a dual BSD/GPLv2 license. When using or | |
5 | * redistributing this file, you may do so under either license. | |
6 | * | |
7 | * GPL LICENSE SUMMARY | |
8 | * | |
77241056 MM |
9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of version 2 of the GNU General Public License as | |
11 | * published by the Free Software Foundation. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | * BSD LICENSE | |
19 | * | |
77241056 MM |
20 | * Redistribution and use in source and binary forms, with or without |
21 | * modification, are permitted provided that the following conditions | |
22 | * are met: | |
23 | * | |
24 | * - Redistributions of source code must retain the above copyright | |
25 | * notice, this list of conditions and the following disclaimer. | |
26 | * - Redistributions in binary form must reproduce the above copyright | |
27 | * notice, this list of conditions and the following disclaimer in | |
28 | * the documentation and/or other materials provided with the | |
29 | * distribution. | |
30 | * - Neither the name of Intel Corporation nor the names of its | |
31 | * contributors may be used to endorse or promote products derived | |
32 | * from this software without specific prior written permission. | |
33 | * | |
34 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
35 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
36 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
37 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
38 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
39 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
40 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
41 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
42 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
43 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
44 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
45 | * | |
46 | */ | |
47 | ||
48 | #include <linux/pci.h> | |
49 | #include <linux/delay.h> | |
8737ce95 | 50 | #include <linux/bitmap.h> |
77241056 MM |
51 | |
52 | #include "hfi.h" | |
53 | #include "common.h" | |
54 | #include "sdma.h" | |
55 | ||
56 | /** | |
57 | * format_hwmsg - format a single hwerror message | |
58 | * @msg message buffer | |
59 | * @msgl length of message buffer | |
60 | * @hwmsg message to add to message buffer | |
61 | */ | |
62 | static void format_hwmsg(char *msg, size_t msgl, const char *hwmsg) | |
63 | { | |
64 | strlcat(msg, "[", msgl); | |
65 | strlcat(msg, hwmsg, msgl); | |
66 | strlcat(msg, "]", msgl); | |
67 | } | |
68 | ||
69 | /** | |
70 | * hfi1_format_hwerrors - format hardware error messages for display | |
71 | * @hwerrs hardware errors bit vector | |
72 | * @hwerrmsgs hardware error descriptions | |
73 | * @nhwerrmsgs number of hwerrmsgs | |
74 | * @msg message buffer | |
75 | * @msgl message buffer length | |
76 | */ | |
77 | void hfi1_format_hwerrors(u64 hwerrs, const struct hfi1_hwerror_msgs *hwerrmsgs, | |
78 | size_t nhwerrmsgs, char *msg, size_t msgl) | |
79 | { | |
80 | int i; | |
81 | ||
82 | for (i = 0; i < nhwerrmsgs; i++) | |
83 | if (hwerrs & hwerrmsgs[i].mask) | |
84 | format_hwmsg(msg, msgl, hwerrmsgs[i].msg); | |
85 | } | |
86 | ||
87 | static void signal_ib_event(struct hfi1_pportdata *ppd, enum ib_event_type ev) | |
88 | { | |
89 | struct ib_event event; | |
90 | struct hfi1_devdata *dd = ppd->dd; | |
91 | ||
92 | /* | |
93 | * Only call ib_dispatch_event() if the IB device has been | |
94 | * registered. HFI1_INITED is set iff the driver has successfully | |
95 | * registered with the IB core. | |
96 | */ | |
97 | if (!(dd->flags & HFI1_INITTED)) | |
98 | return; | |
ec3f2c12 | 99 | event.device = &dd->verbs_dev.rdi.ibdev; |
77241056 MM |
100 | event.element.port_num = ppd->port; |
101 | event.event = ev; | |
102 | ib_dispatch_event(&event); | |
103 | } | |
104 | ||
105 | /* | |
106 | * Handle a linkup or link down notification. | |
107 | * This is called outside an interrupt. | |
108 | */ | |
109 | void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup) | |
110 | { | |
111 | struct hfi1_pportdata *ppd = &dd->pport[0]; | |
112 | enum ib_event_type ev; | |
113 | ||
114 | if (!(ppd->linkup ^ !!linkup)) | |
115 | return; /* no change, nothing to do */ | |
116 | ||
117 | if (linkup) { | |
118 | /* | |
119 | * Quick linkup and all link up on the simulator does not | |
120 | * trigger or implement: | |
121 | * - VerifyCap interrupt | |
122 | * - VerifyCap frames | |
123 | * But rather moves directly to LinkUp. | |
124 | * | |
125 | * Do the work of the VerifyCap interrupt handler, | |
126 | * handle_verify_cap(), but do not try moving the state to | |
127 | * LinkUp as we are already there. | |
128 | * | |
129 | * NOTE: This uses this device's vAU, vCU, and vl15_init for | |
130 | * the remote values. Both sides must be using the values. | |
131 | */ | |
d0d236ea | 132 | if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) { |
b3e6b4bd BJ |
133 | set_up_vau(dd, dd->vau); |
134 | set_up_vl15(dd, dd->vl15_init); | |
77241056 | 135 | assign_remote_cm_au_table(dd, dd->vcu); |
77241056 MM |
136 | } |
137 | ||
98b9ee20 SS |
138 | ppd->neighbor_guid = |
139 | read_csr(dd, DC_DC8051_STS_REMOTE_GUID); | |
140 | ppd->neighbor_type = | |
141 | read_csr(dd, DC_DC8051_STS_REMOTE_NODE_TYPE) & | |
142 | DC_DC8051_STS_REMOTE_NODE_TYPE_VAL_MASK; | |
143 | ppd->neighbor_port_number = | |
144 | read_csr(dd, DC_DC8051_STS_REMOTE_PORT_NO) & | |
145 | DC_DC8051_STS_REMOTE_PORT_NO_VAL_SMASK; | |
146 | ppd->neighbor_fm_security = | |
147 | read_csr(dd, DC_DC8051_STS_REMOTE_FM_SECURITY) & | |
148 | DC_DC8051_STS_LOCAL_FM_SECURITY_DISABLED_MASK; | |
149 | dd_dev_info(dd, | |
150 | "Neighbor Guid %llx, Type %d, Port Num %d\n", | |
151 | ppd->neighbor_guid, ppd->neighbor_type, | |
152 | ppd->neighbor_port_number); | |
153 | ||
77241056 MM |
154 | /* physical link went up */ |
155 | ppd->linkup = 1; | |
a9c05e35 BM |
156 | ppd->offline_disabled_reason = |
157 | HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE); | |
77241056 MM |
158 | |
159 | /* link widths are not available until the link is fully up */ | |
160 | get_linkup_link_widths(ppd); | |
161 | ||
162 | } else { | |
163 | /* physical link went down */ | |
164 | ppd->linkup = 0; | |
165 | ||
166 | /* clear HW details of the previous connection */ | |
167 | reset_link_credits(dd); | |
168 | ||
169 | /* freeze after a link down to guarantee a clean egress */ | |
8638b77f | 170 | start_freeze_handling(ppd, FREEZE_SELF | FREEZE_LINK_DOWN); |
77241056 MM |
171 | |
172 | ev = IB_EVENT_PORT_ERR; | |
173 | ||
174 | hfi1_set_uevent_bits(ppd, _HFI1_EVENT_LINKDOWN_BIT); | |
175 | ||
176 | /* if we are down, the neighbor is down */ | |
177 | ppd->neighbor_normal = 0; | |
178 | ||
179 | /* notify IB of the link change */ | |
180 | signal_ib_event(ppd, ev); | |
181 | } | |
77241056 MM |
182 | } |
183 | ||
184 | /* | |
185 | * Handle receive or urgent interrupts for user contexts. This means a user | |
186 | * process was waiting for a packet to arrive, and didn't want to poll. | |
187 | */ | |
188 | void handle_user_interrupt(struct hfi1_ctxtdata *rcd) | |
189 | { | |
190 | struct hfi1_devdata *dd = rcd->dd; | |
191 | unsigned long flags; | |
192 | ||
193 | spin_lock_irqsave(&dd->uctxt_lock, flags); | |
8737ce95 | 194 | if (bitmap_empty(rcd->in_use_ctxts, HFI1_MAX_SHARED_CTXTS)) |
77241056 MM |
195 | goto done; |
196 | ||
197 | if (test_and_clear_bit(HFI1_CTXT_WAITING_RCV, &rcd->event_flags)) { | |
198 | wake_up_interruptible(&rcd->wait); | |
199 | hfi1_rcvctrl(dd, HFI1_RCVCTRL_INTRAVAIL_DIS, rcd->ctxt); | |
200 | } else if (test_and_clear_bit(HFI1_CTXT_WAITING_URG, | |
201 | &rcd->event_flags)) { | |
202 | rcd->urgent++; | |
203 | wake_up_interruptible(&rcd->wait); | |
204 | } | |
205 | done: | |
206 | spin_unlock_irqrestore(&dd->uctxt_lock, flags); | |
207 | } |