]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | Subject: Update lpfc to 8.2.8.4 |
2 | From: Hannes Reinecke <hare@suse.de> | |
3 | Date: Tue Oct 7 13:50:11 2008 +0200: | |
4 | References: bnc#420767 | |
5 | ||
6 | This patch updates the SLES 11 lpfc driver to 8.2.8.4 which has | |
7 | the following changes: | |
8 | ||
9 | * Changed version number to 8.2.8.4 | |
10 | * Added code to get option ROM version from HBA | |
11 | * Added support for FC_REG_VPORTRSCN_EVENT | |
12 | * Fix the authentication error when the initial authentication is rejected | |
13 | * Add the lpfc_symbolic_name back into the scsi_host attributes | |
14 | * Fix vport failed to create when link was down or in loop (CR 83339) | |
15 | * Fix authentication failures always show up an generic errors (CR 74969) | |
16 | * Fixed statistical data collection for virtual ports | |
17 | * Support changes to vport's symbolic name | |
18 | * Fix Vport created in disabled state doesn't have correct state | |
19 | * Fix vport disable attribute missing | |
20 | * Fix vport attributes by removing physical attributes | |
21 | ||
22 | Signed-off-by: Jamie Wellnitz <jamie.wellnitz@emulex.com> | |
23 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
24 | ||
25 | diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h | |
26 | index 10e1ac6..7508dea 100644 | |
27 | --- a/drivers/scsi/lpfc/lpfc.h | |
28 | +++ b/drivers/scsi/lpfc/lpfc.h | |
29 | @@ -328,6 +328,11 @@ enum auth_state { | |
30 | LPFC_AUTH_UNKNOWN = 0, | |
31 | LPFC_AUTH_SUCCESS = 1, | |
32 | LPFC_AUTH_FAIL = 2, | |
33 | + LPFC_AUTH_FAIL_ELS_TMO = 3, | |
34 | + LPFC_AUTH_FAIL_TRANS_TMO = 4, | |
35 | + LPFC_AUTH_FAIL_LS_RJT_GEN = 5, | |
36 | + LPFC_AUTH_FAIL_LS_RJT_BUSY = 6, | |
37 | + LPFC_AUTH_FAIL_AUTH_RJT = 7, | |
38 | }; | |
39 | enum auth_msg_state { | |
40 | LPFC_AUTH_NONE = 0, | |
41 | @@ -463,8 +468,6 @@ struct lpfc_vport { | |
42 | uint8_t load_flag; | |
43 | #define FC_LOADING 0x1 /* HBA in process of loading drvr */ | |
44 | #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ | |
45 | - char *vname; /* Application assigned name */ | |
46 | - | |
47 | /* Fields used for accessing auth service */ | |
48 | struct lpfc_auth auth; | |
49 | uint32_t sc_tran_id; | |
50 | diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c | |
51 | index 8e94902..1069491 100644 | |
52 | --- a/drivers/scsi/lpfc/lpfc_attr.c | |
53 | +++ b/drivers/scsi/lpfc/lpfc_attr.c | |
54 | @@ -1107,6 +1107,17 @@ lpfc_auth_state_show(struct device *dev, struct device_attribute *attr, | |
55 | return snprintf(buf, PAGE_SIZE, "Not Authenticated\n"); | |
56 | case LPFC_AUTH_FAIL: | |
57 | return snprintf(buf, PAGE_SIZE, "Failed\n"); | |
58 | + case LPFC_AUTH_FAIL_ELS_TMO: | |
59 | + return snprintf(buf, PAGE_SIZE, "Failed - ELS Timeout\n"); | |
60 | + case LPFC_AUTH_FAIL_TRANS_TMO: | |
61 | + return snprintf(buf, PAGE_SIZE, "Failed - " | |
62 | + "Transaction Timeout\n"); | |
63 | + case LPFC_AUTH_FAIL_LS_RJT_GEN: | |
64 | + return snprintf(buf, PAGE_SIZE, "Failed - LS_RJT\n"); | |
65 | + case LPFC_AUTH_FAIL_LS_RJT_BUSY: | |
66 | + return snprintf(buf, PAGE_SIZE, "Failed - LS_RJT Busy\n"); | |
67 | + case LPFC_AUTH_FAIL_AUTH_RJT: | |
68 | + return snprintf(buf, PAGE_SIZE, "Failed - AUTH RJT\n"); | |
69 | case LPFC_AUTH_SUCCESS: | |
70 | if (vport->auth.auth_msg_state == LPFC_AUTH_NEGOTIATE || | |
71 | vport->auth.auth_msg_state == LPFC_DHCHAP_CHALLENGE || | |
72 | @@ -1665,6 +1676,20 @@ static DEVICE_ATTR(auth_hash, S_IRUGO, lpfc_auth_hash_show, NULL); | |
73 | static DEVICE_ATTR(auth_last, S_IRUGO, lpfc_auth_last_show, NULL); | |
74 | static DEVICE_ATTR(auth_next, S_IRUGO, lpfc_auth_next_show, NULL); | |
75 | ||
76 | +static ssize_t | |
77 | +lpfc_symbolic_name_show(struct device *dev, struct device_attribute *attr, | |
78 | + char *buf) | |
79 | +{ | |
80 | + struct Scsi_Host *shost = class_to_shost(dev); | |
81 | + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | |
82 | + int length; | |
83 | + char symbname[256]; | |
84 | + | |
85 | + length = lpfc_vport_symbolic_port_name(vport, symbname, 256); | |
86 | + return snprintf(buf, PAGE_SIZE, "%s\n", symbname); | |
87 | +} | |
88 | +static DEVICE_ATTR(lpfc_symbolic_name, S_IRUGO, lpfc_symbolic_name_show, NULL); | |
89 | + | |
90 | static int | |
91 | lpfc_parse_wwn(const char *ns, uint8_t *nm) | |
92 | { | |
93 | @@ -3134,6 +3159,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |
94 | &dev_attr_auth_hash, | |
95 | &dev_attr_auth_last, | |
96 | &dev_attr_auth_next, | |
97 | + &dev_attr_lpfc_symbolic_name, | |
98 | &dev_attr_lpfc_soft_wwnn, | |
99 | &dev_attr_lpfc_soft_wwpn, | |
100 | &dev_attr_lpfc_soft_wwn_enable, | |
101 | @@ -3171,7 +3197,7 @@ struct device_attribute *lpfc_vport_attrs[] = { | |
102 | &dev_attr_auth_hash, | |
103 | &dev_attr_auth_last, | |
104 | &dev_attr_auth_next, | |
105 | - | |
106 | + &dev_attr_lpfc_symbolic_name, | |
107 | &dev_attr_lpfc_max_scsicmpl_time, | |
108 | &dev_attr_lpfc_stat_data_ctrl, | |
109 | NULL, | |
110 | @@ -4134,25 +4160,28 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport) | |
111 | int error; | |
112 | ||
113 | error = sysfs_create_bin_file(&shost->shost_dev.kobj, | |
114 | - &sysfs_ctlreg_attr); | |
115 | - if (error) | |
116 | + &sysfs_drvr_stat_data_attr); | |
117 | + | |
118 | + /* Virtual ports do not need ctrl_reg and mbox */ | |
119 | + if (error || vport->port_type == LPFC_NPIV_PORT) | |
120 | goto out; | |
121 | ||
122 | error = sysfs_create_bin_file(&shost->shost_dev.kobj, | |
123 | - &sysfs_mbox_attr); | |
124 | + &sysfs_ctlreg_attr); | |
125 | if (error) | |
126 | - goto out_remove_ctlreg_attr; | |
127 | + goto out_remove_stat_attr; | |
128 | ||
129 | error = sysfs_create_bin_file(&shost->shost_dev.kobj, | |
130 | - &sysfs_drvr_stat_data_attr); | |
131 | + &sysfs_mbox_attr); | |
132 | if (error) | |
133 | - goto out_remove_mbox_attr; | |
134 | + goto out_remove_ctlreg_attr; | |
135 | ||
136 | return 0; | |
137 | -out_remove_mbox_attr: | |
138 | - sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr); | |
139 | out_remove_ctlreg_attr: | |
140 | sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); | |
141 | +out_remove_stat_attr: | |
142 | + sysfs_remove_bin_file(&shost->shost_dev.kobj, | |
143 | + &sysfs_drvr_stat_data_attr); | |
144 | out: | |
145 | return error; | |
146 | } | |
147 | @@ -4167,6 +4196,9 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) | |
148 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | |
149 | sysfs_remove_bin_file(&shost->shost_dev.kobj, | |
150 | &sysfs_drvr_stat_data_attr); | |
151 | + /* Virtual ports do not need ctrl_reg and mbox */ | |
152 | + if (vport->port_type == LPFC_NPIV_PORT) | |
153 | + return; | |
154 | sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr); | |
155 | sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); | |
156 | sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_menlo_attr); | |
157 | @@ -4645,6 +4677,23 @@ lpfc_show_rport_##field (struct device *dev, \ | |
158 | lpfc_rport_show_function(field, format_string, sz, ) \ | |
159 | static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL) | |
160 | ||
161 | +/** | |
162 | + * lpfc_set_vport_symbolic_name: Set the vport's symbolic name. | |
163 | + * @fc_vport: The fc_vport who's symbolic name has been changed. | |
164 | + * | |
165 | + * Description: | |
166 | + * This function is called by the transport after the @fc_vport's symbolic name | |
167 | + * has been changed. This function re-registers the symbolic name with the | |
168 | + * switch to propogate the change into the fabric if the vport is active. | |
169 | + **/ | |
170 | +static void | |
171 | +lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport) | |
172 | +{ | |
173 | + struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; | |
174 | + | |
175 | + if (vport->port_state == LPFC_VPORT_READY) | |
176 | + lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0); | |
177 | +} | |
178 | ||
179 | struct fc_function_template lpfc_transport_functions = { | |
180 | /* fixed attributes the driver supports */ | |
181 | @@ -4654,6 +4703,7 @@ struct fc_function_template lpfc_transport_functions = { | |
182 | .show_host_supported_fc4s = 1, | |
183 | .show_host_supported_speeds = 1, | |
184 | .show_host_maxframe_size = 1, | |
185 | + .show_host_symbolic_name = 1, | |
186 | ||
187 | /* dynamic attributes the driver supports */ | |
188 | .get_host_port_id = lpfc_get_host_port_id, | |
189 | @@ -4703,6 +4753,10 @@ struct fc_function_template lpfc_transport_functions = { | |
190 | .terminate_rport_io = lpfc_terminate_rport_io, | |
191 | ||
192 | .dd_fcvport_size = sizeof(struct lpfc_vport *), | |
193 | + | |
194 | + .vport_disable = lpfc_vport_disable, | |
195 | + | |
196 | + .set_vport_symbolic_name = lpfc_set_vport_symbolic_name, | |
197 | }; | |
198 | ||
199 | struct fc_function_template lpfc_vport_transport_functions = { | |
200 | @@ -4713,6 +4767,7 @@ struct fc_function_template lpfc_vport_transport_functions = { | |
201 | .show_host_supported_fc4s = 1, | |
202 | .show_host_supported_speeds = 1, | |
203 | .show_host_maxframe_size = 1, | |
204 | + .show_host_symbolic_name = 1, | |
205 | ||
206 | /* dynamic attributes the driver supports */ | |
207 | .get_host_port_id = lpfc_get_host_port_id, | |
208 | @@ -4761,6 +4816,8 @@ struct fc_function_template lpfc_vport_transport_functions = { | |
209 | .terminate_rport_io = lpfc_terminate_rport_io, | |
210 | ||
211 | .vport_disable = lpfc_vport_disable, | |
212 | + | |
213 | + .set_vport_symbolic_name = lpfc_set_vport_symbolic_name, | |
214 | }; | |
215 | ||
216 | /** | |
217 | @@ -4788,6 +4845,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |
218 | phba->cfg_soft_wwpn = 0L; | |
219 | lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); | |
220 | /* Also reinitialize the host templates with new values. */ | |
221 | + lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; | |
222 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; | |
223 | /* | |
224 | * Since the sg_tablesize is module parameter, the sg_dma_buf_size | |
225 | diff --git a/drivers/scsi/lpfc/lpfc_auth.c b/drivers/scsi/lpfc/lpfc_auth.c | |
226 | index 6a5da93..7dc3600 100644 | |
227 | --- a/drivers/scsi/lpfc/lpfc_auth.c | |
228 | +++ b/drivers/scsi/lpfc/lpfc_auth.c | |
229 | @@ -179,9 +179,8 @@ lpfc_dhchap_authenticate(struct Scsi_Host *shost, | |
230 | ndlp->nlp_DID); | |
231 | lpfc_issue_els_auth_reject(vport, ndlp, | |
232 | AUTH_ERR, AUTHENTICATION_FAILED); | |
233 | - if (vport->auth.auth_state == LPFC_AUTH_SUCCESS) { | |
234 | - lpfc_port_auth_failed(ndlp); | |
235 | - } | |
236 | + if (vport->auth.auth_state == LPFC_AUTH_SUCCESS) | |
237 | + lpfc_port_auth_failed(ndlp, LPFC_AUTH_FAIL_AUTH_RJT); | |
238 | } | |
239 | ||
240 | kfree(rsp); | |
241 | diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h | |
242 | index a93c555..380acef 100644 | |
243 | --- a/drivers/scsi/lpfc/lpfc_crtn.h | |
244 | +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |
245 | @@ -28,6 +28,7 @@ int lpfc_issue_els_auth_reject(struct lpfc_vport *vport, | |
246 | struct lpfc_nodelist *ndlp, | |
247 | uint8_t reason, uint8_t explanation); | |
248 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); | |
249 | +void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); | |
250 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); | |
251 | void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); | |
252 | ||
253 | @@ -89,7 +90,7 @@ struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); | |
254 | struct lpfc_nodelist *lpfc_findnode_wwnn(struct lpfc_vport *, | |
255 | struct lpfc_name *); | |
256 | ||
257 | -void lpfc_port_auth_failed(struct lpfc_nodelist *); | |
258 | +void lpfc_port_auth_failed(struct lpfc_nodelist *, enum auth_state); | |
259 | void lpfc_worker_wake_up(struct lpfc_hba *); | |
260 | int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); | |
261 | int lpfc_do_work(void *); | |
262 | @@ -272,6 +273,7 @@ void lpfc_free_sysfs_attr(struct lpfc_vport *); | |
263 | extern struct device_attribute *lpfc_hba_attrs[]; | |
264 | extern struct device_attribute *lpfc_vport_attrs[]; | |
265 | extern struct scsi_host_template lpfc_template; | |
266 | +extern struct scsi_host_template lpfc_vport_template; | |
267 | extern struct fc_function_template lpfc_transport_functions; | |
268 | extern struct fc_function_template lpfc_vport_transport_functions; | |
269 | extern int lpfc_sli_mode; | |
270 | diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c | |
271 | index 26dae8b..7fecdbb 100644 | |
272 | --- a/drivers/scsi/lpfc/lpfc_ct.c | |
273 | +++ b/drivers/scsi/lpfc/lpfc_ct.c | |
274 | @@ -1008,8 +1008,10 @@ lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol, | |
275 | if (n < size) | |
276 | n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi); | |
277 | ||
278 | - if (n < size && vport->vname) | |
279 | - n += snprintf(symbol + n, size - n, " VName-%s", vport->vname); | |
280 | + if (n < size && | |
281 | + strlen(vport->fc_vport->symbolic_name)) | |
282 | + n += snprintf(symbol + n, size - n, " VName-%s", | |
283 | + vport->fc_vport->symbolic_name); | |
284 | return n; | |
285 | } | |
286 | ||
287 | diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c | |
288 | index a95815e..3f58a4b 100644 | |
289 | --- a/drivers/scsi/lpfc/lpfc_els.c | |
290 | +++ b/drivers/scsi/lpfc/lpfc_els.c | |
291 | @@ -5347,7 +5347,7 @@ lpfc_els_rcv_auth_rjt(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |
292 | "1036 Authentication transaction reject - " | |
293 | "re-auth request reason 0x%x exp 0x%x\n", | |
294 | rjt->reason, rjt->explanation); | |
295 | - lpfc_port_auth_failed(ndlp); | |
296 | + lpfc_port_auth_failed(ndlp, LPFC_AUTH_FAIL_AUTH_RJT); | |
297 | if (vport->auth.auth_msg_state == LPFC_DHCHAP_SUCCESS) { | |
298 | /* start authentication */ | |
299 | lpfc_start_authentication(vport, ndlp); | |
300 | @@ -5366,6 +5366,7 @@ lpfc_els_rcv_auth_rjt(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |
301 | "1057 Authentication transaction " | |
302 | "reject. reason 0x%x exp 0x%x\n", | |
303 | rjt->reason, rjt->explanation); | |
304 | + lpfc_port_auth_failed(ndlp, LPFC_AUTH_FAIL_AUTH_RJT); | |
305 | vport->auth.auth_msg_state = LPFC_AUTH_REJECT; | |
306 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | |
307 | (phba->link_state != LPFC_CLEAR_LA)) { | |
308 | @@ -7040,6 +7041,8 @@ lpfc_cmpl_els_auth(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |
309 | IOCB_t *irsp = &rspiocb->iocb; | |
310 | struct lpfc_vport *vport = cmdiocb->vport; | |
311 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | |
312 | + enum auth_state auth_state; | |
313 | + struct ls_rjt stat; | |
314 | ||
315 | /* Check to see if link went down during discovery */ | |
316 | if (lpfc_els_chk_latt(vport)) { | |
317 | @@ -7049,9 +7052,19 @@ lpfc_cmpl_els_auth(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |
318 | } | |
319 | ||
320 | if (irsp->ulpStatus) { | |
321 | + auth_state = LPFC_AUTH_FAIL; | |
322 | if (irsp->ulpStatus == IOSTAT_LS_RJT) { | |
323 | + stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]); | |
324 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | |
325 | "1043 Authentication LS_RJT\n"); | |
326 | + if (stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY) | |
327 | + auth_state = LPFC_AUTH_FAIL_LS_RJT_BUSY; | |
328 | + else | |
329 | + auth_state = LPFC_AUTH_FAIL_LS_RJT_GEN; | |
330 | + } else if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && | |
331 | + (irsp->un.ulpWord[4] & 0xff) == | |
332 | + IOERR_SEQUENCE_TIMEOUT) { | |
333 | + auth_state = LPFC_AUTH_FAIL_ELS_TMO; | |
334 | } | |
335 | /* Check for retry */ | |
336 | if (!lpfc_els_retry(phba, cmdiocb, rspiocb)) { | |
337 | @@ -7063,7 +7076,7 @@ lpfc_cmpl_els_auth(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |
338 | } | |
339 | if (vport->auth.auth_mode == FC_AUTHMODE_ACTIVE) { | |
340 | lpfc_can_disctmo(vport); | |
341 | - lpfc_port_auth_failed(ndlp); | |
342 | + lpfc_port_auth_failed(ndlp, auth_state); | |
343 | } | |
344 | } | |
345 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | |
346 | diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c | |
347 | index 502a9a5..358e9de 100644 | |
348 | --- a/drivers/scsi/lpfc/lpfc_hbadisc.c | |
349 | +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |
350 | @@ -754,17 +754,18 @@ lpfc_linkdown_port(struct lpfc_vport *vport) | |
351 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | |
352 | ||
353 | lpfc_port_link_failure(vport); | |
354 | - | |
355 | - vport->auth.auth_state = LPFC_AUTH_UNKNOWN; | |
356 | - vport->auth.auth_msg_state = LPFC_AUTH_NONE; | |
357 | + if (vport->auth.auth_state < LPFC_AUTH_FAIL) { | |
358 | + vport->auth.auth_state = LPFC_AUTH_UNKNOWN; | |
359 | + vport->auth.auth_msg_state = LPFC_AUTH_NONE; | |
360 | + } | |
361 | } | |
362 | ||
363 | void | |
364 | -lpfc_port_auth_failed(struct lpfc_nodelist *ndlp) | |
365 | +lpfc_port_auth_failed(struct lpfc_nodelist *ndlp, enum auth_state fail_state) | |
366 | { | |
367 | struct lpfc_vport *vport = ndlp->vport; | |
368 | ||
369 | - vport->auth.auth_state = LPFC_AUTH_FAIL; | |
370 | + vport->auth.auth_state = fail_state; | |
371 | vport->auth.auth_msg_state = LPFC_AUTH_NONE; | |
372 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | |
373 | if (ndlp->nlp_type & NLP_FABRIC) { | |
374 | @@ -886,6 +887,8 @@ lpfc_linkup_port(struct lpfc_vport *vport) | |
375 | if (vport->fc_flag & FC_LBIT) | |
376 | lpfc_linkup_cleanup_nodes(vport); | |
377 | ||
378 | + vport->auth.auth_state = LPFC_AUTH_UNKNOWN; | |
379 | + vport->auth.auth_msg_state = LPFC_AUTH_NONE; | |
380 | } | |
381 | ||
382 | static int | |
383 | diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h | |
384 | index 90d0c5a..c77d49e 100644 | |
385 | --- a/drivers/scsi/lpfc/lpfc_hw.h | |
386 | +++ b/drivers/scsi/lpfc/lpfc_hw.h | |
387 | @@ -2404,6 +2404,30 @@ typedef struct { | |
388 | #define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */ | |
389 | #define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */ | |
390 | ||
391 | +#define WAKE_UP_PARMS_REGION_ID 4 | |
392 | +#define WAKE_UP_PARMS_WORD_SIZE 15 | |
393 | + | |
394 | +/* Option rom version structure */ | |
395 | +struct prog_id { | |
396 | +#ifdef __BIG_ENDIAN_BITFIELD | |
397 | + uint8_t type; | |
398 | + uint8_t id; | |
399 | + uint32_t ver:4; /* Major Version */ | |
400 | + uint32_t rev:4; /* Revision */ | |
401 | + uint32_t lev:2; /* Level */ | |
402 | + uint32_t dist:2; /* Dist Type */ | |
403 | + uint32_t num:4; /* number after dist type */ | |
404 | +#else /* __LITTLE_ENDIAN_BITFIELD */ | |
405 | + uint32_t num:4; /* number after dist type */ | |
406 | + uint32_t dist:2; /* Dist Type */ | |
407 | + uint32_t lev:2; /* Level */ | |
408 | + uint32_t rev:4; /* Revision */ | |
409 | + uint32_t ver:4; /* Major Version */ | |
410 | + uint8_t id; | |
411 | + uint8_t type; | |
412 | +#endif | |
413 | +}; | |
414 | + | |
415 | /* Structure for MB Command UPDATE_CFG (0x1B) */ | |
416 | ||
417 | struct update_cfg_var { | |
418 | diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c | |
419 | index c0ea4fc..c151651 100644 | |
420 | --- a/drivers/scsi/lpfc/lpfc_init.c | |
421 | +++ b/drivers/scsi/lpfc/lpfc_init.c | |
422 | @@ -271,6 +271,48 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | |
423 | } | |
424 | ||
425 | /** | |
426 | + * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox | |
427 | + * command used for getting wake up parameters. | |
428 | + * @phba: pointer to lpfc hba data structure. | |
429 | + * @pmboxq: pointer to the driver internal queue element for mailbox command. | |
430 | + * | |
431 | + * This is the completion handler for dump mailbox command for getting | |
432 | + * wake up parameters. When this command complete, the response contain | |
433 | + * Option rom version of the HBA. This function translate the version number | |
434 | + * into a human readable string and store it in OptionROMVersion. | |
435 | + **/ | |
436 | +static void | |
437 | +lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |
438 | +{ | |
439 | + struct prog_id *prg; | |
440 | + uint32_t prog_id_word; | |
441 | + char dist = ' '; | |
442 | + /* character array used for decoding dist type. */ | |
443 | + char dist_char[] = "nabx"; | |
444 | + | |
445 | + if (pmboxq->mb.mbxStatus != MBX_SUCCESS) | |
446 | + return; | |
447 | + | |
448 | + prg = (struct prog_id *) &prog_id_word; | |
449 | + | |
450 | + /* word 7 contain option rom version */ | |
451 | + prog_id_word = pmboxq->mb.un.varWords[7]; | |
452 | + | |
453 | + /* Decode the Option rom version word to a readable string */ | |
454 | + if (prg->dist < 4) | |
455 | + dist = dist_char[prg->dist]; | |
456 | + | |
457 | + if ((prg->dist == 3) && (prg->num == 0)) | |
458 | + sprintf(phba->OptionROMVersion, "%d.%d%d", | |
459 | + prg->ver, prg->rev, prg->lev); | |
460 | + else | |
461 | + sprintf(phba->OptionROMVersion, "%d.%d%d%c%d", | |
462 | + prg->ver, prg->rev, prg->lev, | |
463 | + dist, prg->num); | |
464 | + return; | |
465 | +} | |
466 | + | |
467 | +/** | |
468 | * lpfc_config_port_post: Perform lpfc initialization after config port. | |
469 | * @phba: pointer to lpfc hba data structure. | |
470 | * | |
471 | @@ -528,6 +570,20 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |
472 | rc); | |
473 | mempool_free(pmb, phba->mbox_mem_pool); | |
474 | } | |
475 | + | |
476 | + /* Get Option rom version */ | |
477 | + pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | |
478 | + lpfc_dump_wakeup_param(phba, pmb); | |
479 | + pmb->mbox_cmpl = lpfc_dump_wakeup_param_cmpl; | |
480 | + pmb->vport = phba->pport; | |
481 | + rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | |
482 | + | |
483 | + if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { | |
484 | + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed " | |
485 | + "to get Option ROM version status x%x\n.", rc); | |
486 | + mempool_free(pmb, phba->mbox_mem_pool); | |
487 | + } | |
488 | + | |
489 | return 0; | |
490 | } | |
491 | ||
492 | @@ -2014,7 +2070,12 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) | |
493 | struct Scsi_Host *shost; | |
494 | int error = 0; | |
495 | ||
496 | - shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport)); | |
497 | + if (dev != &phba->pcidev->dev) | |
498 | + shost = scsi_host_alloc(&lpfc_vport_template, | |
499 | + sizeof(struct lpfc_vport)); | |
500 | + else | |
501 | + shost = scsi_host_alloc(&lpfc_template, | |
502 | + sizeof(struct lpfc_vport)); | |
503 | if (!shost) | |
504 | goto out; | |
505 | ||
506 | @@ -2097,8 +2158,6 @@ destroy_port(struct lpfc_vport *vport) | |
507 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | |
508 | struct lpfc_hba *phba = vport->phba; | |
509 | ||
510 | - kfree(vport->vname); | |
511 | - | |
512 | lpfc_debugfs_terminate(vport); | |
513 | fc_remove_host(shost); | |
514 | scsi_remove_host(shost); | |
515 | @@ -2862,7 +2921,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |
516 | vport->load_flag |= FC_UNLOADING; | |
517 | spin_unlock_irq(&phba->hbalock); | |
518 | ||
519 | - kfree(vport->vname); | |
520 | lpfc_free_sysfs_attr(vport); | |
521 | ||
522 | kthread_stop(phba->worker_thread); | |
523 | diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c | |
524 | index 184fe62..f0ab456 100644 | |
525 | --- a/drivers/scsi/lpfc/lpfc_mbox.c | |
526 | +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |
527 | @@ -77,6 +77,38 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) | |
528 | } | |
529 | ||
530 | /** | |
531 | + * lpfc_dump_mem: Prepare a mailbox command for retrieving wakeup params. | |
532 | + * @phba: pointer to lpfc hba data structure. | |
533 | + * @pmb: pointer to the driver internal queue element for mailbox command. | |
534 | + * This function create a dump memory mailbox command to dump wake up | |
535 | + * parameters. | |
536 | + */ | |
537 | +void | |
538 | +lpfc_dump_wakeup_param(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |
539 | +{ | |
540 | + MAILBOX_t *mb; | |
541 | + void *ctx; | |
542 | + | |
543 | + mb = &pmb->mb; | |
544 | + /* Save context so that we can restore after memset */ | |
545 | + ctx = pmb->context2; | |
546 | + | |
547 | + /* Setup to dump VPD region */ | |
548 | + memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); | |
549 | + mb->mbxCommand = MBX_DUMP_MEMORY; | |
550 | + mb->mbxOwner = OWN_HOST; | |
551 | + mb->un.varDmp.cv = 1; | |
552 | + mb->un.varDmp.type = DMP_NV_PARAMS; | |
553 | + mb->un.varDmp.entry_index = 0; | |
554 | + mb->un.varDmp.region_id = WAKE_UP_PARMS_REGION_ID; | |
555 | + mb->un.varDmp.word_cnt = WAKE_UP_PARMS_WORD_SIZE; | |
556 | + mb->un.varDmp.co = 0; | |
557 | + mb->un.varDmp.resp_offset = 0; | |
558 | + pmb->context2 = ctx; | |
559 | + return; | |
560 | +} | |
561 | + | |
562 | +/** | |
563 | * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param. | |
564 | * @phba: pointer to lpfc hba data structure. | |
565 | * @pmb: pointer to the driver internal queue element for mailbox command. | |
566 | diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h | |
567 | index 991ad53..27d1a88 100644 | |
568 | --- a/drivers/scsi/lpfc/lpfc_nl.h | |
569 | +++ b/drivers/scsi/lpfc/lpfc_nl.h | |
570 | @@ -22,18 +22,20 @@ | |
571 | #define FC_REG_LINK_EVENT 0x0001 /* link up / down events */ | |
572 | #define FC_REG_RSCN_EVENT 0x0002 /* RSCN events */ | |
573 | #define FC_REG_CT_EVENT 0x0004 /* CT request events */ | |
574 | -#define FC_REG_DUMP_EVENT 0x0008 /* Dump events */ | |
575 | -#define FC_REG_TEMPERATURE_EVENT 0x0010 /* temperature events */ | |
576 | -#define FC_REG_ELS_EVENT 0x0020 /* lpfc els events */ | |
577 | -#define FC_REG_FABRIC_EVENT 0x0040 /* lpfc fabric events */ | |
578 | -#define FC_REG_SCSI_EVENT 0x0080 /* lpfc scsi events */ | |
579 | -#define FC_REG_BOARD_EVENT 0x0100 /* lpfc board events */ | |
580 | -#define FC_REG_ADAPTER_EVENT 0x0200 /* lpfc adapter events */ | |
581 | +#define FC_REG_DUMP_EVENT 0x0010 /* Dump events */ | |
582 | +#define FC_REG_TEMPERATURE_EVENT 0x0020 /* temperature events */ | |
583 | +#define FC_REG_VPORTRSCN_EVENT 0x0040 /* Vport RSCN events */ | |
584 | +#define FC_REG_ELS_EVENT 0x0080 /* lpfc els events */ | |
585 | +#define FC_REG_FABRIC_EVENT 0x0100 /* lpfc fabric events */ | |
586 | +#define FC_REG_SCSI_EVENT 0x0200 /* lpfc scsi events */ | |
587 | +#define FC_REG_BOARD_EVENT 0x0400 /* lpfc board events */ | |
588 | +#define FC_REG_ADAPTER_EVENT 0x0800 /* lpfc adapter events */ | |
589 | #define FC_REG_EVENT_MASK (FC_REG_LINK_EVENT | \ | |
590 | FC_REG_RSCN_EVENT | \ | |
591 | FC_REG_CT_EVENT | \ | |
592 | FC_REG_DUMP_EVENT | \ | |
593 | FC_REG_TEMPERATURE_EVENT | \ | |
594 | + FC_REG_VPORTRSCN_EVENT | \ | |
595 | FC_REG_ELS_EVENT | \ | |
596 | FC_REG_FABRIC_EVENT | \ | |
597 | FC_REG_SCSI_EVENT | \ | |
598 | diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c | |
599 | index a7ea952..fed32ff 100644 | |
600 | --- a/drivers/scsi/lpfc/lpfc_scsi.c | |
601 | +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |
602 | @@ -1842,7 +1842,7 @@ struct scsi_host_template lpfc_template = { | |
603 | .info = lpfc_info, | |
604 | .queuecommand = lpfc_queuecommand, | |
605 | .eh_abort_handler = lpfc_abort_handler, | |
606 | - .eh_device_reset_handler= lpfc_device_reset_handler, | |
607 | + .eh_device_reset_handler = lpfc_device_reset_handler, | |
608 | .eh_bus_reset_handler = lpfc_bus_reset_handler, | |
609 | .slave_alloc = lpfc_slave_alloc, | |
610 | .slave_configure = lpfc_slave_configure, | |
611 | @@ -1856,3 +1856,22 @@ struct scsi_host_template lpfc_template = { | |
612 | .max_sectors = 0xFFFF, | |
613 | }; | |
614 | ||
615 | +struct scsi_host_template lpfc_vport_template = { | |
616 | + .module = THIS_MODULE, | |
617 | + .name = LPFC_DRIVER_NAME, | |
618 | + .info = lpfc_info, | |
619 | + .queuecommand = lpfc_queuecommand, | |
620 | + .eh_abort_handler = lpfc_abort_handler, | |
621 | + .eh_device_reset_handler = lpfc_device_reset_handler, | |
622 | + .eh_bus_reset_handler = lpfc_bus_reset_handler, | |
623 | + .slave_alloc = lpfc_slave_alloc, | |
624 | + .slave_configure = lpfc_slave_configure, | |
625 | + .slave_destroy = lpfc_slave_destroy, | |
626 | + .scan_finished = lpfc_scan_finished, | |
627 | + .this_id = -1, | |
628 | + .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT, | |
629 | + .cmd_per_lun = LPFC_CMD_PER_LUN, | |
630 | + .use_clustering = ENABLE_CLUSTERING, | |
631 | + .shost_attrs = lpfc_vport_attrs, | |
632 | + .max_sectors = 0xFFFF, | |
633 | +}; | |
634 | diff --git a/drivers/scsi/lpfc/lpfc_security.c b/drivers/scsi/lpfc/lpfc_security.c | |
635 | index d136f67..c0fbe56 100644 | |
636 | --- a/drivers/scsi/lpfc/lpfc_security.c | |
637 | +++ b/drivers/scsi/lpfc/lpfc_security.c | |
638 | @@ -263,7 +263,7 @@ lpfc_reauthentication_handler(struct lpfc_nodelist *ndlp) | |
639 | lpfc_printf_vlog(vport, KERN_ERR, LOG_SECURITY, | |
640 | "1029 Reauthentication Failure\n"); | |
641 | if (vport->auth.auth_state == LPFC_AUTH_SUCCESS) | |
642 | - lpfc_port_auth_failed(ndlp); | |
643 | + lpfc_port_auth_failed(ndlp, LPFC_AUTH_FAIL); | |
644 | } | |
645 | } | |
646 | ||
647 | diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h | |
648 | index a42cef2..57b559a 100644 | |
649 | --- a/drivers/scsi/lpfc/lpfc_version.h | |
650 | +++ b/drivers/scsi/lpfc/lpfc_version.h | |
651 | @@ -18,7 +18,7 @@ | |
652 | * included with this package. * | |
653 | *******************************************************************/ | |
654 | ||
655 | -#define LPFC_DRIVER_VERSION "8.2.8.3" | |
656 | +#define LPFC_DRIVER_VERSION "8.2.8.4" | |
657 | ||
658 | #define LPFC_DRIVER_NAME "lpfc" | |
659 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" | |
660 | diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c | |
661 | index c3a3f6e..ae8256d 100644 | |
662 | --- a/drivers/scsi/lpfc/lpfc_vport.c | |
663 | +++ b/drivers/scsi/lpfc/lpfc_vport.c | |
664 | @@ -289,10 +289,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |
665 | int vpi; | |
666 | int rc = VPORT_ERROR; | |
667 | int status; | |
668 | - int size; | |
669 | ||
670 | - if ((phba->sli_rev < 3) || | |
671 | - !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { | |
672 | + if ((phba->sli_rev < 3) || !(phba->cfg_enable_npiv)) { | |
673 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, | |
674 | "1808 Create VPORT failed: " | |
675 | "NPIV is not enabled: SLImode:%d\n", | |
676 | @@ -352,20 +350,6 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |
677 | ||
678 | memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8); | |
679 | memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8); | |
680 | - size = strnlen(fc_vport->symbolic_name, LPFC_VNAME_LEN); | |
681 | - if (size) { | |
682 | - vport->vname = kzalloc(size+1, GFP_KERNEL); | |
683 | - if (!vport->vname) { | |
684 | - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | |
685 | - "1814 Create VPORT failed. " | |
686 | - "vname allocation failed.\n"); | |
687 | - rc = VPORT_ERROR; | |
688 | - lpfc_free_vpi(phba, vpi); | |
689 | - destroy_port(vport); | |
690 | - goto error_out; | |
691 | - } | |
692 | - memcpy(vport->vname, fc_vport->symbolic_name, size+1); | |
693 | - } | |
694 | if (fc_vport->node_name != 0) | |
695 | u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn); | |
696 | if (fc_vport->port_name != 0) | |
697 | @@ -410,6 +394,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |
698 | } | |
699 | } | |
700 | ||
701 | + /* Create binary sysfs attribute for vport */ | |
702 | + lpfc_alloc_sysfs_attr(vport); | |
703 | + | |
704 | *(struct lpfc_vport **)fc_vport->dd_data = vport; | |
705 | vport->fc_vport = fc_vport; | |
706 | ||
707 | @@ -421,6 +408,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |
708 | } | |
709 | ||
710 | if (disable) { | |
711 | + lpfc_vport_set_state(vport, FC_VPORT_DISABLED); | |
712 | rc = VPORT_OK; | |
713 | goto out; | |
714 | } | |
715 | @@ -603,7 +591,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |
716 | spin_lock_irq(&phba->hbalock); | |
717 | vport->load_flag |= FC_UNLOADING; | |
718 | spin_unlock_irq(&phba->hbalock); | |
719 | - kfree(vport->vname); | |
720 | + | |
721 | + lpfc_free_sysfs_attr(vport); | |
722 | + | |
723 | lpfc_debugfs_terminate(vport); | |
724 | ||
725 | /* Remove FC host and then SCSI host with the vport */ |