1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
2 | /* |
3 | * Copyright(c) 2015, 2016 Intel Corporation. |
4 | */ |
5 | |
6 | #include <linux/pci.h> |
7 | #include <linux/delay.h> |
8 | #include <linux/bitmap.h> |
9 | |
10 | #include "hfi.h" |
11 | #include "common.h" |
12 | #include "sdma.h" |
13 | |
14 | #define LINK_UP_DELAY 500 /* in microseconds */ |
15 | |
16 | static void set_mgmt_allowed(struct hfi1_pportdata *ppd) |
17 | { |
18 | u32 frame; |
19 | struct hfi1_devdata *dd = ppd->dd; |
20 | |
21 | if (ppd->neighbor_type == NEIGHBOR_TYPE_HFI) { |
22 | ppd->mgmt_allowed = 1; |
23 | } else { |
24 | read_8051_config(dd, REMOTE_LNI_INFO, GENERAL_CONFIG, &frame); |
25 | ppd->mgmt_allowed = (frame >> MGMT_ALLOWED_SHIFT) |
26 | & MGMT_ALLOWED_MASK; |
27 | } |
28 | } |
29 | |
30 | /* |
31 | * Our neighbor has indicated that we are allowed to act as a fabric |
32 | * manager, so place the full management partition key in the second |
33 | * (0-based) pkey array position. Note that we should already have |
34 | * the limited management partition key in array element 1, and also |
35 | * that the port is not yet up when add_full_mgmt_pkey() is invoked. |
36 | */ |
37 | static void add_full_mgmt_pkey(struct hfi1_pportdata *ppd) |
38 | { |
39 | struct hfi1_devdata *dd = ppd->dd; |
40 | |
41 | /* Sanity check - ppd->pkeys[2] should be 0, or already initialized */ |
42 | if (!((ppd->pkeys[2] == 0) || (ppd->pkeys[2] == FULL_MGMT_P_KEY))) |
43 | dd_dev_warn(dd, "%s pkey[2] already set to 0x%x, resetting it to 0x%x\n" , |
44 | __func__, ppd->pkeys[2], FULL_MGMT_P_KEY); |
45 | ppd->pkeys[2] = FULL_MGMT_P_KEY; |
46 | (void)hfi1_set_ib_cfg(ppd, HFI1_IB_CFG_PKEYS, val: 0); |
47 | hfi1_event_pkey_change(dd: ppd->dd, port: ppd->port); |
48 | } |
49 | |
50 | /** |
51 | * format_hwmsg - format a single hwerror message |
52 | * @msg: message buffer |
53 | * @msgl: length of message buffer |
54 | * @hwmsg: message to add to message buffer |
55 | */ |
56 | static void format_hwmsg(char *msg, size_t msgl, const char *hwmsg) |
57 | { |
58 | strlcat(p: msg, q: "[" , avail: msgl); |
59 | strlcat(p: msg, q: hwmsg, avail: msgl); |
60 | strlcat(p: msg, q: "]" , avail: msgl); |
61 | } |
62 | |
63 | /** |
64 | * hfi1_format_hwerrors - format hardware error messages for display |
65 | * @hwerrs: hardware errors bit vector |
66 | * @hwerrmsgs: hardware error descriptions |
67 | * @nhwerrmsgs: number of hwerrmsgs |
68 | * @msg: message buffer |
69 | * @msgl: message buffer length |
70 | */ |
71 | void hfi1_format_hwerrors(u64 hwerrs, const struct hfi1_hwerror_msgs *hwerrmsgs, |
72 | size_t nhwerrmsgs, char *msg, size_t msgl) |
73 | { |
74 | int i; |
75 | |
76 | for (i = 0; i < nhwerrmsgs; i++) |
77 | if (hwerrs & hwerrmsgs[i].mask) |
78 | format_hwmsg(msg, msgl, hwmsg: hwerrmsgs[i].msg); |
79 | } |
80 | |
81 | static void signal_ib_event(struct hfi1_pportdata *ppd, enum ib_event_type ev) |
82 | { |
83 | struct ib_event event; |
84 | struct hfi1_devdata *dd = ppd->dd; |
85 | |
86 | /* |
87 | * Only call ib_dispatch_event() if the IB device has been |
88 | * registered. HFI1_INITED is set iff the driver has successfully |
89 | * registered with the IB core. |
90 | */ |
91 | if (!(dd->flags & HFI1_INITTED)) |
92 | return; |
93 | event.device = &dd->verbs_dev.rdi.ibdev; |
94 | event.element.port_num = ppd->port; |
95 | event.event = ev; |
96 | ib_dispatch_event(event: &event); |
97 | } |
98 | |
99 | /** |
100 | * handle_linkup_change - finish linkup/down state changes |
101 | * @dd: valid device |
102 | * @linkup: link state information |
103 | * |
104 | * Handle a linkup or link down notification. |
105 | * The HW needs time to finish its link up state change. Give it that chance. |
106 | * |
107 | * This is called outside an interrupt. |
108 | * |
109 | */ |
110 | void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup) |
111 | { |
112 | struct hfi1_pportdata *ppd = &dd->pport[0]; |
113 | enum ib_event_type ev; |
114 | |
115 | if (!(ppd->linkup ^ !!linkup)) |
116 | return; /* no change, nothing to do */ |
117 | |
118 | if (linkup) { |
119 | /* |
120 | * Quick linkup and all link up on the simulator does not |
121 | * trigger or implement: |
122 | * - VerifyCap interrupt |
123 | * - VerifyCap frames |
124 | * But rather moves directly to LinkUp. |
125 | * |
126 | * Do the work of the VerifyCap interrupt handler, |
127 | * handle_verify_cap(), but do not try moving the state to |
128 | * LinkUp as we are already there. |
129 | * |
130 | * NOTE: This uses this device's vAU, vCU, and vl15_init for |
131 | * the remote values. Both sides must be using the values. |
132 | */ |
133 | if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) { |
134 | set_up_vau(dd, vau: dd->vau); |
135 | set_up_vl15(dd, vl15buf: dd->vl15_init); |
136 | assign_remote_cm_au_table(dd, vcu: dd->vcu); |
137 | } |
138 | |
139 | ppd->neighbor_guid = |
140 | read_csr(dd, DC_DC8051_STS_REMOTE_GUID); |
141 | ppd->neighbor_type = |
142 | read_csr(dd, DC_DC8051_STS_REMOTE_NODE_TYPE) & |
143 | DC_DC8051_STS_REMOTE_NODE_TYPE_VAL_MASK; |
144 | ppd->neighbor_port_number = |
145 | read_csr(dd, DC_DC8051_STS_REMOTE_PORT_NO) & |
146 | DC_DC8051_STS_REMOTE_PORT_NO_VAL_SMASK; |
147 | ppd->neighbor_fm_security = |
148 | read_csr(dd, DC_DC8051_STS_REMOTE_FM_SECURITY) & |
149 | DC_DC8051_STS_LOCAL_FM_SECURITY_DISABLED_MASK; |
150 | dd_dev_info(dd, |
151 | "Neighbor Guid %llx, Type %d, Port Num %d\n" , |
152 | ppd->neighbor_guid, ppd->neighbor_type, |
153 | ppd->neighbor_port_number); |
154 | |
155 | /* HW needs LINK_UP_DELAY to settle, give it that chance */ |
156 | udelay(LINK_UP_DELAY); |
157 | |
158 | /* |
159 | * 'MgmtAllowed' information, which is exchanged during |
160 | * LNI, is available at this point. |
161 | */ |
162 | set_mgmt_allowed(ppd); |
163 | |
164 | if (ppd->mgmt_allowed) |
165 | add_full_mgmt_pkey(ppd); |
166 | |
167 | /* physical link went up */ |
168 | ppd->linkup = 1; |
169 | ppd->offline_disabled_reason = |
170 | HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE); |
171 | |
172 | /* link widths are not available until the link is fully up */ |
173 | get_linkup_link_widths(ppd); |
174 | |
175 | } else { |
176 | /* physical link went down */ |
177 | ppd->linkup = 0; |
178 | |
179 | /* clear HW details of the previous connection */ |
180 | ppd->actual_vls_operational = 0; |
181 | reset_link_credits(dd); |
182 | |
183 | /* freeze after a link down to guarantee a clean egress */ |
184 | start_freeze_handling(ppd, FREEZE_SELF | FREEZE_LINK_DOWN); |
185 | |
186 | ev = IB_EVENT_PORT_ERR; |
187 | |
188 | hfi1_set_uevent_bits(ppd, _HFI1_EVENT_LINKDOWN_BIT); |
189 | |
190 | /* if we are down, the neighbor is down */ |
191 | ppd->neighbor_normal = 0; |
192 | |
193 | /* notify IB of the link change */ |
194 | signal_ib_event(ppd, ev); |
195 | } |
196 | } |
197 | |
198 | /* |
199 | * Handle receive or urgent interrupts for user contexts. This means a user |
200 | * process was waiting for a packet to arrive, and didn't want to poll. |
201 | */ |
202 | void handle_user_interrupt(struct hfi1_ctxtdata *rcd) |
203 | { |
204 | struct hfi1_devdata *dd = rcd->dd; |
205 | unsigned long flags; |
206 | |
207 | spin_lock_irqsave(&dd->uctxt_lock, flags); |
208 | if (bitmap_empty(src: rcd->in_use_ctxts, HFI1_MAX_SHARED_CTXTS)) |
209 | goto done; |
210 | |
211 | if (test_and_clear_bit(HFI1_CTXT_WAITING_RCV, addr: &rcd->event_flags)) { |
212 | wake_up_interruptible(&rcd->wait); |
213 | hfi1_rcvctrl(dd, HFI1_RCVCTRL_INTRAVAIL_DIS, rcd); |
214 | } else if (test_and_clear_bit(HFI1_CTXT_WAITING_URG, |
215 | addr: &rcd->event_flags)) { |
216 | rcd->urgent++; |
217 | wake_up_interruptible(&rcd->wait); |
218 | } |
219 | done: |
220 | spin_unlock_irqrestore(lock: &dd->uctxt_lock, flags); |
221 | } |
222 | |