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> | |
50 | ||
51 | #include "hfi.h" | |
52 | #include "common.h" | |
53 | #include "sdma.h" | |
54 | ||
55 | /** | |
56 | * format_hwmsg - format a single hwerror message | |
57 | * @msg message buffer | |
58 | * @msgl length of message buffer | |
59 | * @hwmsg message to add to message buffer | |
60 | */ | |
61 | static void format_hwmsg(char *msg, size_t msgl, const char *hwmsg) | |
62 | { | |
63 | strlcat(msg, "[", msgl); | |
64 | strlcat(msg, hwmsg, msgl); | |
65 | strlcat(msg, "]", msgl); | |
66 | } | |
67 | ||
68 | /** | |
69 | * hfi1_format_hwerrors - format hardware error messages for display | |
70 | * @hwerrs hardware errors bit vector | |
71 | * @hwerrmsgs hardware error descriptions | |
72 | * @nhwerrmsgs number of hwerrmsgs | |
73 | * @msg message buffer | |
74 | * @msgl message buffer length | |
75 | */ | |
76 | void hfi1_format_hwerrors(u64 hwerrs, const struct hfi1_hwerror_msgs *hwerrmsgs, | |
77 | size_t nhwerrmsgs, char *msg, size_t msgl) | |
78 | { | |
79 | int i; | |
80 | ||
81 | for (i = 0; i < nhwerrmsgs; i++) | |
82 | if (hwerrs & hwerrmsgs[i].mask) | |
83 | format_hwmsg(msg, msgl, hwerrmsgs[i].msg); | |
84 | } | |
85 | ||
86 | static void signal_ib_event(struct hfi1_pportdata *ppd, enum ib_event_type ev) | |
87 | { | |
88 | struct ib_event event; | |
89 | struct hfi1_devdata *dd = ppd->dd; | |
90 | ||
91 | /* | |
92 | * Only call ib_dispatch_event() if the IB device has been | |
93 | * registered. HFI1_INITED is set iff the driver has successfully | |
94 | * registered with the IB core. | |
95 | */ | |
96 | if (!(dd->flags & HFI1_INITTED)) | |
97 | return; | |
ec3f2c12 | 98 | event.device = &dd->verbs_dev.rdi.ibdev; |
77241056 MM |
99 | event.element.port_num = ppd->port; |
100 | event.event = ev; | |
101 | ib_dispatch_event(&event); | |
102 | } | |
103 | ||
104 | /* | |
105 | * Handle a linkup or link down notification. | |
106 | * This is called outside an interrupt. | |
107 | */ | |
108 | void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup) | |
109 | { | |
110 | struct hfi1_pportdata *ppd = &dd->pport[0]; | |
111 | enum ib_event_type ev; | |
112 | ||
113 | if (!(ppd->linkup ^ !!linkup)) | |
114 | return; /* no change, nothing to do */ | |
115 | ||
116 | if (linkup) { | |
117 | /* | |
118 | * Quick linkup and all link up on the simulator does not | |
119 | * trigger or implement: | |
120 | * - VerifyCap interrupt | |
121 | * - VerifyCap frames | |
122 | * But rather moves directly to LinkUp. | |
123 | * | |
124 | * Do the work of the VerifyCap interrupt handler, | |
125 | * handle_verify_cap(), but do not try moving the state to | |
126 | * LinkUp as we are already there. | |
127 | * | |
128 | * NOTE: This uses this device's vAU, vCU, and vl15_init for | |
129 | * the remote values. Both sides must be using the values. | |
130 | */ | |
d0d236ea | 131 | if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) { |
77241056 MM |
132 | set_up_vl15(dd, dd->vau, dd->vl15_init); |
133 | assign_remote_cm_au_table(dd, dd->vcu); | |
134 | ppd->neighbor_guid = | |
17fb4f29 | 135 | read_csr(dd, DC_DC8051_STS_REMOTE_GUID); |
77241056 MM |
136 | ppd->neighbor_type = |
137 | read_csr(dd, DC_DC8051_STS_REMOTE_NODE_TYPE) & | |
138 | DC_DC8051_STS_REMOTE_NODE_TYPE_VAL_MASK; | |
139 | ppd->neighbor_port_number = | |
140 | read_csr(dd, DC_DC8051_STS_REMOTE_PORT_NO) & | |
17fb4f29 JJ |
141 | DC_DC8051_STS_REMOTE_PORT_NO_VAL_SMASK; |
142 | dd_dev_info(dd, "Neighbor GUID: %llx Neighbor type %d\n", | |
143 | ppd->neighbor_guid, | |
144 | ppd->neighbor_type); | |
77241056 MM |
145 | } |
146 | ||
147 | /* physical link went up */ | |
148 | ppd->linkup = 1; | |
a9c05e35 BM |
149 | ppd->offline_disabled_reason = |
150 | HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE); | |
77241056 MM |
151 | |
152 | /* link widths are not available until the link is fully up */ | |
153 | get_linkup_link_widths(ppd); | |
154 | ||
155 | } else { | |
156 | /* physical link went down */ | |
157 | ppd->linkup = 0; | |
158 | ||
159 | /* clear HW details of the previous connection */ | |
160 | reset_link_credits(dd); | |
161 | ||
162 | /* freeze after a link down to guarantee a clean egress */ | |
8638b77f | 163 | start_freeze_handling(ppd, FREEZE_SELF | FREEZE_LINK_DOWN); |
77241056 MM |
164 | |
165 | ev = IB_EVENT_PORT_ERR; | |
166 | ||
167 | hfi1_set_uevent_bits(ppd, _HFI1_EVENT_LINKDOWN_BIT); | |
168 | ||
169 | /* if we are down, the neighbor is down */ | |
170 | ppd->neighbor_normal = 0; | |
171 | ||
172 | /* notify IB of the link change */ | |
173 | signal_ib_event(ppd, ev); | |
174 | } | |
77241056 MM |
175 | } |
176 | ||
177 | /* | |
178 | * Handle receive or urgent interrupts for user contexts. This means a user | |
179 | * process was waiting for a packet to arrive, and didn't want to poll. | |
180 | */ | |
181 | void handle_user_interrupt(struct hfi1_ctxtdata *rcd) | |
182 | { | |
183 | struct hfi1_devdata *dd = rcd->dd; | |
184 | unsigned long flags; | |
185 | ||
186 | spin_lock_irqsave(&dd->uctxt_lock, flags); | |
187 | if (!rcd->cnt) | |
188 | goto done; | |
189 | ||
190 | if (test_and_clear_bit(HFI1_CTXT_WAITING_RCV, &rcd->event_flags)) { | |
191 | wake_up_interruptible(&rcd->wait); | |
192 | hfi1_rcvctrl(dd, HFI1_RCVCTRL_INTRAVAIL_DIS, rcd->ctxt); | |
193 | } else if (test_and_clear_bit(HFI1_CTXT_WAITING_URG, | |
194 | &rcd->event_flags)) { | |
195 | rcd->urgent++; | |
196 | wake_up_interruptible(&rcd->wait); | |
197 | } | |
198 | done: | |
199 | spin_unlock_irqrestore(&dd->uctxt_lock, flags); | |
200 | } |