1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 *
24 * Fibre Channel SCSI ULP Mapping driver
25 */
26
27 #include <sys/scsi/scsi.h>
28 #include <sys/types.h>
29 #include <sys/varargs.h>
30 #include <sys/devctl.h>
31 #include <sys/thread.h>
32 #include <sys/thread.h>
33 #include <sys/open.h>
34 #include <sys/file.h>
35 #include <sys/sunndi.h>
36 #include <sys/console.h>
37 #include <sys/proc.h>
38 #include <sys/time.h>
39 #include <sys/utsname.h>
40 #include <sys/scsi/impl/scsi_reset_notify.h>
41 #include <sys/ndi_impldefs.h>
42 #include <sys/byteorder.h>
43 #include <sys/fs/dv_node.h>
44 #include <sys/ctype.h>
45 #include <sys/sunmdi.h>
46
47 #include <sys/fibre-channel/fc.h>
48 #include <sys/fibre-channel/impl/fc_ulpif.h>
49 #include <sys/fibre-channel/ulp/fcpvar.h>
50
51 /*
52 * Discovery Process
53 * =================
54 *
55 * The discovery process is a major function of FCP. In order to help
56 * understand that function a flow diagram is given here. This diagram
57 * doesn't claim to cover all the cases and the events that can occur during
58 * the discovery process nor the subtleties of the code. The code paths shown
59 * are simplified. Its purpose is to help the reader (and potentially bug
60 * fixer) have an overall view of the logic of the code. For that reason the
61 * diagram covers the simple case of the line coming up cleanly or of a new
62 * port attaching to FCP the link being up. The reader must keep in mind
63 * that:
64 *
65 * - There are special cases where bringing devices online and offline
66 * is driven by Ioctl.
67 *
68 * - The behavior of the discovery process can be modified through the
69 * .conf file.
70 *
71 * - The line can go down and come back up at any time during the
72 * discovery process which explains some of the complexity of the code.
73 *
74 * ............................................................................
75 *
76 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
77 *
78 *
79 * +-------------------------+
80 * fp/fctl module --->| fcp_port_attach |
81 * +-------------------------+
82 * | |
83 * | |
84 * | v
85 * | +-------------------------+
86 * | | fcp_handle_port_attach |
87 * | +-------------------------+
88 * | |
89 * | |
90 * +--------------------+ |
91 * | |
92 * v v
93 * +-------------------------+
94 * | fcp_statec_callback |
95 * +-------------------------+
96 * |
97 * |
98 * v
99 * +-------------------------+
100 * | fcp_handle_devices |
101 * +-------------------------+
102 * |
103 * |
104 * v
105 * +-------------------------+
106 * | fcp_handle_mapflags |
107 * +-------------------------+
108 * |
109 * |
110 * v
111 * +-------------------------+
112 * | fcp_send_els |
113 * | |
114 * | PLOGI or PRLI To all the|
115 * | reachable devices. |
116 * +-------------------------+
117 *
118 *
119 * ............................................................................
120 *
121 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
122 * STEP 1 are called (it is actually the same function).
123 *
124 *
125 * +-------------------------+
126 * | fcp_icmd_callback |
127 * fp/fctl module --->| |
128 * | callback for PLOGI and |
129 * | PRLI. |
130 * +-------------------------+
131 * |
132 * |
133 * Received PLOGI Accept /-\ Received PRLI Accept
134 * _ _ _ _ _ _ / \_ _ _ _ _ _
135 * | \ / |
136 * | \-/ |
137 * | |
138 * v v
139 * +-------------------------+ +-------------------------+
140 * | fcp_send_els | | fcp_send_scsi |
141 * | | | |
142 * | PRLI | | REPORT_LUN |
143 * +-------------------------+ +-------------------------+
144 *
145 * ............................................................................
146 *
147 * STEP 3: The callback functions of the SCSI commands issued by FCP are called
148 * (It is actually the same function).
149 *
150 *
151 * +-------------------------+
152 * fp/fctl module ------->| fcp_scsi_callback |
153 * +-------------------------+
154 * |
155 * |
156 * |
157 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply
158 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _
159 * | \ / |
160 * | \-/ |
161 * | | |
162 * | Receive INQUIRY reply| |
163 * | | |
164 * v v v
165 * +------------------------+ +----------------------+ +----------------------+
166 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 |
167 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
168 * +------------------------+ +----------------------+ +----------------------+
169 * | | |
170 * | | |
171 * | | |
172 * v v |
173 * +-----------------+ +-----------------+ |
174 * | fcp_send_scsi | | fcp_send_scsi | |
175 * | | | | |
176 * | INQUIRY | | INQUIRY PAGE83 | |
177 * | (To each LUN) | +-----------------+ |
178 * +-----------------+ |
179 * |
180 * v
181 * +------------------------+
182 * | fcp_call_finish_init |
183 * +------------------------+
184 * |
185 * v
186 * +-----------------------------+
187 * | fcp_call_finish_init_held |
188 * +-----------------------------+
189 * |
190 * |
191 * All LUNs scanned /-\
192 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \
193 * | \ /
194 * | \-/
195 * v |
196 * +------------------+ |
197 * | fcp_finish_tgt | |
198 * +------------------+ |
199 * | Target Not Offline and |
200 * Target Not Offline and | not marked and tgt_node_state |
201 * marked /-\ not FCP_TGT_NODE_ON_DEMAND |
202 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ |
203 * | \ / | |
204 * | \-/ | |
205 * v v |
206 * +----------------------------+ +-------------------+ |
207 * | fcp_offline_target | | fcp_create_luns | |
208 * | | +-------------------+ |
209 * | A structure fcp_tgt_elem | | |
210 * | is created and queued in | v |
211 * | the FCP port list | +-------------------+ |
212 * | port_offline_tgts. It | | fcp_pass_to_hp | |
213 * | will be unqueued by the | | | |
214 * | watchdog timer. | | Called for each | |
215 * +----------------------------+ | LUN. Dispatches | |
216 * | | fcp_hp_task | |
217 * | +-------------------+ |
218 * | | |
219 * | | |
220 * | | |
221 * | +---------------->|
222 * | |
223 * +---------------------------------------------->|
224 * |
225 * |
226 * All the targets (devices) have been scanned /-\
227 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \
228 * | \ /
229 * | \-/
230 * +-------------------------------------+ |
231 * | fcp_finish_init | |
232 * | | |
233 * | Signal broadcasts the condition | |
234 * | variable port_config_cv of the FCP | |
235 * | port. One potential code sequence | |
236 * | waiting on the condition variable | |
237 * | the code sequence handling | |
238 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| |
239 * | The other is in the function | |
240 * | fcp_reconfig_wait which is called | |
241 * | in the transmit path preventing IOs | |
242 * | from going through till the disco- | |
243 * | very process is over. | |
244 * +-------------------------------------+ |
245 * | |
246 * | |
247 * +--------------------------------->|
248 * |
249 * v
250 * Return
251 *
252 * ............................................................................
253 *
254 * STEP 4: The hot plug task is called (for each fcp_hp_elem).
255 *
256 *
257 * +-------------------------+
258 * | fcp_hp_task |
259 * +-------------------------+
260 * |
261 * |
262 * v
263 * +-------------------------+
264 * | fcp_trigger_lun |
265 * +-------------------------+
266 * |
267 * |
268 * v
269 * Bring offline /-\ Bring online
270 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _
271 * | \ / |
272 * | \-/ |
273 * v v
274 * +---------------------+ +-----------------------+
275 * | fcp_offline_child | | fcp_get_cip |
276 * +---------------------+ | |
277 * | Creates a dev_info_t |
278 * | or a mdi_pathinfo_t |
279 * | depending on whether |
280 * | mpxio is on or off. |
281 * +-----------------------+
282 * |
283 * |
284 * v
285 * +-----------------------+
286 * | fcp_online_child |
287 * | |
288 * | Set device online |
289 * | using NDI or MDI. |
290 * +-----------------------+
291 *
292 * ............................................................................
293 *
294 * STEP 5: The watchdog timer expires. The watch dog timer does much more that
295 * what is described here. We only show the target offline path.
296 *
297 *
298 * +--------------------------+
299 * | fcp_watch |
300 * +--------------------------+
301 * |
302 * |
303 * v
304 * +--------------------------+
305 * | fcp_scan_offline_tgts |
306 * +--------------------------+
307 * |
308 * |
309 * v
310 * +--------------------------+
311 * | fcp_offline_target_now |
312 * +--------------------------+
313 * |
314 * |
315 * v
316 * +--------------------------+
317 * | fcp_offline_tgt_luns |
318 * +--------------------------+
319 * |
320 * |
321 * v
322 * +--------------------------+
323 * | fcp_offline_lun |
324 * +--------------------------+
325 * |
326 * |
327 * v
328 * +----------------------------------+
329 * | fcp_offline_lun_now |
330 * | |
331 * | A request (or two if mpxio) is |
332 * | sent to the hot plug task using |
333 * | a fcp_hp_elem structure. |
334 * +----------------------------------+
335 */
336
337 /*
338 * Functions registered with DDI framework
339 */
340 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
341 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
342 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
343 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
344 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
345 cred_t *credp, int *rval);
346
347 /*
348 * Functions registered with FC Transport framework
349 */
350 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
351 fc_attach_cmd_t cmd, uint32_t s_id);
352 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
353 fc_detach_cmd_t cmd);
354 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
355 int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
356 uint32_t claimed);
357 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
358 fc_unsol_buf_t *buf, uint32_t claimed);
359 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
360 fc_unsol_buf_t *buf, uint32_t claimed);
361 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
362 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
363 uint32_t dev_cnt, uint32_t port_sid);
364
365 /*
366 * Functions registered with SCSA framework
367 */
368 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
369 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
370 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
371 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
372 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
373 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
374 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
375 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
376 static int fcp_scsi_reset(struct scsi_address *ap, int level);
377 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
378 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
379 int whom);
380 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
381 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
382 void (*callback)(caddr_t), caddr_t arg);
383 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
384 char *name, ddi_eventcookie_t *event_cookiep);
385 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
386 ddi_eventcookie_t eventid, void (*callback)(), void *arg,
387 ddi_callback_id_t *cb_id);
388 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
389 ddi_callback_id_t cb_id);
390 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
391 ddi_eventcookie_t eventid, void *impldata);
392 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
393 ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
394 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
395 ddi_bus_config_op_t op, void *arg);
396
397 /*
398 * Internal functions
399 */
400 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
401 int mode, int *rval);
402
403 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
404 int mode, int *rval);
405 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
406 struct fcp_scsi_cmd *fscsi, int mode);
407 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
408 caddr_t base_addr, int mode);
409 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
410
411 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
412 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state,
413 int *fc_pkt_reason, int *fc_pkt_action);
414 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
415 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
416 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status,
417 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
418 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
419 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
420 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
421 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
422
423 static void fcp_handle_devices(struct fcp_port *pptr,
424 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
425 fcp_map_tag_t *map_tag, int cause);
426 static int fcp_handle_mapflags(struct fcp_port *pptr,
427 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
428 int tgt_cnt, int cause);
429 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
431 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
433 int cause);
434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
435 uint32_t state);
436 static struct fcp_port *fcp_get_port(opaque_t port_handle);
437 static void fcp_unsol_callback(fc_packet_t *fpkt);
438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
439 uchar_t r_ctl, uchar_t type);
440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
442 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
443 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
446 int nodma, int flags);
447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
449 uchar_t *wwn);
450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
451 uint32_t d_id);
452 static void fcp_icmd_callback(fc_packet_t *fpkt);
453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
454 int len, int lcount, int tcount, int cause, uint32_t rscn_count);
455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
456 static void fcp_scsi_callback(fc_packet_t *fpkt);
457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
461 uint16_t lun_num);
462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
463 int link_cnt, int tgt_cnt, int cause);
464 static void fcp_finish_init(struct fcp_port *pptr);
465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
466 int tgt_cnt, int cause);
467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
468 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
470 int link_cnt, int tgt_cnt, int nowait, int flags);
471 static void fcp_offline_target_now(struct fcp_port *pptr,
472 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
474 int tgt_cnt, int flags);
475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
476 int nowait, int flags);
477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
478 int tgt_cnt);
479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
480 int tgt_cnt, int flags);
481 static void fcp_scan_offline_luns(struct fcp_port *pptr);
482 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
483 static void fcp_update_offline_flags(struct fcp_lun *plun);
484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
485 static void fcp_abort_commands(struct fcp_pkt *head, struct
486 fcp_port *pptr);
487 static void fcp_cmd_callback(fc_packet_t *fpkt);
488 static void fcp_complete_pkt(fc_packet_t *fpkt);
489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
490 struct fcp_port *pptr);
491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
492 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
494 static void fcp_dealloc_lun(struct fcp_lun *plun);
495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
496 fc_portmap_t *map_entry, int link_cnt);
497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
500 int internal);
501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
503 uint32_t s_id, int instance);
504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
505 int instance);
506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
508 int);
509 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *);
510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
512 int flags);
513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
514 static int fcp_reset_target(struct scsi_address *ap, int level);
515 static int fcp_commoncap(struct scsi_address *ap, char *cap,
516 int val, int tgtonly, int doset);
517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
520 int sleep);
521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
522 uint32_t s_id, fc_attach_cmd_t cmd, int instance);
523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
526 int lcount, int tcount);
527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
530 int tgt_cnt);
531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
532 dev_info_t *pdip, caddr_t name);
533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
534 int lcount, int tcount, int flags, int *circ);
535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
536 int lcount, int tcount, int flags, int *circ);
537 static void fcp_remove_child(struct fcp_lun *plun);
538 static void fcp_watch(void *arg);
539 static void fcp_check_reset_delay(struct fcp_port *pptr);
540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
541 struct fcp_lun *rlun, int tgt_cnt);
542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
544 uchar_t *wwn, uint16_t lun);
545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
546 struct fcp_lun *plun);
547 static void fcp_post_callback(struct fcp_pkt *cmd);
548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
549 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
551 child_info_t *cip);
552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
553 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
554 int tgt_cnt, int flags);
555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
556 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
557 int tgt_cnt, int flags, int wait);
558 static void fcp_retransport_cmd(struct fcp_port *pptr,
559 struct fcp_pkt *cmd);
560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
561 uint_t statistics);
562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
563 static void fcp_update_targets(struct fcp_port *pptr,
564 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
565 static int fcp_call_finish_init(struct fcp_port *pptr,
566 struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
567 static int fcp_call_finish_init_held(struct fcp_port *pptr,
568 struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
569 static void fcp_reconfigure_luns(void * tgt_handle);
570 static void fcp_free_targets(struct fcp_port *pptr);
571 static void fcp_free_target(struct fcp_tgt *ptgt);
572 static int fcp_is_retryable(struct fcp_ipkt *icmd);
573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
576 static void fcp_print_error(fc_packet_t *fpkt);
577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
578 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
581 uint32_t *dev_cnt);
582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
585 struct fcp_ioctl *, struct fcp_port **);
586 static char *fcp_get_lun_path(struct fcp_lun *plun);
587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
588 int *rval);
589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
591 static char *fcp_get_lun_path(struct fcp_lun *plun);
592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
593 int *rval);
594 static void fcp_reconfig_wait(struct fcp_port *pptr);
595
596 /*
597 * New functions added for mpxio support
598 */
599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
600 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
602 int tcount);
603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
604 dev_info_t *pdip);
605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
610 int what);
611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
612 fc_packet_t *fpkt);
613 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
614
615 /*
616 * New functions added for lun masking support
617 */
618 static void fcp_read_blacklist(dev_info_t *dip,
619 struct fcp_black_list_entry **pplun_blacklist);
620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
621 struct fcp_black_list_entry **pplun_blacklist);
622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
623 struct fcp_black_list_entry **pplun_blacklist);
624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
626
627 /*
628 * New functions to support software FCA (like fcoei)
629 */
630 static struct scsi_pkt *fcp_pseudo_init_pkt(
631 struct scsi_address *ap, struct scsi_pkt *pkt,
632 struct buf *bp, int cmdlen, int statuslen,
633 int tgtlen, int flags, int (*callback)(), caddr_t arg);
634 static void fcp_pseudo_destroy_pkt(
635 struct scsi_address *ap, struct scsi_pkt *pkt);
636 static void fcp_pseudo_sync_pkt(
637 struct scsi_address *ap, struct scsi_pkt *pkt);
638 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
639 static void fcp_pseudo_dmafree(
640 struct scsi_address *ap, struct scsi_pkt *pkt);
641
642 extern struct mod_ops mod_driverops;
643 /*
644 * This variable is defined in modctl.c and set to '1' after the root driver
645 * and fs are loaded. It serves as an indication that the root filesystem can
646 * be used.
647 */
648 extern int modrootloaded;
649 /*
650 * This table contains strings associated with the SCSI sense key codes. It
651 * is used by FCP to print a clear explanation of the code returned in the
652 * sense information by a device.
653 */
654 extern char *sense_keys[];
655 /*
656 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is
657 * under this device that the paths to a physical device are created when
658 * MPxIO is used.
659 */
660 extern dev_info_t *scsi_vhci_dip;
661
662 /*
663 * Report lun processing
664 */
665 #define FCP_LUN_ADDRESSING 0x80
666 #define FCP_PD_ADDRESSING 0x00
667 #define FCP_VOLUME_ADDRESSING 0x40
668
669 #define FCP_SVE_THROTTLE 0x28 /* Vicom */
670 #define MAX_INT_DMA 0x7fffffff
671 /*
672 * Property definitions
673 */
674 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop
675 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop
676 #define TARGET_PROP (char *)fcp_target_prop
677 #define LUN_PROP (char *)fcp_lun_prop
678 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop
679 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop
680 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn
681 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only
682 #define INIT_PORT_PROP (char *)fcp_init_port_prop
683 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop
684 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop
685 /*
686 * Short hand macros.
687 */
688 #define LUN_PORT (plun->lun_tgt->tgt_port)
689 #define LUN_TGT (plun->lun_tgt)
690
691 /*
692 * Driver private macros
693 */
694 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \
695 ((x) >= 'a' && (x) <= 'f') ? \
696 ((x) - 'a' + 10) : ((x) - 'A' + 10))
697
698 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b))
699
700 #define FCP_N_NDI_EVENTS \
701 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
702
703 #define FCP_LINK_STATE_CHANGED(p, c) \
704 ((p)->port_link_cnt != (c)->ipkt_link_cnt)
705
706 #define FCP_TGT_STATE_CHANGED(t, c) \
707 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
708
709 #define FCP_STATE_CHANGED(p, t, c) \
710 (FCP_TGT_STATE_CHANGED(t, c))
711
712 #define FCP_MUST_RETRY(fpkt) \
713 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \
714 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \
715 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \
716 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \
717 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \
718 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \
719 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \
720 (fpkt)->pkt_reason == FC_REASON_OFFLINE)
721
722 #define FCP_SENSE_REPORTLUN_CHANGED(es) \
723 ((es)->es_key == KEY_UNIT_ATTENTION && \
724 (es)->es_add_code == 0x3f && \
725 (es)->es_qual_code == 0x0e)
726
727 #define FCP_SENSE_NO_LUN(es) \
728 ((es)->es_key == KEY_ILLEGAL_REQUEST && \
729 (es)->es_add_code == 0x25 && \
730 (es)->es_qual_code == 0x0)
731
732 #define FCP_VERSION "20091208-1.192"
733 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION
734
735 #define FCP_NUM_ELEMENTS(array) \
736 (sizeof (array) / sizeof ((array)[0]))
737
738 /*
739 * Debugging, Error reporting, and tracing
740 */
741 #define FCP_LOG_SIZE 1024 * 1024
742
743 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */
744 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */
745 #define FCP_LEVEL_3 0x00004 /* state change, discovery */
746 #define FCP_LEVEL_4 0x00008 /* ULP messages */
747 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */
748 #define FCP_LEVEL_6 0x00020 /* Transport failures */
749 #define FCP_LEVEL_7 0x00040
750 #define FCP_LEVEL_8 0x00080 /* I/O tracing */
751 #define FCP_LEVEL_9 0x00100 /* I/O tracing */
752
753
754
755 /*
756 * Log contents to system messages file
757 */
758 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
759 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
760 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
761 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
762 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
763 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
764 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
765 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
766 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
767
768
769 /*
770 * Log contents to trace buffer
771 */
772 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
773 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
774 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
775 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
776 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
777 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
778 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
779 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
780 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
781
782
783 /*
784 * Log contents to both system messages file and trace buffer
785 */
786 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \
787 FC_TRACE_LOG_MSG)
788 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \
789 FC_TRACE_LOG_MSG)
790 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \
791 FC_TRACE_LOG_MSG)
792 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \
793 FC_TRACE_LOG_MSG)
794 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \
795 FC_TRACE_LOG_MSG)
796 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \
797 FC_TRACE_LOG_MSG)
798 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \
799 FC_TRACE_LOG_MSG)
800 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \
801 FC_TRACE_LOG_MSG)
802 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \
803 FC_TRACE_LOG_MSG)
804 #ifdef DEBUG
805 #define FCP_DTRACE fc_trace_debug
806 #else
807 #define FCP_DTRACE
808 #endif
809
810 #define FCP_TRACE fc_trace_debug
811
812 static struct cb_ops fcp_cb_ops = {
813 fcp_open, /* open */
814 fcp_close, /* close */
815 nodev, /* strategy */
816 nodev, /* print */
817 nodev, /* dump */
818 nodev, /* read */
819 nodev, /* write */
820 fcp_ioctl, /* ioctl */
821 nodev, /* devmap */
822 nodev, /* mmap */
823 nodev, /* segmap */
824 nochpoll, /* chpoll */
825 ddi_prop_op, /* cb_prop_op */
826 0, /* streamtab */
827 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */
828 CB_REV, /* rev */
829 nodev, /* aread */
830 nodev /* awrite */
831 };
832
833
834 static struct dev_ops fcp_ops = {
835 DEVO_REV,
836 0,
837 ddi_getinfo_1to1,
838 nulldev, /* identify */
839 nulldev, /* probe */
840 fcp_attach, /* attach and detach are mandatory */
841 fcp_detach,
842 nodev, /* reset */
843 &fcp_cb_ops, /* cb_ops */
844 NULL, /* bus_ops */
845 NULL, /* power */
846 };
847
848
849 char *fcp_version = FCP_NAME_VERSION;
850
851 static struct modldrv modldrv = {
852 &mod_driverops,
853 FCP_NAME_VERSION,
854 &fcp_ops
855 };
856
857
858 static struct modlinkage modlinkage = {
859 MODREV_1,
860 &modldrv,
861 NULL
862 };
863
864
865 static fc_ulp_modinfo_t fcp_modinfo = {
866 &fcp_modinfo, /* ulp_handle */
867 FCTL_ULP_MODREV_4, /* ulp_rev */
868 FC4_SCSI_FCP, /* ulp_type */
869 "fcp", /* ulp_name */
870 FCP_STATEC_MASK, /* ulp_statec_mask */
871 fcp_port_attach, /* ulp_port_attach */
872 fcp_port_detach, /* ulp_port_detach */
873 fcp_port_ioctl, /* ulp_port_ioctl */
874 fcp_els_callback, /* ulp_els_callback */
875 fcp_data_callback, /* ulp_data_callback */
876 fcp_statec_callback /* ulp_statec_callback */
877 };
878
879 #ifdef DEBUG
880 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \
881 FCP_LEVEL_2 | FCP_LEVEL_3 | \
882 FCP_LEVEL_4 | FCP_LEVEL_5 | \
883 FCP_LEVEL_6 | FCP_LEVEL_7)
884 #else
885 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \
886 FCP_LEVEL_2 | FCP_LEVEL_3 | \
887 FCP_LEVEL_4 | FCP_LEVEL_5 | \
888 FCP_LEVEL_6 | FCP_LEVEL_7)
889 #endif
890
891 /* FCP global variables */
892 int fcp_bus_config_debug = 0;
893 static int fcp_log_size = FCP_LOG_SIZE;
894 static int fcp_trace = FCP_TRACE_DEFAULT;
895 static fc_trace_logq_t *fcp_logq = NULL;
896 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL;
897 /*
898 * The auto-configuration is set by default. The only way of disabling it is
899 * through the property MANUAL_CFG_ONLY in the fcp.conf file.
900 */
901 static int fcp_enable_auto_configuration = 1;
902 static int fcp_max_bus_config_retries = 4;
903 static int fcp_lun_ready_retry = 300;
904 /*
905 * The value assigned to the following variable has changed several times due
906 * to a problem with the data underruns reporting of some firmware(s). The
907 * current value of 50 gives a timeout value of 25 seconds for a max number
908 * of 256 LUNs.
909 */
910 static int fcp_max_target_retries = 50;
911 /*
912 * Watchdog variables
913 * ------------------
914 *
915 * fcp_watchdog_init
916 *
917 * Indicates if the watchdog timer is running or not. This is actually
918 * a counter of the number of Fibre Channel ports that attached. When
919 * the first port attaches the watchdog is started. When the last port
920 * detaches the watchdog timer is stopped.
921 *
922 * fcp_watchdog_time
923 *
924 * This is the watchdog clock counter. It is incremented by
925 * fcp_watchdog_time each time the watchdog timer expires.
926 *
927 * fcp_watchdog_timeout
928 *
929 * Increment value of the variable fcp_watchdog_time as well as the
930 * the timeout value of the watchdog timer. The unit is 1 second. It
931 * is strange that this is not a #define but a variable since the code
932 * never changes this value. The reason why it can be said that the
933 * unit is 1 second is because the number of ticks for the watchdog
934 * timer is determined like this:
935 *
936 * fcp_watchdog_tick = fcp_watchdog_timeout *
937 * drv_usectohz(1000000);
938 *
939 * The value 1000000 is hard coded in the code.
940 *
941 * fcp_watchdog_tick
942 *
943 * Watchdog timer value in ticks.
944 */
945 static int fcp_watchdog_init = 0;
946 static int fcp_watchdog_time = 0;
947 static int fcp_watchdog_timeout = 1;
948 static int fcp_watchdog_tick;
949
950 /*
951 * fcp_offline_delay is a global variable to enable customisation of
952 * the timeout on link offlines or RSCNs. The default value is set
953 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
954 * specified in FCP4 Chapter 11 (see www.t10.org).
955 *
956 * The variable fcp_offline_delay is specified in SECONDS.
957 *
958 * If we made this a static var then the user would not be able to
959 * change it. This variable is set in fcp_attach().
960 */
961 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY;
962
963 static void *fcp_softstate = NULL; /* for soft state */
964 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */
965 static kmutex_t fcp_global_mutex;
966 static kmutex_t fcp_ioctl_mutex;
967 static dev_info_t *fcp_global_dip = NULL;
968 static timeout_id_t fcp_watchdog_id;
969 const char *fcp_lun_prop = "lun";
970 const char *fcp_sam_lun_prop = "sam-lun";
971 const char *fcp_target_prop = "target";
972 /*
973 * NOTE: consumers of "node-wwn" property include stmsboot in ON
974 * consolidation.
975 */
976 const char *fcp_node_wwn_prop = "node-wwn";
977 const char *fcp_port_wwn_prop = "port-wwn";
978 const char *fcp_conf_wwn_prop = "fc-port-wwn";
979 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
980 const char *fcp_manual_config_only = "manual_configuration_only";
981 const char *fcp_init_port_prop = "initiator-port";
982 const char *fcp_tgt_port_prop = "target-port";
983 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
984
985 static struct fcp_port *fcp_port_head = NULL;
986 static ddi_eventcookie_t fcp_insert_eid;
987 static ddi_eventcookie_t fcp_remove_eid;
988
989 static ndi_event_definition_t fcp_ndi_event_defs[] = {
990 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
991 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
992 };
993
994 /*
995 * List of valid commands for the scsi_ioctl call
996 */
997 static uint8_t scsi_ioctl_list[] = {
998 SCMD_INQUIRY,
999 SCMD_REPORT_LUN,
1000 SCMD_READ_CAPACITY
1001 };
1002
1003 /*
1004 * this is used to dummy up a report lun response for cases
1005 * where the target doesn't support it
1006 */
1007 static uchar_t fcp_dummy_lun[] = {
1008 0x00, /* MSB length (length = no of luns * 8) */
1009 0x00,
1010 0x00,
1011 0x08, /* LSB length */
1012 0x00, /* MSB reserved */
1013 0x00,
1014 0x00,
1015 0x00, /* LSB reserved */
1016 FCP_PD_ADDRESSING,
1017 0x00, /* LUN is ZERO at the first level */
1018 0x00,
1019 0x00, /* second level is zero */
1020 0x00,
1021 0x00, /* third level is zero */
1022 0x00,
1023 0x00 /* fourth level is zero */
1024 };
1025
1026 static uchar_t fcp_alpa_to_switch[] = {
1027 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1029 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1030 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1031 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1032 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1033 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1034 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1035 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1036 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1037 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1038 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1039 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1040 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1041 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1043 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1044 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1045 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1047 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1048 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1049 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1050 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1051 };
1052
1053 static caddr_t pid = "SESS01 ";
1054
1055 #if !defined(lint)
1056
1057 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1058 fcp_port::fcp_next fcp_watchdog_id))
1059
1060 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1061
1062 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1063 fcp_insert_eid
1064 fcp_remove_eid
1065 fcp_watchdog_time))
1066
1067 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1068 fcp_cb_ops
1069 fcp_ops
1070 callb_cpr))
1071
1072 #endif /* lint */
1073
1074 /*
1075 * This table is used to determine whether or not it's safe to copy in
1076 * the target node name for a lun. Since all luns behind the same target
1077 * have the same wwnn, only tagets that do not support multiple luns are
1078 * eligible to be enumerated under mpxio if they aren't page83 compliant.
1079 */
1080
1081 char *fcp_symmetric_disk_table[] = {
1082 "SEAGATE ST",
1083 "IBM DDYFT",
1084 "SUNW SUNWGS", /* Daktari enclosure */
1085 "SUN SENA", /* SES device */
1086 "SUN SESS01" /* VICOM SVE box */
1087 };
1088
1089 int fcp_symmetric_disk_table_size =
1090 sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1091
1092 /*
1093 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1094 * will panic if you don't pass this in to the routine, this information.
1095 * Need to determine what the actual impact to the system is by providing
1096 * this information if any. Since dma allocation is done in pkt_init it may
1097 * not have any impact. These values are straight from the Writing Device
1098 * Driver manual.
1099 */
1100 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1101 DMA_ATTR_V0, /* ddi_dma_attr version */
1102 0, /* low address */
1103 0xffffffff, /* high address */
1104 0x00ffffff, /* counter upper bound */
1105 1, /* alignment requirements */
1106 0x3f, /* burst sizes */
1107 1, /* minimum DMA access */
1108 0xffffffff, /* maximum DMA access */
1109 (1 << 24) - 1, /* segment boundary restrictions */
1110 1, /* scater/gather list length */
1111 512, /* device granularity */
1112 0 /* DMA flags */
1113 };
1114
1115 /*
1116 * The _init(9e) return value should be that of mod_install(9f). Under
1117 * some circumstances, a failure may not be related mod_install(9f) and
1118 * one would then require a return value to indicate the failure. Looking
1119 * at mod_install(9f), it is expected to return 0 for success and non-zero
1120 * for failure. mod_install(9f) for device drivers, further goes down the
1121 * calling chain and ends up in ddi_installdrv(), whose return values are
1122 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1123 * calling chain of mod_install(9f) which return values like EINVAL and
1124 * in some even return -1.
1125 *
1126 * To work around the vagaries of the mod_install() calling chain, return
1127 * either 0 or ENODEV depending on the success or failure of mod_install()
1128 */
1129 int
_init(void)1130 _init(void)
1131 {
1132 int rval;
1133
1134 /*
1135 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1136 * before registering with the transport first.
1137 */
1138 if (ddi_soft_state_init(&fcp_softstate,
1139 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1140 return (EINVAL);
1141 }
1142
1143 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1144 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1145
1146 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1147 cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1148 mutex_destroy(&fcp_global_mutex);
1149 mutex_destroy(&fcp_ioctl_mutex);
1150 ddi_soft_state_fini(&fcp_softstate);
1151 return (ENODEV);
1152 }
1153
1154 fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1155
1156 if ((rval = mod_install(&modlinkage)) != 0) {
1157 fc_trace_free_logq(fcp_logq);
1158 (void) fc_ulp_remove(&fcp_modinfo);
1159 mutex_destroy(&fcp_global_mutex);
1160 mutex_destroy(&fcp_ioctl_mutex);
1161 ddi_soft_state_fini(&fcp_softstate);
1162 rval = ENODEV;
1163 }
1164
1165 return (rval);
1166 }
1167
1168
1169 /*
1170 * the system is done with us as a driver, so clean up
1171 */
1172 int
_fini(void)1173 _fini(void)
1174 {
1175 int rval;
1176
1177 /*
1178 * don't start cleaning up until we know that the module remove
1179 * has worked -- if this works, then we know that each instance
1180 * has successfully been DDI_DETACHed
1181 */
1182 if ((rval = mod_remove(&modlinkage)) != 0) {
1183 return (rval);
1184 }
1185
1186 (void) fc_ulp_remove(&fcp_modinfo);
1187
1188 ddi_soft_state_fini(&fcp_softstate);
1189 mutex_destroy(&fcp_global_mutex);
1190 mutex_destroy(&fcp_ioctl_mutex);
1191 fc_trace_free_logq(fcp_logq);
1192
1193 return (rval);
1194 }
1195
1196
1197 int
_info(struct modinfo * modinfop)1198 _info(struct modinfo *modinfop)
1199 {
1200 return (mod_info(&modlinkage, modinfop));
1201 }
1202
1203
1204 /*
1205 * attach the module
1206 */
1207 static int
fcp_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)1208 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1209 {
1210 int rval = DDI_SUCCESS;
1211
1212 FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1213 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1214
1215 if (cmd == DDI_ATTACH) {
1216 /* The FCP pseudo device is created here. */
1217 mutex_enter(&fcp_global_mutex);
1218 fcp_global_dip = devi;
1219 mutex_exit(&fcp_global_mutex);
1220
1221 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1222 0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1223 ddi_report_dev(fcp_global_dip);
1224 } else {
1225 cmn_err(CE_WARN, "FCP: Cannot create minor node");
1226 mutex_enter(&fcp_global_mutex);
1227 fcp_global_dip = NULL;
1228 mutex_exit(&fcp_global_mutex);
1229
1230 rval = DDI_FAILURE;
1231 }
1232 /*
1233 * We check the fcp_offline_delay property at this
1234 * point. This variable is global for the driver,
1235 * not specific to an instance.
1236 *
1237 * We do not recommend setting the value to less
1238 * than 10 seconds (RA_TOV_els), or greater than
1239 * 60 seconds.
1240 */
1241 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1242 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1243 "fcp_offline_delay", FCP_OFFLINE_DELAY);
1244 if ((fcp_offline_delay < 10) ||
1245 (fcp_offline_delay > 60)) {
1246 cmn_err(CE_WARN, "Setting fcp_offline_delay "
1247 "to %d second(s). This is outside the "
1248 "recommended range of 10..60 seconds.",
1249 fcp_offline_delay);
1250 }
1251 }
1252
1253 return (rval);
1254 }
1255
1256
1257 /*ARGSUSED*/
1258 static int
fcp_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)1259 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1260 {
1261 int res = DDI_SUCCESS;
1262
1263 FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1264 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd);
1265
1266 if (cmd == DDI_DETACH) {
1267 /*
1268 * Check if there are active ports/threads. If there
1269 * are any, we will fail, else we will succeed (there
1270 * should not be much to clean up)
1271 */
1272 mutex_enter(&fcp_global_mutex);
1273 FCP_DTRACE(fcp_logq, "fcp",
1274 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p",
1275 (void *) fcp_port_head);
1276
1277 if (fcp_port_head == NULL) {
1278 ddi_remove_minor_node(fcp_global_dip, NULL);
1279 fcp_global_dip = NULL;
1280 mutex_exit(&fcp_global_mutex);
1281 } else {
1282 mutex_exit(&fcp_global_mutex);
1283 res = DDI_FAILURE;
1284 }
1285 }
1286 FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1287 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res);
1288
1289 return (res);
1290 }
1291
1292
1293 /* ARGSUSED */
1294 static int
fcp_open(dev_t * devp,int flag,int otype,cred_t * credp)1295 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1296 {
1297 if (otype != OTYP_CHR) {
1298 return (EINVAL);
1299 }
1300
1301 /*
1302 * Allow only root to talk;
1303 */
1304 if (drv_priv(credp)) {
1305 return (EPERM);
1306 }
1307
1308 mutex_enter(&fcp_global_mutex);
1309 if (fcp_oflag & FCP_EXCL) {
1310 mutex_exit(&fcp_global_mutex);
1311 return (EBUSY);
1312 }
1313
1314 if (flag & FEXCL) {
1315 if (fcp_oflag & FCP_OPEN) {
1316 mutex_exit(&fcp_global_mutex);
1317 return (EBUSY);
1318 }
1319 fcp_oflag |= FCP_EXCL;
1320 }
1321 fcp_oflag |= FCP_OPEN;
1322 mutex_exit(&fcp_global_mutex);
1323
1324 return (0);
1325 }
1326
1327
1328 /* ARGSUSED */
1329 static int
fcp_close(dev_t dev,int flag,int otype,cred_t * credp)1330 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1331 {
1332 if (otype != OTYP_CHR) {
1333 return (EINVAL);
1334 }
1335
1336 mutex_enter(&fcp_global_mutex);
1337 if (!(fcp_oflag & FCP_OPEN)) {
1338 mutex_exit(&fcp_global_mutex);
1339 return (ENODEV);
1340 }
1341 fcp_oflag = FCP_IDLE;
1342 mutex_exit(&fcp_global_mutex);
1343
1344 return (0);
1345 }
1346
1347
1348 /*
1349 * fcp_ioctl
1350 * Entry point for the FCP ioctls
1351 *
1352 * Input:
1353 * See ioctl(9E)
1354 *
1355 * Output:
1356 * See ioctl(9E)
1357 *
1358 * Returns:
1359 * See ioctl(9E)
1360 *
1361 * Context:
1362 * Kernel context.
1363 */
1364 /* ARGSUSED */
1365 static int
fcp_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval)1366 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1367 int *rval)
1368 {
1369 int ret = 0;
1370
1371 mutex_enter(&fcp_global_mutex);
1372 if (!(fcp_oflag & FCP_OPEN)) {
1373 mutex_exit(&fcp_global_mutex);
1374 return (ENXIO);
1375 }
1376 mutex_exit(&fcp_global_mutex);
1377
1378 switch (cmd) {
1379 case FCP_TGT_INQUIRY:
1380 case FCP_TGT_CREATE:
1381 case FCP_TGT_DELETE:
1382 ret = fcp_setup_device_data_ioctl(cmd,
1383 (struct fcp_ioctl *)data, mode, rval);
1384 break;
1385
1386 case FCP_TGT_SEND_SCSI:
1387 mutex_enter(&fcp_ioctl_mutex);
1388 ret = fcp_setup_scsi_ioctl(
1389 (struct fcp_scsi_cmd *)data, mode, rval);
1390 mutex_exit(&fcp_ioctl_mutex);
1391 break;
1392
1393 case FCP_STATE_COUNT:
1394 ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1395 mode, rval);
1396 break;
1397 case FCP_GET_TARGET_MAPPINGS:
1398 ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1399 mode, rval);
1400 break;
1401 default:
1402 fcp_log(CE_WARN, NULL,
1403 "!Invalid ioctl opcode = 0x%x", cmd);
1404 ret = EINVAL;
1405 }
1406
1407 return (ret);
1408 }
1409
1410
1411 /*
1412 * fcp_setup_device_data_ioctl
1413 * Setup handler for the "device data" style of
1414 * ioctl for FCP. See "fcp_util.h" for data structure
1415 * definition.
1416 *
1417 * Input:
1418 * cmd = FCP ioctl command
1419 * data = ioctl data
1420 * mode = See ioctl(9E)
1421 *
1422 * Output:
1423 * data = ioctl data
1424 * rval = return value - see ioctl(9E)
1425 *
1426 * Returns:
1427 * See ioctl(9E)
1428 *
1429 * Context:
1430 * Kernel context.
1431 */
1432 /* ARGSUSED */
1433 static int
fcp_setup_device_data_ioctl(int cmd,struct fcp_ioctl * data,int mode,int * rval)1434 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1435 int *rval)
1436 {
1437 struct fcp_port *pptr;
1438 struct device_data *dev_data;
1439 uint32_t link_cnt;
1440 la_wwn_t *wwn_ptr = NULL;
1441 struct fcp_tgt *ptgt = NULL;
1442 struct fcp_lun *plun = NULL;
1443 int i, error;
1444 struct fcp_ioctl fioctl;
1445
1446 #ifdef _MULTI_DATAMODEL
1447 switch (ddi_model_convert_from(mode & FMODELS)) {
1448 case DDI_MODEL_ILP32: {
1449 struct fcp32_ioctl f32_ioctl;
1450
1451 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1452 sizeof (struct fcp32_ioctl), mode)) {
1453 return (EFAULT);
1454 }
1455 fioctl.fp_minor = f32_ioctl.fp_minor;
1456 fioctl.listlen = f32_ioctl.listlen;
1457 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1458 break;
1459 }
1460 case DDI_MODEL_NONE:
1461 if (ddi_copyin((void *)data, (void *)&fioctl,
1462 sizeof (struct fcp_ioctl), mode)) {
1463 return (EFAULT);
1464 }
1465 break;
1466 }
1467
1468 #else /* _MULTI_DATAMODEL */
1469 if (ddi_copyin((void *)data, (void *)&fioctl,
1470 sizeof (struct fcp_ioctl), mode)) {
1471 return (EFAULT);
1472 }
1473 #endif /* _MULTI_DATAMODEL */
1474
1475 /*
1476 * Right now we can assume that the minor number matches with
1477 * this instance of fp. If this changes we will need to
1478 * revisit this logic.
1479 */
1480 mutex_enter(&fcp_global_mutex);
1481 pptr = fcp_port_head;
1482 while (pptr) {
1483 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1484 break;
1485 } else {
1486 pptr = pptr->port_next;
1487 }
1488 }
1489 mutex_exit(&fcp_global_mutex);
1490 if (pptr == NULL) {
1491 return (ENXIO);
1492 }
1493 mutex_enter(&pptr->port_mutex);
1494
1495
1496 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1497 fioctl.listlen, KM_NOSLEEP)) == NULL) {
1498 mutex_exit(&pptr->port_mutex);
1499 return (ENOMEM);
1500 }
1501
1502 if (ddi_copyin(fioctl.list, dev_data,
1503 (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1504 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1505 mutex_exit(&pptr->port_mutex);
1506 return (EFAULT);
1507 }
1508 link_cnt = pptr->port_link_cnt;
1509
1510 if (cmd == FCP_TGT_INQUIRY) {
1511 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1512 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1513 sizeof (wwn_ptr->raw_wwn)) == 0) {
1514 /* This ioctl is requesting INQ info of local HBA */
1515 mutex_exit(&pptr->port_mutex);
1516 dev_data[0].dev0_type = DTYPE_UNKNOWN;
1517 dev_data[0].dev_status = 0;
1518 if (ddi_copyout(dev_data, fioctl.list,
1519 (sizeof (struct device_data)) * fioctl.listlen,
1520 mode)) {
1521 kmem_free(dev_data,
1522 sizeof (*dev_data) * fioctl.listlen);
1523 return (EFAULT);
1524 }
1525 kmem_free(dev_data,
1526 sizeof (*dev_data) * fioctl.listlen);
1527 #ifdef _MULTI_DATAMODEL
1528 switch (ddi_model_convert_from(mode & FMODELS)) {
1529 case DDI_MODEL_ILP32: {
1530 struct fcp32_ioctl f32_ioctl;
1531 f32_ioctl.fp_minor = fioctl.fp_minor;
1532 f32_ioctl.listlen = fioctl.listlen;
1533 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1534 if (ddi_copyout((void *)&f32_ioctl,
1535 (void *)data,
1536 sizeof (struct fcp32_ioctl), mode)) {
1537 return (EFAULT);
1538 }
1539 break;
1540 }
1541 case DDI_MODEL_NONE:
1542 if (ddi_copyout((void *)&fioctl, (void *)data,
1543 sizeof (struct fcp_ioctl), mode)) {
1544 return (EFAULT);
1545 }
1546 break;
1547 }
1548 #else /* _MULTI_DATAMODEL */
1549 if (ddi_copyout((void *)&fioctl, (void *)data,
1550 sizeof (struct fcp_ioctl), mode)) {
1551 return (EFAULT);
1552 }
1553 #endif /* _MULTI_DATAMODEL */
1554 return (0);
1555 }
1556 }
1557
1558 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1559 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1560 mutex_exit(&pptr->port_mutex);
1561 return (ENXIO);
1562 }
1563
1564 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1565 i++) {
1566 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1567
1568 dev_data[i].dev0_type = DTYPE_UNKNOWN;
1569
1570
1571 dev_data[i].dev_status = ENXIO;
1572
1573 if ((ptgt = fcp_lookup_target(pptr,
1574 (uchar_t *)wwn_ptr)) == NULL) {
1575 mutex_exit(&pptr->port_mutex);
1576 if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1577 wwn_ptr, &error, 0) == NULL) {
1578 dev_data[i].dev_status = ENODEV;
1579 mutex_enter(&pptr->port_mutex);
1580 continue;
1581 } else {
1582
1583 dev_data[i].dev_status = EAGAIN;
1584
1585 mutex_enter(&pptr->port_mutex);
1586 continue;
1587 }
1588 } else {
1589 mutex_enter(&ptgt->tgt_mutex);
1590 if (ptgt->tgt_state & (FCP_TGT_MARK |
1591 FCP_TGT_BUSY)) {
1592 dev_data[i].dev_status = EAGAIN;
1593 mutex_exit(&ptgt->tgt_mutex);
1594 continue;
1595 }
1596
1597 if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1598 if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1599 dev_data[i].dev_status = ENOTSUP;
1600 } else {
1601 dev_data[i].dev_status = ENXIO;
1602 }
1603 mutex_exit(&ptgt->tgt_mutex);
1604 continue;
1605 }
1606
1607 switch (cmd) {
1608 case FCP_TGT_INQUIRY:
1609 /*
1610 * The reason we give device type of
1611 * lun 0 only even though in some
1612 * cases(like maxstrat) lun 0 device
1613 * type may be 0x3f(invalid) is that
1614 * for bridge boxes target will appear
1615 * as luns and the first lun could be
1616 * a device that utility may not care
1617 * about (like a tape device).
1618 */
1619 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1620 dev_data[i].dev_status = 0;
1621 mutex_exit(&ptgt->tgt_mutex);
1622
1623 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1624 dev_data[i].dev0_type = DTYPE_UNKNOWN;
1625 } else {
1626 dev_data[i].dev0_type = plun->lun_type;
1627 }
1628 mutex_enter(&ptgt->tgt_mutex);
1629 break;
1630
1631 case FCP_TGT_CREATE:
1632 mutex_exit(&ptgt->tgt_mutex);
1633 mutex_exit(&pptr->port_mutex);
1634
1635 /*
1636 * serialize state change call backs.
1637 * only one call back will be handled
1638 * at a time.
1639 */
1640 mutex_enter(&fcp_global_mutex);
1641 if (fcp_oflag & FCP_BUSY) {
1642 mutex_exit(&fcp_global_mutex);
1643 if (dev_data) {
1644 kmem_free(dev_data,
1645 sizeof (*dev_data) *
1646 fioctl.listlen);
1647 }
1648 return (EBUSY);
1649 }
1650 fcp_oflag |= FCP_BUSY;
1651 mutex_exit(&fcp_global_mutex);
1652
1653 dev_data[i].dev_status =
1654 fcp_create_on_demand(pptr,
1655 wwn_ptr->raw_wwn);
1656
1657 if (dev_data[i].dev_status != 0) {
1658 char buf[25];
1659
1660 for (i = 0; i < FC_WWN_SIZE; i++) {
1661 (void) sprintf(&buf[i << 1],
1662 "%02x",
1663 wwn_ptr->raw_wwn[i]);
1664 }
1665
1666 fcp_log(CE_WARN, pptr->port_dip,
1667 "!Failed to create nodes for"
1668 " pwwn=%s; error=%x", buf,
1669 dev_data[i].dev_status);
1670 }
1671
1672 /* allow state change call backs again */
1673 mutex_enter(&fcp_global_mutex);
1674 fcp_oflag &= ~FCP_BUSY;
1675 mutex_exit(&fcp_global_mutex);
1676
1677 mutex_enter(&pptr->port_mutex);
1678 mutex_enter(&ptgt->tgt_mutex);
1679
1680 break;
1681
1682 case FCP_TGT_DELETE:
1683 break;
1684
1685 default:
1686 fcp_log(CE_WARN, pptr->port_dip,
1687 "!Invalid device data ioctl "
1688 "opcode = 0x%x", cmd);
1689 }
1690 mutex_exit(&ptgt->tgt_mutex);
1691 }
1692 }
1693 mutex_exit(&pptr->port_mutex);
1694
1695 if (ddi_copyout(dev_data, fioctl.list,
1696 (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1697 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1698 return (EFAULT);
1699 }
1700 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1701
1702 #ifdef _MULTI_DATAMODEL
1703 switch (ddi_model_convert_from(mode & FMODELS)) {
1704 case DDI_MODEL_ILP32: {
1705 struct fcp32_ioctl f32_ioctl;
1706
1707 f32_ioctl.fp_minor = fioctl.fp_minor;
1708 f32_ioctl.listlen = fioctl.listlen;
1709 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1710 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1711 sizeof (struct fcp32_ioctl), mode)) {
1712 return (EFAULT);
1713 }
1714 break;
1715 }
1716 case DDI_MODEL_NONE:
1717 if (ddi_copyout((void *)&fioctl, (void *)data,
1718 sizeof (struct fcp_ioctl), mode)) {
1719 return (EFAULT);
1720 }
1721 break;
1722 }
1723 #else /* _MULTI_DATAMODEL */
1724
1725 if (ddi_copyout((void *)&fioctl, (void *)data,
1726 sizeof (struct fcp_ioctl), mode)) {
1727 return (EFAULT);
1728 }
1729 #endif /* _MULTI_DATAMODEL */
1730
1731 return (0);
1732 }
1733
1734 /*
1735 * Fetch the target mappings (path, etc.) for all LUNs
1736 * on this port.
1737 */
1738 /* ARGSUSED */
1739 static int
fcp_get_target_mappings(struct fcp_ioctl * data,int mode,int * rval)1740 fcp_get_target_mappings(struct fcp_ioctl *data,
1741 int mode, int *rval)
1742 {
1743 struct fcp_port *pptr;
1744 fc_hba_target_mappings_t *mappings;
1745 fc_hba_mapping_entry_t *map;
1746 struct fcp_tgt *ptgt = NULL;
1747 struct fcp_lun *plun = NULL;
1748 int i, mapIndex, mappingSize;
1749 int listlen;
1750 struct fcp_ioctl fioctl;
1751 char *path;
1752 fcp_ent_addr_t sam_lun_addr;
1753
1754 #ifdef _MULTI_DATAMODEL
1755 switch (ddi_model_convert_from(mode & FMODELS)) {
1756 case DDI_MODEL_ILP32: {
1757 struct fcp32_ioctl f32_ioctl;
1758
1759 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1760 sizeof (struct fcp32_ioctl), mode)) {
1761 return (EFAULT);
1762 }
1763 fioctl.fp_minor = f32_ioctl.fp_minor;
1764 fioctl.listlen = f32_ioctl.listlen;
1765 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1766 break;
1767 }
1768 case DDI_MODEL_NONE:
1769 if (ddi_copyin((void *)data, (void *)&fioctl,
1770 sizeof (struct fcp_ioctl), mode)) {
1771 return (EFAULT);
1772 }
1773 break;
1774 }
1775
1776 #else /* _MULTI_DATAMODEL */
1777 if (ddi_copyin((void *)data, (void *)&fioctl,
1778 sizeof (struct fcp_ioctl), mode)) {
1779 return (EFAULT);
1780 }
1781 #endif /* _MULTI_DATAMODEL */
1782
1783 /*
1784 * Right now we can assume that the minor number matches with
1785 * this instance of fp. If this changes we will need to
1786 * revisit this logic.
1787 */
1788 mutex_enter(&fcp_global_mutex);
1789 pptr = fcp_port_head;
1790 while (pptr) {
1791 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1792 break;
1793 } else {
1794 pptr = pptr->port_next;
1795 }
1796 }
1797 mutex_exit(&fcp_global_mutex);
1798 if (pptr == NULL) {
1799 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1800 fioctl.fp_minor);
1801 return (ENXIO);
1802 }
1803
1804
1805 /* We use listlen to show the total buffer size */
1806 mappingSize = fioctl.listlen;
1807
1808 /* Now calculate how many mapping entries will fit */
1809 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1810 - sizeof (fc_hba_target_mappings_t);
1811 if (listlen <= 0) {
1812 cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1813 return (ENXIO);
1814 }
1815 listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1816
1817 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1818 return (ENOMEM);
1819 }
1820 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1821
1822 /* Now get to work */
1823 mapIndex = 0;
1824
1825 mutex_enter(&pptr->port_mutex);
1826 /* Loop through all targets on this port */
1827 for (i = 0; i < FCP_NUM_HASH; i++) {
1828 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1829 ptgt = ptgt->tgt_next) {
1830
1831 mutex_enter(&ptgt->tgt_mutex);
1832
1833 /* Loop through all LUNs on this target */
1834 for (plun = ptgt->tgt_lun; plun != NULL;
1835 plun = plun->lun_next) {
1836 if (plun->lun_state & FCP_LUN_OFFLINE) {
1837 continue;
1838 }
1839
1840 path = fcp_get_lun_path(plun);
1841 if (path == NULL) {
1842 continue;
1843 }
1844
1845 if (mapIndex >= listlen) {
1846 mapIndex ++;
1847 kmem_free(path, MAXPATHLEN);
1848 continue;
1849 }
1850 map = &mappings->entries[mapIndex++];
1851 bcopy(path, map->targetDriver,
1852 sizeof (map->targetDriver));
1853 map->d_id = ptgt->tgt_d_id;
1854 map->busNumber = 0;
1855 map->targetNumber = ptgt->tgt_d_id;
1856 map->osLUN = plun->lun_num;
1857
1858 /*
1859 * We had swapped lun when we stored it in
1860 * lun_addr. We need to swap it back before
1861 * returning it to user land
1862 */
1863
1864 sam_lun_addr.ent_addr_0 =
1865 BE_16(plun->lun_addr.ent_addr_0);
1866 sam_lun_addr.ent_addr_1 =
1867 BE_16(plun->lun_addr.ent_addr_1);
1868 sam_lun_addr.ent_addr_2 =
1869 BE_16(plun->lun_addr.ent_addr_2);
1870 sam_lun_addr.ent_addr_3 =
1871 BE_16(plun->lun_addr.ent_addr_3);
1872
1873 bcopy(&sam_lun_addr, &map->samLUN,
1874 FCP_LUN_SIZE);
1875 bcopy(ptgt->tgt_node_wwn.raw_wwn,
1876 map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1877 bcopy(ptgt->tgt_port_wwn.raw_wwn,
1878 map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1879
1880 if (plun->lun_guid) {
1881
1882 /* convert ascii wwn to bytes */
1883 fcp_ascii_to_wwn(plun->lun_guid,
1884 map->guid, sizeof (map->guid));
1885
1886 if ((sizeof (map->guid)) <
1887 plun->lun_guid_size / 2) {
1888 cmn_err(CE_WARN,
1889 "fcp_get_target_mappings:"
1890 "guid copy space "
1891 "insufficient."
1892 "Copy Truncation - "
1893 "available %d; need %d",
1894 (int)sizeof (map->guid),
1895 (int)
1896 plun->lun_guid_size / 2);
1897 }
1898 }
1899 kmem_free(path, MAXPATHLEN);
1900 }
1901 mutex_exit(&ptgt->tgt_mutex);
1902 }
1903 }
1904 mutex_exit(&pptr->port_mutex);
1905 mappings->numLuns = mapIndex;
1906
1907 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1908 kmem_free(mappings, mappingSize);
1909 return (EFAULT);
1910 }
1911 kmem_free(mappings, mappingSize);
1912
1913 #ifdef _MULTI_DATAMODEL
1914 switch (ddi_model_convert_from(mode & FMODELS)) {
1915 case DDI_MODEL_ILP32: {
1916 struct fcp32_ioctl f32_ioctl;
1917
1918 f32_ioctl.fp_minor = fioctl.fp_minor;
1919 f32_ioctl.listlen = fioctl.listlen;
1920 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1921 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1922 sizeof (struct fcp32_ioctl), mode)) {
1923 return (EFAULT);
1924 }
1925 break;
1926 }
1927 case DDI_MODEL_NONE:
1928 if (ddi_copyout((void *)&fioctl, (void *)data,
1929 sizeof (struct fcp_ioctl), mode)) {
1930 return (EFAULT);
1931 }
1932 break;
1933 }
1934 #else /* _MULTI_DATAMODEL */
1935
1936 if (ddi_copyout((void *)&fioctl, (void *)data,
1937 sizeof (struct fcp_ioctl), mode)) {
1938 return (EFAULT);
1939 }
1940 #endif /* _MULTI_DATAMODEL */
1941
1942 return (0);
1943 }
1944
1945 /*
1946 * fcp_setup_scsi_ioctl
1947 * Setup handler for the "scsi passthru" style of
1948 * ioctl for FCP. See "fcp_util.h" for data structure
1949 * definition.
1950 *
1951 * Input:
1952 * u_fscsi = ioctl data (user address space)
1953 * mode = See ioctl(9E)
1954 *
1955 * Output:
1956 * u_fscsi = ioctl data (user address space)
1957 * rval = return value - see ioctl(9E)
1958 *
1959 * Returns:
1960 * 0 = OK
1961 * EAGAIN = See errno.h
1962 * EBUSY = See errno.h
1963 * EFAULT = See errno.h
1964 * EINTR = See errno.h
1965 * EINVAL = See errno.h
1966 * EIO = See errno.h
1967 * ENOMEM = See errno.h
1968 * ENXIO = See errno.h
1969 *
1970 * Context:
1971 * Kernel context.
1972 */
1973 /* ARGSUSED */
1974 static int
fcp_setup_scsi_ioctl(struct fcp_scsi_cmd * u_fscsi,int mode,int * rval)1975 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1976 int mode, int *rval)
1977 {
1978 int ret = 0;
1979 int temp_ret;
1980 caddr_t k_cdbbufaddr = NULL;
1981 caddr_t k_bufaddr = NULL;
1982 caddr_t k_rqbufaddr = NULL;
1983 caddr_t u_cdbbufaddr;
1984 caddr_t u_bufaddr;
1985 caddr_t u_rqbufaddr;
1986 struct fcp_scsi_cmd k_fscsi;
1987
1988 /*
1989 * Get fcp_scsi_cmd array element from user address space
1990 */
1991 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1992 != 0) {
1993 return (ret);
1994 }
1995
1996
1997 /*
1998 * Even though kmem_alloc() checks the validity of the
1999 * buffer length, this check is needed when the
2000 * kmem_flags set and the zero buffer length is passed.
2001 */
2002 if ((k_fscsi.scsi_cdblen <= 0) ||
2003 (k_fscsi.scsi_buflen <= 0) ||
2004 (k_fscsi.scsi_rqlen <= 0)) {
2005 return (EINVAL);
2006 }
2007
2008 /*
2009 * Allocate data for fcp_scsi_cmd pointer fields
2010 */
2011 if (ret == 0) {
2012 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2013 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2014 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP);
2015
2016 if (k_cdbbufaddr == NULL ||
2017 k_bufaddr == NULL ||
2018 k_rqbufaddr == NULL) {
2019 ret = ENOMEM;
2020 }
2021 }
2022
2023 /*
2024 * Get fcp_scsi_cmd pointer fields from user
2025 * address space
2026 */
2027 if (ret == 0) {
2028 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2029 u_bufaddr = k_fscsi.scsi_bufaddr;
2030 u_rqbufaddr = k_fscsi.scsi_rqbufaddr;
2031
2032 if (ddi_copyin(u_cdbbufaddr,
2033 k_cdbbufaddr,
2034 k_fscsi.scsi_cdblen,
2035 mode)) {
2036 ret = EFAULT;
2037 } else if (ddi_copyin(u_bufaddr,
2038 k_bufaddr,
2039 k_fscsi.scsi_buflen,
2040 mode)) {
2041 ret = EFAULT;
2042 } else if (ddi_copyin(u_rqbufaddr,
2043 k_rqbufaddr,
2044 k_fscsi.scsi_rqlen,
2045 mode)) {
2046 ret = EFAULT;
2047 }
2048 }
2049
2050 /*
2051 * Send scsi command (blocking)
2052 */
2053 if (ret == 0) {
2054 /*
2055 * Prior to sending the scsi command, the
2056 * fcp_scsi_cmd data structure must contain kernel,
2057 * not user, addresses.
2058 */
2059 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr;
2060 k_fscsi.scsi_bufaddr = k_bufaddr;
2061 k_fscsi.scsi_rqbufaddr = k_rqbufaddr;
2062
2063 ret = fcp_send_scsi_ioctl(&k_fscsi);
2064
2065 /*
2066 * After sending the scsi command, the
2067 * fcp_scsi_cmd data structure must contain user,
2068 * not kernel, addresses.
2069 */
2070 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr;
2071 k_fscsi.scsi_bufaddr = u_bufaddr;
2072 k_fscsi.scsi_rqbufaddr = u_rqbufaddr;
2073 }
2074
2075 /*
2076 * Put fcp_scsi_cmd pointer fields to user address space
2077 */
2078 if (ret == 0) {
2079 if (ddi_copyout(k_cdbbufaddr,
2080 u_cdbbufaddr,
2081 k_fscsi.scsi_cdblen,
2082 mode)) {
2083 ret = EFAULT;
2084 } else if (ddi_copyout(k_bufaddr,
2085 u_bufaddr,
2086 k_fscsi.scsi_buflen,
2087 mode)) {
2088 ret = EFAULT;
2089 } else if (ddi_copyout(k_rqbufaddr,
2090 u_rqbufaddr,
2091 k_fscsi.scsi_rqlen,
2092 mode)) {
2093 ret = EFAULT;
2094 }
2095 }
2096
2097 /*
2098 * Free data for fcp_scsi_cmd pointer fields
2099 */
2100 if (k_cdbbufaddr != NULL) {
2101 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2102 }
2103 if (k_bufaddr != NULL) {
2104 kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2105 }
2106 if (k_rqbufaddr != NULL) {
2107 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2108 }
2109
2110 /*
2111 * Put fcp_scsi_cmd array element to user address space
2112 */
2113 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2114 if (temp_ret != 0) {
2115 ret = temp_ret;
2116 }
2117
2118 /*
2119 * Return status
2120 */
2121 return (ret);
2122 }
2123
2124
2125 /*
2126 * fcp_copyin_scsi_cmd
2127 * Copy in fcp_scsi_cmd data structure from user address space.
2128 * The data may be in 32 bit or 64 bit modes.
2129 *
2130 * Input:
2131 * base_addr = from address (user address space)
2132 * mode = See ioctl(9E) and ddi_copyin(9F)
2133 *
2134 * Output:
2135 * fscsi = to address (kernel address space)
2136 *
2137 * Returns:
2138 * 0 = OK
2139 * EFAULT = Error
2140 *
2141 * Context:
2142 * Kernel context.
2143 */
2144 static int
fcp_copyin_scsi_cmd(caddr_t base_addr,struct fcp_scsi_cmd * fscsi,int mode)2145 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2146 {
2147 #ifdef _MULTI_DATAMODEL
2148 struct fcp32_scsi_cmd f32scsi;
2149
2150 switch (ddi_model_convert_from(mode & FMODELS)) {
2151 case DDI_MODEL_ILP32:
2152 /*
2153 * Copy data from user address space
2154 */
2155 if (ddi_copyin((void *)base_addr,
2156 &f32scsi,
2157 sizeof (struct fcp32_scsi_cmd),
2158 mode)) {
2159 return (EFAULT);
2160 }
2161 /*
2162 * Convert from 32 bit to 64 bit
2163 */
2164 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2165 break;
2166 case DDI_MODEL_NONE:
2167 /*
2168 * Copy data from user address space
2169 */
2170 if (ddi_copyin((void *)base_addr,
2171 fscsi,
2172 sizeof (struct fcp_scsi_cmd),
2173 mode)) {
2174 return (EFAULT);
2175 }
2176 break;
2177 }
2178 #else /* _MULTI_DATAMODEL */
2179 /*
2180 * Copy data from user address space
2181 */
2182 if (ddi_copyin((void *)base_addr,
2183 fscsi,
2184 sizeof (struct fcp_scsi_cmd),
2185 mode)) {
2186 return (EFAULT);
2187 }
2188 #endif /* _MULTI_DATAMODEL */
2189
2190 return (0);
2191 }
2192
2193
2194 /*
2195 * fcp_copyout_scsi_cmd
2196 * Copy out fcp_scsi_cmd data structure to user address space.
2197 * The data may be in 32 bit or 64 bit modes.
2198 *
2199 * Input:
2200 * fscsi = to address (kernel address space)
2201 * mode = See ioctl(9E) and ddi_copyin(9F)
2202 *
2203 * Output:
2204 * base_addr = from address (user address space)
2205 *
2206 * Returns:
2207 * 0 = OK
2208 * EFAULT = Error
2209 *
2210 * Context:
2211 * Kernel context.
2212 */
2213 static int
fcp_copyout_scsi_cmd(struct fcp_scsi_cmd * fscsi,caddr_t base_addr,int mode)2214 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2215 {
2216 #ifdef _MULTI_DATAMODEL
2217 struct fcp32_scsi_cmd f32scsi;
2218
2219 switch (ddi_model_convert_from(mode & FMODELS)) {
2220 case DDI_MODEL_ILP32:
2221 /*
2222 * Convert from 64 bit to 32 bit
2223 */
2224 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2225 /*
2226 * Copy data to user address space
2227 */
2228 if (ddi_copyout(&f32scsi,
2229 (void *)base_addr,
2230 sizeof (struct fcp32_scsi_cmd),
2231 mode)) {
2232 return (EFAULT);
2233 }
2234 break;
2235 case DDI_MODEL_NONE:
2236 /*
2237 * Copy data to user address space
2238 */
2239 if (ddi_copyout(fscsi,
2240 (void *)base_addr,
2241 sizeof (struct fcp_scsi_cmd),
2242 mode)) {
2243 return (EFAULT);
2244 }
2245 break;
2246 }
2247 #else /* _MULTI_DATAMODEL */
2248 /*
2249 * Copy data to user address space
2250 */
2251 if (ddi_copyout(fscsi,
2252 (void *)base_addr,
2253 sizeof (struct fcp_scsi_cmd),
2254 mode)) {
2255 return (EFAULT);
2256 }
2257 #endif /* _MULTI_DATAMODEL */
2258
2259 return (0);
2260 }
2261
2262
2263 /*
2264 * fcp_send_scsi_ioctl
2265 * Sends the SCSI command in blocking mode.
2266 *
2267 * Input:
2268 * fscsi = SCSI command data structure
2269 *
2270 * Output:
2271 * fscsi = SCSI command data structure
2272 *
2273 * Returns:
2274 * 0 = OK
2275 * EAGAIN = See errno.h
2276 * EBUSY = See errno.h
2277 * EINTR = See errno.h
2278 * EINVAL = See errno.h
2279 * EIO = See errno.h
2280 * ENOMEM = See errno.h
2281 * ENXIO = See errno.h
2282 *
2283 * Context:
2284 * Kernel context.
2285 */
2286 static int
fcp_send_scsi_ioctl(struct fcp_scsi_cmd * fscsi)2287 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2288 {
2289 struct fcp_lun *plun = NULL;
2290 struct fcp_port *pptr = NULL;
2291 struct fcp_tgt *ptgt = NULL;
2292 fc_packet_t *fpkt = NULL;
2293 struct fcp_ipkt *icmd = NULL;
2294 int target_created = FALSE;
2295 fc_frame_hdr_t *hp;
2296 struct fcp_cmd fcp_cmd;
2297 struct fcp_cmd *fcmd;
2298 union scsi_cdb *scsi_cdb;
2299 la_wwn_t *wwn_ptr;
2300 int nodma;
2301 struct fcp_rsp *rsp;
2302 struct fcp_rsp_info *rsp_info;
2303 caddr_t rsp_sense;
2304 int buf_len;
2305 int info_len;
2306 int sense_len;
2307 struct scsi_extended_sense *sense_to = NULL;
2308 timeout_id_t tid;
2309 uint8_t reconfig_lun = FALSE;
2310 uint8_t reconfig_pending = FALSE;
2311 uint8_t scsi_cmd;
2312 int rsp_len;
2313 int cmd_index;
2314 int fc_status;
2315 int pkt_state;
2316 int pkt_action;
2317 int pkt_reason;
2318 int ret, xport_retval = ~FC_SUCCESS;
2319 int lcount;
2320 int tcount;
2321 int reconfig_status;
2322 int port_busy = FALSE;
2323 uchar_t *lun_string;
2324
2325 /*
2326 * Check valid SCSI command
2327 */
2328 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2329 ret = EINVAL;
2330 for (cmd_index = 0;
2331 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2332 ret != 0;
2333 cmd_index++) {
2334 /*
2335 * First byte of CDB is the SCSI command
2336 */
2337 if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2338 ret = 0;
2339 }
2340 }
2341
2342 /*
2343 * Check inputs
2344 */
2345 if (fscsi->scsi_flags != FCP_SCSI_READ) {
2346 ret = EINVAL;
2347 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2348 /* no larger than */
2349 ret = EINVAL;
2350 }
2351
2352
2353 /*
2354 * Find FC port
2355 */
2356 if (ret == 0) {
2357 /*
2358 * Acquire global mutex
2359 */
2360 mutex_enter(&fcp_global_mutex);
2361
2362 pptr = fcp_port_head;
2363 while (pptr) {
2364 if (pptr->port_instance ==
2365 (uint32_t)fscsi->scsi_fc_port_num) {
2366 break;
2367 } else {
2368 pptr = pptr->port_next;
2369 }
2370 }
2371
2372 if (pptr == NULL) {
2373 ret = ENXIO;
2374 } else {
2375 /*
2376 * fc_ulp_busy_port can raise power
2377 * so, we must not hold any mutexes involved in PM
2378 */
2379 mutex_exit(&fcp_global_mutex);
2380 ret = fc_ulp_busy_port(pptr->port_fp_handle);
2381 }
2382
2383 if (ret == 0) {
2384
2385 /* remember port is busy, so we will release later */
2386 port_busy = TRUE;
2387
2388 /*
2389 * If there is a reconfiguration in progress, wait
2390 * for it to complete.
2391 */
2392
2393 fcp_reconfig_wait(pptr);
2394
2395 /* reacquire mutexes in order */
2396 mutex_enter(&fcp_global_mutex);
2397 mutex_enter(&pptr->port_mutex);
2398
2399 /*
2400 * Will port accept DMA?
2401 */
2402 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2403 ? 1 : 0;
2404
2405 /*
2406 * If init or offline, device not known
2407 *
2408 * If we are discovering (onlining), we can
2409 * NOT obviously provide reliable data about
2410 * devices until it is complete
2411 */
2412 if (pptr->port_state & (FCP_STATE_INIT |
2413 FCP_STATE_OFFLINE)) {
2414 ret = ENXIO;
2415 } else if (pptr->port_state & FCP_STATE_ONLINING) {
2416 ret = EBUSY;
2417 } else {
2418 /*
2419 * Find target from pwwn
2420 *
2421 * The wwn must be put into a local
2422 * variable to ensure alignment.
2423 */
2424 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2425 ptgt = fcp_lookup_target(pptr,
2426 (uchar_t *)wwn_ptr);
2427
2428 /*
2429 * If target not found,
2430 */
2431 if (ptgt == NULL) {
2432 /*
2433 * Note: Still have global &
2434 * port mutexes
2435 */
2436 mutex_exit(&pptr->port_mutex);
2437 ptgt = fcp_port_create_tgt(pptr,
2438 wwn_ptr, &ret, &fc_status,
2439 &pkt_state, &pkt_action,
2440 &pkt_reason);
2441 mutex_enter(&pptr->port_mutex);
2442
2443 fscsi->scsi_fc_status = fc_status;
2444 fscsi->scsi_pkt_state =
2445 (uchar_t)pkt_state;
2446 fscsi->scsi_pkt_reason = pkt_reason;
2447 fscsi->scsi_pkt_action =
2448 (uchar_t)pkt_action;
2449
2450 if (ptgt != NULL) {
2451 target_created = TRUE;
2452 } else if (ret == 0) {
2453 ret = ENOMEM;
2454 }
2455 }
2456
2457 if (ret == 0) {
2458 /*
2459 * Acquire target
2460 */
2461 mutex_enter(&ptgt->tgt_mutex);
2462
2463 /*
2464 * If target is mark or busy,
2465 * then target can not be used
2466 */
2467 if (ptgt->tgt_state &
2468 (FCP_TGT_MARK |
2469 FCP_TGT_BUSY)) {
2470 ret = EBUSY;
2471 } else {
2472 /*
2473 * Mark target as busy
2474 */
2475 ptgt->tgt_state |=
2476 FCP_TGT_BUSY;
2477 }
2478
2479 /*
2480 * Release target
2481 */
2482 lcount = pptr->port_link_cnt;
2483 tcount = ptgt->tgt_change_cnt;
2484 mutex_exit(&ptgt->tgt_mutex);
2485 }
2486 }
2487
2488 /*
2489 * Release port
2490 */
2491 mutex_exit(&pptr->port_mutex);
2492 }
2493
2494 /*
2495 * Release global mutex
2496 */
2497 mutex_exit(&fcp_global_mutex);
2498 }
2499
2500 if (ret == 0) {
2501 uint64_t belun = BE_64(fscsi->scsi_lun);
2502
2503 /*
2504 * If it's a target device, find lun from pwwn
2505 * The wwn must be put into a local
2506 * variable to ensure alignment.
2507 */
2508 mutex_enter(&pptr->port_mutex);
2509 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2510 if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2511 /* this is not a target */
2512 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2513 ret = ENXIO;
2514 } else if ((belun << 16) != 0) {
2515 /*
2516 * Since fcp only support PD and LU addressing method
2517 * so far, the last 6 bytes of a valid LUN are expected
2518 * to be filled with 00h.
2519 */
2520 fscsi->scsi_fc_status = FC_INVALID_LUN;
2521 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2522 " method 0x%02x with LUN number 0x%016" PRIx64,
2523 (uint8_t)(belun >> 62), belun);
2524 ret = ENXIO;
2525 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2526 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2527 /*
2528 * This is a SCSI target, but no LUN at this
2529 * address.
2530 *
2531 * In the future, we may want to send this to
2532 * the target, and let it respond
2533 * appropriately
2534 */
2535 ret = ENXIO;
2536 }
2537 mutex_exit(&pptr->port_mutex);
2538 }
2539
2540 /*
2541 * Finished grabbing external resources
2542 * Allocate internal packet (icmd)
2543 */
2544 if (ret == 0) {
2545 /*
2546 * Calc rsp len assuming rsp info included
2547 */
2548 rsp_len = sizeof (struct fcp_rsp) +
2549 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2550
2551 icmd = fcp_icmd_alloc(pptr, ptgt,
2552 sizeof (struct fcp_cmd),
2553 rsp_len,
2554 fscsi->scsi_buflen,
2555 nodma,
2556 lcount, /* ipkt_link_cnt */
2557 tcount, /* ipkt_change_cnt */
2558 0, /* cause */
2559 FC_INVALID_RSCN_COUNT); /* invalidate the count */
2560
2561 if (icmd == NULL) {
2562 ret = ENOMEM;
2563 } else {
2564 /*
2565 * Setup internal packet as sema sync
2566 */
2567 fcp_ipkt_sema_init(icmd);
2568 }
2569 }
2570
2571 if (ret == 0) {
2572 /*
2573 * Init fpkt pointer for use.
2574 */
2575
2576 fpkt = icmd->ipkt_fpkt;
2577
2578 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
2579 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */
2580 fpkt->pkt_timeout = fscsi->scsi_timeout;
2581
2582 /*
2583 * Init fcmd pointer for use by SCSI command
2584 */
2585
2586 if (nodma) {
2587 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2588 } else {
2589 fcmd = &fcp_cmd;
2590 }
2591 bzero(fcmd, sizeof (struct fcp_cmd));
2592 ptgt = plun->lun_tgt;
2593
2594 lun_string = (uchar_t *)&fscsi->scsi_lun;
2595
2596 fcmd->fcp_ent_addr.ent_addr_0 =
2597 BE_16(*(uint16_t *)&(lun_string[0]));
2598 fcmd->fcp_ent_addr.ent_addr_1 =
2599 BE_16(*(uint16_t *)&(lun_string[2]));
2600 fcmd->fcp_ent_addr.ent_addr_2 =
2601 BE_16(*(uint16_t *)&(lun_string[4]));
2602 fcmd->fcp_ent_addr.ent_addr_3 =
2603 BE_16(*(uint16_t *)&(lun_string[6]));
2604
2605 /*
2606 * Setup internal packet(icmd)
2607 */
2608 icmd->ipkt_lun = plun;
2609 icmd->ipkt_restart = 0;
2610 icmd->ipkt_retries = 0;
2611 icmd->ipkt_opcode = 0;
2612
2613 /*
2614 * Init the frame HEADER Pointer for use
2615 */
2616 hp = &fpkt->pkt_cmd_fhdr;
2617
2618 hp->s_id = pptr->port_id;
2619 hp->d_id = ptgt->tgt_d_id;
2620 hp->r_ctl = R_CTL_COMMAND;
2621 hp->type = FC_TYPE_SCSI_FCP;
2622 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2623 hp->rsvd = 0;
2624 hp->seq_id = 0;
2625 hp->seq_cnt = 0;
2626 hp->ox_id = 0xffff;
2627 hp->rx_id = 0xffff;
2628 hp->ro = 0;
2629
2630 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
2631 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */
2632 fcmd->fcp_cntl.cntl_write_data = 0;
2633 fcmd->fcp_data_len = fscsi->scsi_buflen;
2634
2635 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2636 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2637 fscsi->scsi_cdblen);
2638
2639 if (!nodma) {
2640 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2641 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2642 }
2643
2644 /*
2645 * Send SCSI command to FC transport
2646 */
2647
2648 if (ret == 0) {
2649 mutex_enter(&ptgt->tgt_mutex);
2650
2651 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2652 mutex_exit(&ptgt->tgt_mutex);
2653 fscsi->scsi_fc_status = xport_retval =
2654 fc_ulp_transport(pptr->port_fp_handle,
2655 fpkt);
2656 if (fscsi->scsi_fc_status != FC_SUCCESS) {
2657 ret = EIO;
2658 }
2659 } else {
2660 mutex_exit(&ptgt->tgt_mutex);
2661 ret = EBUSY;
2662 }
2663 }
2664 }
2665
2666 /*
2667 * Wait for completion only if fc_ulp_transport was called and it
2668 * returned a success. This is the only time callback will happen.
2669 * Otherwise, there is no point in waiting
2670 */
2671 if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2672 ret = fcp_ipkt_sema_wait(icmd);
2673 }
2674
2675 /*
2676 * Copy data to IOCTL data structures
2677 */
2678 rsp = NULL;
2679 if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2680 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2681
2682 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2683 fcp_log(CE_WARN, pptr->port_dip,
2684 "!SCSI command to d_id=0x%x lun=0x%x"
2685 " failed, Bad FCP response values:"
2686 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2687 " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2688 ptgt->tgt_d_id, plun->lun_num,
2689 rsp->reserved_0, rsp->reserved_1,
2690 rsp->fcp_u.fcp_status.reserved_0,
2691 rsp->fcp_u.fcp_status.reserved_1,
2692 rsp->fcp_response_len, rsp->fcp_sense_len);
2693
2694 ret = EIO;
2695 }
2696 }
2697
2698 if ((ret == 0) && (rsp != NULL)) {
2699 /*
2700 * Calc response lengths
2701 */
2702 sense_len = 0;
2703 info_len = 0;
2704
2705 if (rsp->fcp_u.fcp_status.rsp_len_set) {
2706 info_len = rsp->fcp_response_len;
2707 }
2708
2709 rsp_info = (struct fcp_rsp_info *)
2710 ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2711
2712 /*
2713 * Get SCSI status
2714 */
2715 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2716 /*
2717 * If a lun was just added or removed and the next command
2718 * comes through this interface, we need to capture the check
2719 * condition so we can discover the new topology.
2720 */
2721 if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2722 rsp->fcp_u.fcp_status.sense_len_set) {
2723 sense_len = rsp->fcp_sense_len;
2724 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len);
2725 sense_to = (struct scsi_extended_sense *)rsp_sense;
2726 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2727 (FCP_SENSE_NO_LUN(sense_to))) {
2728 reconfig_lun = TRUE;
2729 }
2730 }
2731
2732 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2733 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2734 if (reconfig_lun == FALSE) {
2735 reconfig_status =
2736 fcp_is_reconfig_needed(ptgt, fpkt);
2737 }
2738
2739 if ((reconfig_lun == TRUE) ||
2740 (reconfig_status == TRUE)) {
2741 mutex_enter(&ptgt->tgt_mutex);
2742 if (ptgt->tgt_tid == NULL) {
2743 /*
2744 * Either we've been notified the
2745 * REPORT_LUN data has changed, or
2746 * we've determined on our own that
2747 * we're out of date. Kick off
2748 * rediscovery.
2749 */
2750 tid = timeout(fcp_reconfigure_luns,
2751 (caddr_t)ptgt, drv_usectohz(1));
2752
2753 ptgt->tgt_tid = tid;
2754 ptgt->tgt_state |= FCP_TGT_BUSY;
2755 ret = EBUSY;
2756 reconfig_pending = TRUE;
2757 }
2758 mutex_exit(&ptgt->tgt_mutex);
2759 }
2760 }
2761
2762 /*
2763 * Calc residuals and buffer lengths
2764 */
2765
2766 if (ret == 0) {
2767 buf_len = fscsi->scsi_buflen;
2768 fscsi->scsi_bufresid = 0;
2769 if (rsp->fcp_u.fcp_status.resid_under) {
2770 if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2771 fscsi->scsi_bufresid = rsp->fcp_resid;
2772 } else {
2773 cmn_err(CE_WARN, "fcp: bad residue %x "
2774 "for txfer len %x", rsp->fcp_resid,
2775 fscsi->scsi_buflen);
2776 fscsi->scsi_bufresid =
2777 fscsi->scsi_buflen;
2778 }
2779 buf_len -= fscsi->scsi_bufresid;
2780 }
2781 if (rsp->fcp_u.fcp_status.resid_over) {
2782 fscsi->scsi_bufresid = -rsp->fcp_resid;
2783 }
2784
2785 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len;
2786 if (fscsi->scsi_rqlen < sense_len) {
2787 sense_len = fscsi->scsi_rqlen;
2788 }
2789
2790 fscsi->scsi_fc_rspcode = 0;
2791 if (rsp->fcp_u.fcp_status.rsp_len_set) {
2792 fscsi->scsi_fc_rspcode = rsp_info->rsp_code;
2793 }
2794 fscsi->scsi_pkt_state = fpkt->pkt_state;
2795 fscsi->scsi_pkt_action = fpkt->pkt_action;
2796 fscsi->scsi_pkt_reason = fpkt->pkt_reason;
2797
2798 /*
2799 * Copy data and request sense
2800 *
2801 * Data must be copied by using the FCP_CP_IN macro.
2802 * This will ensure the proper byte order since the data
2803 * is being copied directly from the memory mapped
2804 * device register.
2805 *
2806 * The response (and request sense) will be in the
2807 * correct byte order. No special copy is necessary.
2808 */
2809
2810 if (buf_len) {
2811 FCP_CP_IN(fpkt->pkt_data,
2812 fscsi->scsi_bufaddr,
2813 fpkt->pkt_data_acc,
2814 buf_len);
2815 }
2816 bcopy((void *)rsp_sense,
2817 (void *)fscsi->scsi_rqbufaddr,
2818 sense_len);
2819 }
2820 }
2821
2822 /*
2823 * Cleanup transport data structures if icmd was alloc-ed
2824 * So, cleanup happens in the same thread that icmd was alloc-ed
2825 */
2826 if (icmd != NULL) {
2827 fcp_ipkt_sema_cleanup(icmd);
2828 }
2829
2830 /* restore pm busy/idle status */
2831 if (port_busy) {
2832 fc_ulp_idle_port(pptr->port_fp_handle);
2833 }
2834
2835 /*
2836 * Cleanup target. if a reconfig is pending, don't clear the BUSY
2837 * flag, it'll be cleared when the reconfig is complete.
2838 */
2839 if ((ptgt != NULL) && !reconfig_pending) {
2840 /*
2841 * If target was created,
2842 */
2843 if (target_created) {
2844 mutex_enter(&ptgt->tgt_mutex);
2845 ptgt->tgt_state &= ~FCP_TGT_BUSY;
2846 mutex_exit(&ptgt->tgt_mutex);
2847 } else {
2848 /*
2849 * De-mark target as busy
2850 */
2851 mutex_enter(&ptgt->tgt_mutex);
2852 ptgt->tgt_state &= ~FCP_TGT_BUSY;
2853 mutex_exit(&ptgt->tgt_mutex);
2854 }
2855 }
2856 return (ret);
2857 }
2858
2859
2860 static int
fcp_is_reconfig_needed(struct fcp_tgt * ptgt,fc_packet_t * fpkt)2861 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2862 fc_packet_t *fpkt)
2863 {
2864 uchar_t *lun_string;
2865 uint16_t lun_num, i;
2866 int num_luns;
2867 int actual_luns;
2868 int num_masked_luns;
2869 int lun_buflen;
2870 struct fcp_lun *plun = NULL;
2871 struct fcp_reportlun_resp *report_lun;
2872 uint8_t reconfig_needed = FALSE;
2873 uint8_t lun_exists = FALSE;
2874 fcp_port_t *pptr = ptgt->tgt_port;
2875
2876 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2877
2878 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2879 fpkt->pkt_datalen);
2880
2881 /* get number of luns (which is supplied as LUNS * 8) */
2882 num_luns = BE_32(report_lun->num_lun) >> 3;
2883
2884 /*
2885 * Figure out exactly how many lun strings our response buffer
2886 * can hold.
2887 */
2888 lun_buflen = (fpkt->pkt_datalen -
2889 2 * sizeof (uint32_t)) / sizeof (longlong_t);
2890
2891 /*
2892 * Is our response buffer full or not? We don't want to
2893 * potentially walk beyond the number of luns we have.
2894 */
2895 if (num_luns <= lun_buflen) {
2896 actual_luns = num_luns;
2897 } else {
2898 actual_luns = lun_buflen;
2899 }
2900
2901 mutex_enter(&ptgt->tgt_mutex);
2902
2903 /* Scan each lun to see if we have masked it. */
2904 num_masked_luns = 0;
2905 if (fcp_lun_blacklist != NULL) {
2906 for (i = 0; i < actual_luns; i++) {
2907 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2908 switch (lun_string[0] & 0xC0) {
2909 case FCP_LUN_ADDRESSING:
2910 case FCP_PD_ADDRESSING:
2911 case FCP_VOLUME_ADDRESSING:
2912 lun_num = ((lun_string[0] & 0x3F) << 8)
2913 | lun_string[1];
2914 if (fcp_should_mask(&ptgt->tgt_port_wwn,
2915 lun_num) == TRUE) {
2916 num_masked_luns++;
2917 }
2918 break;
2919 default:
2920 break;
2921 }
2922 }
2923 }
2924
2925 /*
2926 * The quick and easy check. If the number of LUNs reported
2927 * doesn't match the number we currently know about, we need
2928 * to reconfigure.
2929 */
2930 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2931 mutex_exit(&ptgt->tgt_mutex);
2932 kmem_free(report_lun, fpkt->pkt_datalen);
2933 return (TRUE);
2934 }
2935
2936 /*
2937 * If the quick and easy check doesn't turn up anything, we walk
2938 * the list of luns from the REPORT_LUN response and look for
2939 * any luns we don't know about. If we find one, we know we need
2940 * to reconfigure. We will skip LUNs that are masked because of the
2941 * blacklist.
2942 */
2943 for (i = 0; i < actual_luns; i++) {
2944 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2945 lun_exists = FALSE;
2946 switch (lun_string[0] & 0xC0) {
2947 case FCP_LUN_ADDRESSING:
2948 case FCP_PD_ADDRESSING:
2949 case FCP_VOLUME_ADDRESSING:
2950 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2951
2952 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2953 &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2954 lun_exists = TRUE;
2955 break;
2956 }
2957
2958 for (plun = ptgt->tgt_lun; plun;
2959 plun = plun->lun_next) {
2960 if (plun->lun_num == lun_num) {
2961 lun_exists = TRUE;
2962 break;
2963 }
2964 }
2965 break;
2966 default:
2967 break;
2968 }
2969
2970 if (lun_exists == FALSE) {
2971 reconfig_needed = TRUE;
2972 break;
2973 }
2974 }
2975
2976 mutex_exit(&ptgt->tgt_mutex);
2977 kmem_free(report_lun, fpkt->pkt_datalen);
2978
2979 return (reconfig_needed);
2980 }
2981
2982 /*
2983 * This function is called by fcp_handle_page83 and uses inquiry response data
2984 * stored in plun->lun_inq to determine whether or not a device is a member of
2985 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2986 * otherwise 1.
2987 */
2988 static int
fcp_symmetric_device_probe(struct fcp_lun * plun)2989 fcp_symmetric_device_probe(struct fcp_lun *plun)
2990 {
2991 struct scsi_inquiry *stdinq = &plun->lun_inq;
2992 char *devidptr;
2993 int i, len;
2994
2995 for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2996 devidptr = fcp_symmetric_disk_table[i];
2997 len = (int)strlen(devidptr);
2998
2999 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3000 return (0);
3001 }
3002 }
3003 return (1);
3004 }
3005
3006
3007 /*
3008 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3009 * It basically returns the current count of # of state change callbacks
3010 * i.e the value of tgt_change_cnt.
3011 *
3012 * INPUT:
3013 * fcp_ioctl.fp_minor -> The minor # of the fp port
3014 * fcp_ioctl.listlen -> 1
3015 * fcp_ioctl.list -> Pointer to a 32 bit integer
3016 */
3017 /*ARGSUSED2*/
3018 static int
fcp_get_statec_count(struct fcp_ioctl * data,int mode,int * rval)3019 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3020 {
3021 int ret;
3022 uint32_t link_cnt;
3023 struct fcp_ioctl fioctl;
3024 struct fcp_port *pptr = NULL;
3025
3026 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3027 &pptr)) != 0) {
3028 return (ret);
3029 }
3030
3031 ASSERT(pptr != NULL);
3032
3033 if (fioctl.listlen != 1) {
3034 return (EINVAL);
3035 }
3036
3037 mutex_enter(&pptr->port_mutex);
3038 if (pptr->port_state & FCP_STATE_OFFLINE) {
3039 mutex_exit(&pptr->port_mutex);
3040 return (ENXIO);
3041 }
3042
3043 /*
3044 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3045 * When the fcp initially attaches to the port and there are nothing
3046 * hanging out of the port or if there was a repeat offline state change
3047 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3048 * In the latter case, port_tmp_cnt will be non-zero and that is how we
3049 * will differentiate the 2 cases.
3050 */
3051 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3052 mutex_exit(&pptr->port_mutex);
3053 return (ENXIO);
3054 }
3055
3056 link_cnt = pptr->port_link_cnt;
3057 mutex_exit(&pptr->port_mutex);
3058
3059 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3060 return (EFAULT);
3061 }
3062
3063 #ifdef _MULTI_DATAMODEL
3064 switch (ddi_model_convert_from(mode & FMODELS)) {
3065 case DDI_MODEL_ILP32: {
3066 struct fcp32_ioctl f32_ioctl;
3067
3068 f32_ioctl.fp_minor = fioctl.fp_minor;
3069 f32_ioctl.listlen = fioctl.listlen;
3070 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3071 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3072 sizeof (struct fcp32_ioctl), mode)) {
3073 return (EFAULT);
3074 }
3075 break;
3076 }
3077 case DDI_MODEL_NONE:
3078 if (ddi_copyout((void *)&fioctl, (void *)data,
3079 sizeof (struct fcp_ioctl), mode)) {
3080 return (EFAULT);
3081 }
3082 break;
3083 }
3084 #else /* _MULTI_DATAMODEL */
3085
3086 if (ddi_copyout((void *)&fioctl, (void *)data,
3087 sizeof (struct fcp_ioctl), mode)) {
3088 return (EFAULT);
3089 }
3090 #endif /* _MULTI_DATAMODEL */
3091
3092 return (0);
3093 }
3094
3095 /*
3096 * This function copies the fcp_ioctl structure passed in from user land
3097 * into kernel land. Handles 32 bit applications.
3098 */
3099 /*ARGSUSED*/
3100 static int
fcp_copyin_fcp_ioctl_data(struct fcp_ioctl * data,int mode,int * rval,struct fcp_ioctl * fioctl,struct fcp_port ** pptr)3101 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3102 struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3103 {
3104 struct fcp_port *t_pptr;
3105
3106 #ifdef _MULTI_DATAMODEL
3107 switch (ddi_model_convert_from(mode & FMODELS)) {
3108 case DDI_MODEL_ILP32: {
3109 struct fcp32_ioctl f32_ioctl;
3110
3111 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3112 sizeof (struct fcp32_ioctl), mode)) {
3113 return (EFAULT);
3114 }
3115 fioctl->fp_minor = f32_ioctl.fp_minor;
3116 fioctl->listlen = f32_ioctl.listlen;
3117 fioctl->list = (caddr_t)(long)f32_ioctl.list;
3118 break;
3119 }
3120 case DDI_MODEL_NONE:
3121 if (ddi_copyin((void *)data, (void *)fioctl,
3122 sizeof (struct fcp_ioctl), mode)) {
3123 return (EFAULT);
3124 }
3125 break;
3126 }
3127
3128 #else /* _MULTI_DATAMODEL */
3129 if (ddi_copyin((void *)data, (void *)fioctl,
3130 sizeof (struct fcp_ioctl), mode)) {
3131 return (EFAULT);
3132 }
3133 #endif /* _MULTI_DATAMODEL */
3134
3135 /*
3136 * Right now we can assume that the minor number matches with
3137 * this instance of fp. If this changes we will need to
3138 * revisit this logic.
3139 */
3140 mutex_enter(&fcp_global_mutex);
3141 t_pptr = fcp_port_head;
3142 while (t_pptr) {
3143 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3144 break;
3145 } else {
3146 t_pptr = t_pptr->port_next;
3147 }
3148 }
3149 *pptr = t_pptr;
3150 mutex_exit(&fcp_global_mutex);
3151 if (t_pptr == NULL) {
3152 return (ENXIO);
3153 }
3154
3155 return (0);
3156 }
3157
3158 /*
3159 * Function: fcp_port_create_tgt
3160 *
3161 * Description: As the name suggest this function creates the target context
3162 * specified by the the WWN provided by the caller. If the
3163 * creation goes well and the target is known by fp/fctl a PLOGI
3164 * followed by a PRLI are issued.
3165 *
3166 * Argument: pptr fcp port structure
3167 * pwwn WWN of the target
3168 * ret_val Address of the return code. It could be:
3169 * EIO, ENOMEM or 0.
3170 * fc_status PLOGI or PRLI status completion
3171 * fc_pkt_state PLOGI or PRLI state completion
3172 * fc_pkt_reason PLOGI or PRLI reason completion
3173 * fc_pkt_action PLOGI or PRLI action completion
3174 *
3175 * Return Value: NULL if it failed
3176 * Target structure address if it succeeds
3177 */
3178 static struct fcp_tgt *
fcp_port_create_tgt(struct fcp_port * pptr,la_wwn_t * pwwn,int * ret_val,int * fc_status,int * fc_pkt_state,int * fc_pkt_reason,int * fc_pkt_action)3179 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3180 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3181 {
3182 struct fcp_tgt *ptgt = NULL;
3183 fc_portmap_t devlist;
3184 int lcount;
3185 int error;
3186
3187 *ret_val = 0;
3188
3189 /*
3190 * Check FC port device & get port map
3191 */
3192 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3193 &error, 1) == NULL) {
3194 *ret_val = EIO;
3195 } else {
3196 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3197 &devlist) != FC_SUCCESS) {
3198 *ret_val = EIO;
3199 }
3200 }
3201
3202 /* Set port map flags */
3203 devlist.map_type = PORT_DEVICE_USER_CREATE;
3204
3205 /* Allocate target */
3206 if (*ret_val == 0) {
3207 lcount = pptr->port_link_cnt;
3208 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3209 if (ptgt == NULL) {
3210 fcp_log(CE_WARN, pptr->port_dip,
3211 "!FC target allocation failed");
3212 *ret_val = ENOMEM;
3213 } else {
3214 /* Setup target */
3215 mutex_enter(&ptgt->tgt_mutex);
3216
3217 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE;
3218 ptgt->tgt_tmp_cnt = 1;
3219 ptgt->tgt_d_id = devlist.map_did.port_id;
3220 ptgt->tgt_hard_addr =
3221 devlist.map_hard_addr.hard_addr;
3222 ptgt->tgt_pd_handle = devlist.map_pd;
3223 ptgt->tgt_fca_dev = NULL;
3224
3225 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3226 FC_WWN_SIZE);
3227 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3228 FC_WWN_SIZE);
3229
3230 mutex_exit(&ptgt->tgt_mutex);
3231 }
3232 }
3233
3234 /* Release global mutex for PLOGI and PRLI */
3235 mutex_exit(&fcp_global_mutex);
3236
3237 /* Send PLOGI (If necessary) */
3238 if (*ret_val == 0) {
3239 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3240 fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3241 }
3242
3243 /* Send PRLI (If necessary) */
3244 if (*ret_val == 0) {
3245 *ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3246 fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3247 }
3248
3249 mutex_enter(&fcp_global_mutex);
3250
3251 return (ptgt);
3252 }
3253
3254 /*
3255 * Function: fcp_tgt_send_plogi
3256 *
3257 * Description: This function sends a PLOGI to the target specified by the
3258 * caller and waits till it completes.
3259 *
3260 * Argument: ptgt Target to send the plogi to.
3261 * fc_status Status returned by fp/fctl in the PLOGI request.
3262 * fc_pkt_state State returned by fp/fctl in the PLOGI request.
3263 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request.
3264 * fc_pkt_action Action returned by fp/fctl in the PLOGI request.
3265 *
3266 * Return Value: 0
3267 * ENOMEM
3268 * EIO
3269 *
3270 * Context: User context.
3271 */
3272 static int
fcp_tgt_send_plogi(struct fcp_tgt * ptgt,int * fc_status,int * fc_pkt_state,int * fc_pkt_reason,int * fc_pkt_action)3273 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3274 int *fc_pkt_reason, int *fc_pkt_action)
3275 {
3276 struct fcp_port *pptr;
3277 struct fcp_ipkt *icmd;
3278 struct fc_packet *fpkt;
3279 fc_frame_hdr_t *hp;
3280 struct la_els_logi logi;
3281 int tcount;
3282 int lcount;
3283 int ret, login_retval = ~FC_SUCCESS;
3284
3285 ret = 0;
3286
3287 pptr = ptgt->tgt_port;
3288
3289 lcount = pptr->port_link_cnt;
3290 tcount = ptgt->tgt_change_cnt;
3291
3292 /* Alloc internal packet */
3293 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3294 sizeof (la_els_logi_t), 0,
3295 pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3296 lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3297
3298 if (icmd == NULL) {
3299 ret = ENOMEM;
3300 } else {
3301 /*
3302 * Setup internal packet as sema sync
3303 */
3304 fcp_ipkt_sema_init(icmd);
3305
3306 /*
3307 * Setup internal packet (icmd)
3308 */
3309 icmd->ipkt_lun = NULL;
3310 icmd->ipkt_restart = 0;
3311 icmd->ipkt_retries = 0;
3312 icmd->ipkt_opcode = LA_ELS_PLOGI;
3313
3314 /*
3315 * Setup fc_packet
3316 */
3317 fpkt = icmd->ipkt_fpkt;
3318
3319 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
3320 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
3321 fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
3322
3323 /*
3324 * Setup FC frame header
3325 */
3326 hp = &fpkt->pkt_cmd_fhdr;
3327
3328 hp->s_id = pptr->port_id; /* source ID */
3329 hp->d_id = ptgt->tgt_d_id; /* dest ID */
3330 hp->r_ctl = R_CTL_ELS_REQ;
3331 hp->type = FC_TYPE_EXTENDED_LS;
3332 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3333 hp->seq_id = 0;
3334 hp->rsvd = 0;
3335 hp->df_ctl = 0;
3336 hp->seq_cnt = 0;
3337 hp->ox_id = 0xffff; /* i.e. none */
3338 hp->rx_id = 0xffff; /* i.e. none */
3339 hp->ro = 0;
3340
3341 /*
3342 * Setup PLOGI
3343 */
3344 bzero(&logi, sizeof (struct la_els_logi));
3345 logi.ls_code.ls_code = LA_ELS_PLOGI;
3346
3347 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3348 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3349
3350 /*
3351 * Send PLOGI
3352 */
3353 *fc_status = login_retval =
3354 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3355 if (*fc_status != FC_SUCCESS) {
3356 ret = EIO;
3357 }
3358 }
3359
3360 /*
3361 * Wait for completion
3362 */
3363 if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3364 ret = fcp_ipkt_sema_wait(icmd);
3365
3366 *fc_pkt_state = fpkt->pkt_state;
3367 *fc_pkt_reason = fpkt->pkt_reason;
3368 *fc_pkt_action = fpkt->pkt_action;
3369 }
3370
3371 /*
3372 * Cleanup transport data structures if icmd was alloc-ed AND if there
3373 * is going to be no callback (i.e if fc_ulp_login() failed).
3374 * Otherwise, cleanup happens in callback routine.
3375 */
3376 if (icmd != NULL) {
3377 fcp_ipkt_sema_cleanup(icmd);
3378 }
3379
3380 return (ret);
3381 }
3382
3383 /*
3384 * Function: fcp_tgt_send_prli
3385 *
3386 * Description: Does nothing as of today.
3387 *
3388 * Argument: ptgt Target to send the prli to.
3389 * fc_status Status returned by fp/fctl in the PRLI request.
3390 * fc_pkt_state State returned by fp/fctl in the PRLI request.
3391 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request.
3392 * fc_pkt_action Action returned by fp/fctl in the PRLI request.
3393 *
3394 * Return Value: 0
3395 */
3396 /*ARGSUSED*/
3397 static int
fcp_tgt_send_prli(struct fcp_tgt * ptgt,int * fc_status,int * fc_pkt_state,int * fc_pkt_reason,int * fc_pkt_action)3398 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3399 int *fc_pkt_reason, int *fc_pkt_action)
3400 {
3401 return (0);
3402 }
3403
3404 /*
3405 * Function: fcp_ipkt_sema_init
3406 *
3407 * Description: Initializes the semaphore contained in the internal packet.
3408 *
3409 * Argument: icmd Internal packet the semaphore of which must be
3410 * initialized.
3411 *
3412 * Return Value: None
3413 *
3414 * Context: User context only.
3415 */
3416 static void
fcp_ipkt_sema_init(struct fcp_ipkt * icmd)3417 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3418 {
3419 struct fc_packet *fpkt;
3420
3421 fpkt = icmd->ipkt_fpkt;
3422
3423 /* Create semaphore for sync */
3424 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3425
3426 /* Setup the completion callback */
3427 fpkt->pkt_comp = fcp_ipkt_sema_callback;
3428 }
3429
3430 /*
3431 * Function: fcp_ipkt_sema_wait
3432 *
3433 * Description: Wait on the semaphore embedded in the internal packet. The
3434 * semaphore is released in the callback.
3435 *
3436 * Argument: icmd Internal packet to wait on for completion.
3437 *
3438 * Return Value: 0
3439 * EIO
3440 * EBUSY
3441 * EAGAIN
3442 *
3443 * Context: User context only.
3444 *
3445 * This function does a conversion between the field pkt_state of the fc_packet
3446 * embedded in the internal packet (icmd) and the code it returns.
3447 */
3448 static int
fcp_ipkt_sema_wait(struct fcp_ipkt * icmd)3449 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3450 {
3451 struct fc_packet *fpkt;
3452 int ret;
3453
3454 ret = EIO;
3455 fpkt = icmd->ipkt_fpkt;
3456
3457 /*
3458 * Wait on semaphore
3459 */
3460 sema_p(&(icmd->ipkt_sema));
3461
3462 /*
3463 * Check the status of the FC packet
3464 */
3465 switch (fpkt->pkt_state) {
3466 case FC_PKT_SUCCESS:
3467 ret = 0;
3468 break;
3469 case FC_PKT_LOCAL_RJT:
3470 switch (fpkt->pkt_reason) {
3471 case FC_REASON_SEQ_TIMEOUT:
3472 case FC_REASON_RX_BUF_TIMEOUT:
3473 ret = EAGAIN;
3474 break;
3475 case FC_REASON_PKT_BUSY:
3476 ret = EBUSY;
3477 break;
3478 }
3479 break;
3480 case FC_PKT_TIMEOUT:
3481 ret = EAGAIN;
3482 break;
3483 case FC_PKT_LOCAL_BSY:
3484 case FC_PKT_TRAN_BSY:
3485 case FC_PKT_NPORT_BSY:
3486 case FC_PKT_FABRIC_BSY:
3487 ret = EBUSY;
3488 break;
3489 case FC_PKT_LS_RJT:
3490 case FC_PKT_BA_RJT:
3491 switch (fpkt->pkt_reason) {
3492 case FC_REASON_LOGICAL_BSY:
3493 ret = EBUSY;
3494 break;
3495 }
3496 break;
3497 case FC_PKT_FS_RJT:
3498 switch (fpkt->pkt_reason) {
3499 case FC_REASON_FS_LOGICAL_BUSY:
3500 ret = EBUSY;
3501 break;
3502 }
3503 break;
3504 }
3505
3506 return (ret);
3507 }
3508
3509 /*
3510 * Function: fcp_ipkt_sema_callback
3511 *
3512 * Description: Registered as the completion callback function for the FC
3513 * transport when the ipkt semaphore is used for sync. This will
3514 * cleanup the used data structures, if necessary and wake up
3515 * the user thread to complete the transaction.
3516 *
3517 * Argument: fpkt FC packet (points to the icmd)
3518 *
3519 * Return Value: None
3520 *
3521 * Context: User context only
3522 */
3523 static void
fcp_ipkt_sema_callback(struct fc_packet * fpkt)3524 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3525 {
3526 struct fcp_ipkt *icmd;
3527
3528 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3529
3530 /*
3531 * Wake up user thread
3532 */
3533 sema_v(&(icmd->ipkt_sema));
3534 }
3535
3536 /*
3537 * Function: fcp_ipkt_sema_cleanup
3538 *
3539 * Description: Called to cleanup (if necessary) the data structures used
3540 * when ipkt sema is used for sync. This function will detect
3541 * whether the caller is the last thread (via counter) and
3542 * cleanup only if necessary.
3543 *
3544 * Argument: icmd Internal command packet
3545 *
3546 * Return Value: None
3547 *
3548 * Context: User context only
3549 */
3550 static void
fcp_ipkt_sema_cleanup(struct fcp_ipkt * icmd)3551 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3552 {
3553 struct fcp_tgt *ptgt;
3554 struct fcp_port *pptr;
3555
3556 ptgt = icmd->ipkt_tgt;
3557 pptr = icmd->ipkt_port;
3558
3559 /*
3560 * Acquire data structure
3561 */
3562 mutex_enter(&ptgt->tgt_mutex);
3563
3564 /*
3565 * Destroy semaphore
3566 */
3567 sema_destroy(&(icmd->ipkt_sema));
3568
3569 /*
3570 * Cleanup internal packet
3571 */
3572 mutex_exit(&ptgt->tgt_mutex);
3573 fcp_icmd_free(pptr, icmd);
3574 }
3575
3576 /*
3577 * Function: fcp_port_attach
3578 *
3579 * Description: Called by the transport framework to resume, suspend or
3580 * attach a new port.
3581 *
3582 * Argument: ulph Port handle
3583 * *pinfo Port information
3584 * cmd Command
3585 * s_id Port ID
3586 *
3587 * Return Value: FC_FAILURE or FC_SUCCESS
3588 */
3589 /*ARGSUSED*/
3590 static int
fcp_port_attach(opaque_t ulph,fc_ulp_port_info_t * pinfo,fc_attach_cmd_t cmd,uint32_t s_id)3591 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3592 fc_attach_cmd_t cmd, uint32_t s_id)
3593 {
3594 int instance;
3595 int res = FC_FAILURE; /* default result */
3596
3597 ASSERT(pinfo != NULL);
3598
3599 instance = ddi_get_instance(pinfo->port_dip);
3600
3601 switch (cmd) {
3602 case FC_CMD_ATTACH:
3603 /*
3604 * this port instance attaching for the first time (or after
3605 * being detached before)
3606 */
3607 if (fcp_handle_port_attach(ulph, pinfo, s_id,
3608 instance) == DDI_SUCCESS) {
3609 res = FC_SUCCESS;
3610 } else {
3611 ASSERT(ddi_get_soft_state(fcp_softstate,
3612 instance) == NULL);
3613 }
3614 break;
3615
3616 case FC_CMD_RESUME:
3617 case FC_CMD_POWER_UP:
3618 /*
3619 * this port instance was attached and the suspended and
3620 * will now be resumed
3621 */
3622 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3623 instance) == DDI_SUCCESS) {
3624 res = FC_SUCCESS;
3625 }
3626 break;
3627
3628 default:
3629 /* shouldn't happen */
3630 FCP_TRACE(fcp_logq, "fcp",
3631 fcp_trace, FCP_BUF_LEVEL_2, 0,
3632 "port_attach: unknown cmdcommand: %d", cmd);
3633 break;
3634 }
3635
3636 /* return result */
3637 FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3638 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3639
3640 return (res);
3641 }
3642
3643
3644 /*
3645 * detach or suspend this port instance
3646 *
3647 * acquires and releases the global mutex
3648 *
3649 * acquires and releases the mutex for this port
3650 *
3651 * acquires and releases the hotplug mutex for this port
3652 */
3653 /*ARGSUSED*/
3654 static int
fcp_port_detach(opaque_t ulph,fc_ulp_port_info_t * info,fc_detach_cmd_t cmd)3655 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3656 fc_detach_cmd_t cmd)
3657 {
3658 int flag;
3659 int instance;
3660 struct fcp_port *pptr;
3661
3662 instance = ddi_get_instance(info->port_dip);
3663 pptr = ddi_get_soft_state(fcp_softstate, instance);
3664
3665 switch (cmd) {
3666 case FC_CMD_SUSPEND:
3667 FCP_DTRACE(fcp_logq, "fcp",
3668 fcp_trace, FCP_BUF_LEVEL_8, 0,
3669 "port suspend called for port %d", instance);
3670 flag = FCP_STATE_SUSPENDED;
3671 break;
3672
3673 case FC_CMD_POWER_DOWN:
3674 FCP_DTRACE(fcp_logq, "fcp",
3675 fcp_trace, FCP_BUF_LEVEL_8, 0,
3676 "port power down called for port %d", instance);
3677 flag = FCP_STATE_POWER_DOWN;
3678 break;
3679
3680 case FC_CMD_DETACH:
3681 FCP_DTRACE(fcp_logq, "fcp",
3682 fcp_trace, FCP_BUF_LEVEL_8, 0,
3683 "port detach called for port %d", instance);
3684 flag = FCP_STATE_DETACHING;
3685 break;
3686
3687 default:
3688 /* shouldn't happen */
3689 return (FC_FAILURE);
3690 }
3691 FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3692 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3693
3694 return (fcp_handle_port_detach(pptr, flag, instance));
3695 }
3696
3697
3698 /*
3699 * called for ioctls on the transport's devctl interface, and the transport
3700 * has passed it to us
3701 *
3702 * this will only be called for device control ioctls (i.e. hotplugging stuff)
3703 *
3704 * return FC_SUCCESS if we decide to claim the ioctl,
3705 * else return FC_UNCLAIMED
3706 *
3707 * *rval is set iff we decide to claim the ioctl
3708 */
3709 /*ARGSUSED*/
3710 static int
fcp_port_ioctl(opaque_t ulph,opaque_t port_handle,dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval,uint32_t claimed)3711 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3712 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3713 {
3714 int retval = FC_UNCLAIMED; /* return value */
3715 struct fcp_port *pptr = NULL; /* our soft state */
3716 struct devctl_iocdata *dcp = NULL; /* for devctl */
3717 dev_info_t *cdip;
3718 mdi_pathinfo_t *pip = NULL;
3719 char *ndi_nm; /* NDI name */
3720 char *ndi_addr; /* NDI addr */
3721 int is_mpxio, circ;
3722 int devi_entered = 0;
3723 clock_t end_time;
3724
3725 ASSERT(rval != NULL);
3726
3727 FCP_DTRACE(fcp_logq, "fcp",
3728 fcp_trace, FCP_BUF_LEVEL_8, 0,
3729 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3730
3731 /* if already claimed then forget it */
3732 if (claimed) {
3733 /*
3734 * for now, if this ioctl has already been claimed, then
3735 * we just ignore it
3736 */
3737 return (retval);
3738 }
3739
3740 /* get our port info */
3741 if ((pptr = fcp_get_port(port_handle)) == NULL) {
3742 fcp_log(CE_WARN, NULL,
3743 "!fcp:Invalid port handle handle in ioctl");
3744 *rval = ENXIO;
3745 return (retval);
3746 }
3747 is_mpxio = pptr->port_mpxio;
3748
3749 switch (cmd) {
3750 case DEVCTL_BUS_GETSTATE:
3751 case DEVCTL_BUS_QUIESCE:
3752 case DEVCTL_BUS_UNQUIESCE:
3753 case DEVCTL_BUS_RESET:
3754 case DEVCTL_BUS_RESETALL:
3755
3756 case DEVCTL_BUS_DEV_CREATE:
3757 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3758 return (retval);
3759 }
3760 break;
3761
3762 case DEVCTL_DEVICE_GETSTATE:
3763 case DEVCTL_DEVICE_OFFLINE:
3764 case DEVCTL_DEVICE_ONLINE:
3765 case DEVCTL_DEVICE_REMOVE:
3766 case DEVCTL_DEVICE_RESET:
3767 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3768 return (retval);
3769 }
3770
3771 ASSERT(dcp != NULL);
3772
3773 /* ensure we have a name and address */
3774 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3775 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3776 FCP_TRACE(fcp_logq, pptr->port_instbuf,
3777 fcp_trace, FCP_BUF_LEVEL_2, 0,
3778 "ioctl: can't get name (%s) or addr (%s)",
3779 ndi_nm ? ndi_nm : "<null ptr>",
3780 ndi_addr ? ndi_addr : "<null ptr>");
3781 ndi_dc_freehdl(dcp);
3782 return (retval);
3783 }
3784
3785
3786 /* get our child's DIP */
3787 ASSERT(pptr != NULL);
3788 if (is_mpxio) {
3789 mdi_devi_enter(pptr->port_dip, &circ);
3790 } else {
3791 ndi_devi_enter(pptr->port_dip, &circ);
3792 }
3793 devi_entered = 1;
3794
3795 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3796 ndi_addr)) == NULL) {
3797 /* Look for virtually enumerated devices. */
3798 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3799 if (pip == NULL ||
3800 ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3801 *rval = ENXIO;
3802 goto out;
3803 }
3804 }
3805 break;
3806
3807 default:
3808 *rval = ENOTTY;
3809 return (retval);
3810 }
3811
3812 /* this ioctl is ours -- process it */
3813
3814 retval = FC_SUCCESS; /* just means we claim the ioctl */
3815
3816 /* we assume it will be a success; else we'll set error value */
3817 *rval = 0;
3818
3819
3820 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3821 fcp_trace, FCP_BUF_LEVEL_8, 0,
3822 "ioctl: claiming this one");
3823
3824 /* handle ioctls now */
3825 switch (cmd) {
3826 case DEVCTL_DEVICE_GETSTATE:
3827 ASSERT(cdip != NULL);
3828 ASSERT(dcp != NULL);
3829 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3830 *rval = EFAULT;
3831 }
3832 break;
3833
3834 case DEVCTL_DEVICE_REMOVE:
3835 case DEVCTL_DEVICE_OFFLINE: {
3836 int flag = 0;
3837 int lcount;
3838 int tcount;
3839 struct fcp_pkt *head = NULL;
3840 struct fcp_lun *plun;
3841 child_info_t *cip = CIP(cdip);
3842 int all = 1;
3843 struct fcp_lun *tplun;
3844 struct fcp_tgt *ptgt;
3845
3846 ASSERT(pptr != NULL);
3847 ASSERT(cdip != NULL);
3848
3849 mutex_enter(&pptr->port_mutex);
3850 if (pip != NULL) {
3851 cip = CIP(pip);
3852 }
3853 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3854 mutex_exit(&pptr->port_mutex);
3855 *rval = ENXIO;
3856 break;
3857 }
3858
3859 head = fcp_scan_commands(plun);
3860 if (head != NULL) {
3861 fcp_abort_commands(head, LUN_PORT);
3862 }
3863 lcount = pptr->port_link_cnt;
3864 tcount = plun->lun_tgt->tgt_change_cnt;
3865 mutex_exit(&pptr->port_mutex);
3866
3867 if (cmd == DEVCTL_DEVICE_REMOVE) {
3868 flag = NDI_DEVI_REMOVE;
3869 }
3870
3871 if (is_mpxio) {
3872 mdi_devi_exit(pptr->port_dip, circ);
3873 } else {
3874 ndi_devi_exit(pptr->port_dip, circ);
3875 }
3876 devi_entered = 0;
3877
3878 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3879 FCP_OFFLINE, lcount, tcount, flag);
3880
3881 if (*rval != NDI_SUCCESS) {
3882 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3883 break;
3884 }
3885
3886 fcp_update_offline_flags(plun);
3887
3888 ptgt = plun->lun_tgt;
3889 mutex_enter(&ptgt->tgt_mutex);
3890 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3891 tplun->lun_next) {
3892 mutex_enter(&tplun->lun_mutex);
3893 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3894 all = 0;
3895 }
3896 mutex_exit(&tplun->lun_mutex);
3897 }
3898
3899 if (all) {
3900 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3901 /*
3902 * The user is unconfiguring/offlining the device.
3903 * If fabric and the auto configuration is set
3904 * then make sure the user is the only one who
3905 * can reconfigure the device.
3906 */
3907 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3908 fcp_enable_auto_configuration) {
3909 ptgt->tgt_manual_config_only = 1;
3910 }
3911 }
3912 mutex_exit(&ptgt->tgt_mutex);
3913 break;
3914 }
3915
3916 case DEVCTL_DEVICE_ONLINE: {
3917 int lcount;
3918 int tcount;
3919 struct fcp_lun *plun;
3920 child_info_t *cip = CIP(cdip);
3921
3922 ASSERT(cdip != NULL);
3923 ASSERT(pptr != NULL);
3924
3925 mutex_enter(&pptr->port_mutex);
3926 if (pip != NULL) {
3927 cip = CIP(pip);
3928 }
3929 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3930 mutex_exit(&pptr->port_mutex);
3931 *rval = ENXIO;
3932 break;
3933 }
3934 lcount = pptr->port_link_cnt;
3935 tcount = plun->lun_tgt->tgt_change_cnt;
3936 mutex_exit(&pptr->port_mutex);
3937
3938 /*
3939 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3940 * to allow the device attach to occur when the device is
3941 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3942 * from the scsi_probe()).
3943 */
3944 mutex_enter(&LUN_TGT->tgt_mutex);
3945 plun->lun_state |= FCP_LUN_ONLINING;
3946 mutex_exit(&LUN_TGT->tgt_mutex);
3947
3948 if (is_mpxio) {
3949 mdi_devi_exit(pptr->port_dip, circ);
3950 } else {
3951 ndi_devi_exit(pptr->port_dip, circ);
3952 }
3953 devi_entered = 0;
3954
3955 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3956 FCP_ONLINE, lcount, tcount, 0);
3957
3958 if (*rval != NDI_SUCCESS) {
3959 /* Reset the FCP_LUN_ONLINING bit */
3960 mutex_enter(&LUN_TGT->tgt_mutex);
3961 plun->lun_state &= ~FCP_LUN_ONLINING;
3962 mutex_exit(&LUN_TGT->tgt_mutex);
3963 *rval = EIO;
3964 break;
3965 }
3966 mutex_enter(&LUN_TGT->tgt_mutex);
3967 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3968 FCP_LUN_ONLINING);
3969 mutex_exit(&LUN_TGT->tgt_mutex);
3970 break;
3971 }
3972
3973 case DEVCTL_BUS_DEV_CREATE: {
3974 uchar_t *bytes = NULL;
3975 uint_t nbytes;
3976 struct fcp_tgt *ptgt = NULL;
3977 struct fcp_lun *plun = NULL;
3978 dev_info_t *useless_dip = NULL;
3979
3980 *rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3981 DEVCTL_CONSTRUCT, &useless_dip);
3982 if (*rval != 0 || useless_dip == NULL) {
3983 break;
3984 }
3985
3986 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3987 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3988 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3989 *rval = EINVAL;
3990 (void) ndi_devi_free(useless_dip);
3991 if (bytes != NULL) {
3992 ddi_prop_free(bytes);
3993 }
3994 break;
3995 }
3996
3997 *rval = fcp_create_on_demand(pptr, bytes);
3998 if (*rval == 0) {
3999 mutex_enter(&pptr->port_mutex);
4000 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4001 if (ptgt) {
4002 /*
4003 * We now have a pointer to the target that
4004 * was created. Lets point to the first LUN on
4005 * this new target.
4006 */
4007 mutex_enter(&ptgt->tgt_mutex);
4008
4009 plun = ptgt->tgt_lun;
4010 /*
4011 * There may be stale/offline LUN entries on
4012 * this list (this is by design) and so we have
4013 * to make sure we point to the first online
4014 * LUN
4015 */
4016 while (plun &&
4017 plun->lun_state & FCP_LUN_OFFLINE) {
4018 plun = plun->lun_next;
4019 }
4020
4021 mutex_exit(&ptgt->tgt_mutex);
4022 }
4023 mutex_exit(&pptr->port_mutex);
4024 }
4025
4026 if (*rval == 0 && ptgt && plun) {
4027 mutex_enter(&plun->lun_mutex);
4028 /*
4029 * Allow up to fcp_lun_ready_retry seconds to
4030 * configure all the luns behind the target.
4031 *
4032 * The intent here is to allow targets with long
4033 * reboot/reset-recovery times to become available
4034 * while limiting the maximum wait time for an
4035 * unresponsive target.
4036 */
4037 end_time = ddi_get_lbolt() +
4038 SEC_TO_TICK(fcp_lun_ready_retry);
4039
4040 while (ddi_get_lbolt() < end_time) {
4041 retval = FC_SUCCESS;
4042
4043 /*
4044 * The new ndi interfaces for on-demand creation
4045 * are inflexible, Do some more work to pass on
4046 * a path name of some LUN (design is broken !)
4047 */
4048 if (plun->lun_cip) {
4049 if (plun->lun_mpxio == 0) {
4050 cdip = DIP(plun->lun_cip);
4051 } else {
4052 cdip = mdi_pi_get_client(
4053 PIP(plun->lun_cip));
4054 }
4055 if (cdip == NULL) {
4056 *rval = ENXIO;
4057 break;
4058 }
4059
4060 if (!i_ddi_devi_attached(cdip)) {
4061 mutex_exit(&plun->lun_mutex);
4062 delay(drv_usectohz(1000000));
4063 mutex_enter(&plun->lun_mutex);
4064 } else {
4065 /*
4066 * This Lun is ready, lets
4067 * check the next one.
4068 */
4069 mutex_exit(&plun->lun_mutex);
4070 plun = plun->lun_next;
4071 while (plun && (plun->lun_state
4072 & FCP_LUN_OFFLINE)) {
4073 plun = plun->lun_next;
4074 }
4075 if (!plun) {
4076 break;
4077 }
4078 mutex_enter(&plun->lun_mutex);
4079 }
4080 } else {
4081 /*
4082 * lun_cip field for a valid lun
4083 * should never be NULL. Fail the
4084 * command.
4085 */
4086 *rval = ENXIO;
4087 break;
4088 }
4089 }
4090 if (plun) {
4091 mutex_exit(&plun->lun_mutex);
4092 } else {
4093 char devnm[MAXNAMELEN];
4094 int nmlen;
4095
4096 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4097 ddi_node_name(cdip),
4098 ddi_get_name_addr(cdip));
4099
4100 if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4101 0) {
4102 *rval = EFAULT;
4103 }
4104 }
4105 } else {
4106 int i;
4107 char buf[25];
4108
4109 for (i = 0; i < FC_WWN_SIZE; i++) {
4110 (void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4111 }
4112
4113 fcp_log(CE_WARN, pptr->port_dip,
4114 "!Failed to create nodes for pwwn=%s; error=%x",
4115 buf, *rval);
4116 }
4117
4118 (void) ndi_devi_free(useless_dip);
4119 ddi_prop_free(bytes);
4120 break;
4121 }
4122
4123 case DEVCTL_DEVICE_RESET: {
4124 struct fcp_lun *plun;
4125 child_info_t *cip = CIP(cdip);
4126
4127 ASSERT(cdip != NULL);
4128 ASSERT(pptr != NULL);
4129 mutex_enter(&pptr->port_mutex);
4130 if (pip != NULL) {
4131 cip = CIP(pip);
4132 }
4133 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4134 mutex_exit(&pptr->port_mutex);
4135 *rval = ENXIO;
4136 break;
4137 }
4138 mutex_exit(&pptr->port_mutex);
4139
4140 mutex_enter(&plun->lun_tgt->tgt_mutex);
4141 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4142 mutex_exit(&plun->lun_tgt->tgt_mutex);
4143
4144 *rval = ENXIO;
4145 break;
4146 }
4147
4148 if (plun->lun_sd == NULL) {
4149 mutex_exit(&plun->lun_tgt->tgt_mutex);
4150
4151 *rval = ENXIO;
4152 break;
4153 }
4154 mutex_exit(&plun->lun_tgt->tgt_mutex);
4155
4156 /*
4157 * set up ap so that fcp_reset can figure out
4158 * which target to reset
4159 */
4160 if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4161 RESET_TARGET) == FALSE) {
4162 *rval = EIO;
4163 }
4164 break;
4165 }
4166
4167 case DEVCTL_BUS_GETSTATE:
4168 ASSERT(dcp != NULL);
4169 ASSERT(pptr != NULL);
4170 ASSERT(pptr->port_dip != NULL);
4171 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4172 NDI_SUCCESS) {
4173 *rval = EFAULT;
4174 }
4175 break;
4176
4177 case DEVCTL_BUS_QUIESCE:
4178 case DEVCTL_BUS_UNQUIESCE:
4179 *rval = ENOTSUP;
4180 break;
4181
4182 case DEVCTL_BUS_RESET:
4183 case DEVCTL_BUS_RESETALL:
4184 ASSERT(pptr != NULL);
4185 (void) fcp_linkreset(pptr, NULL, KM_SLEEP);
4186 break;
4187
4188 default:
4189 ASSERT(dcp != NULL);
4190 *rval = ENOTTY;
4191 break;
4192 }
4193
4194 /* all done -- clean up and return */
4195 out: if (devi_entered) {
4196 if (is_mpxio) {
4197 mdi_devi_exit(pptr->port_dip, circ);
4198 } else {
4199 ndi_devi_exit(pptr->port_dip, circ);
4200 }
4201 }
4202
4203 if (dcp != NULL) {
4204 ndi_dc_freehdl(dcp);
4205 }
4206
4207 return (retval);
4208 }
4209
4210
4211 /*ARGSUSED*/
4212 static int
fcp_els_callback(opaque_t ulph,opaque_t port_handle,fc_unsol_buf_t * buf,uint32_t claimed)4213 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4214 uint32_t claimed)
4215 {
4216 uchar_t r_ctl;
4217 uchar_t ls_code;
4218 struct fcp_port *pptr;
4219
4220 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4221 return (FC_UNCLAIMED);
4222 }
4223
4224 mutex_enter(&pptr->port_mutex);
4225 if (pptr->port_state & (FCP_STATE_DETACHING |
4226 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4227 mutex_exit(&pptr->port_mutex);
4228 return (FC_UNCLAIMED);
4229 }
4230 mutex_exit(&pptr->port_mutex);
4231
4232 r_ctl = buf->ub_frame.r_ctl;
4233
4234 switch (r_ctl & R_CTL_ROUTING) {
4235 case R_CTL_EXTENDED_SVC:
4236 if (r_ctl == R_CTL_ELS_REQ) {
4237 ls_code = buf->ub_buffer[0];
4238
4239 switch (ls_code) {
4240 case LA_ELS_PRLI:
4241 /*
4242 * We really don't care if something fails.
4243 * If the PRLI was not sent out, then the
4244 * other end will time it out.
4245 */
4246 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4247 return (FC_SUCCESS);
4248 }
4249 return (FC_UNCLAIMED);
4250 /* NOTREACHED */
4251
4252 default:
4253 break;
4254 }
4255 }
4256 /* FALLTHROUGH */
4257
4258 default:
4259 return (FC_UNCLAIMED);
4260 }
4261 }
4262
4263
4264 /*ARGSUSED*/
4265 static int
fcp_data_callback(opaque_t ulph,opaque_t port_handle,fc_unsol_buf_t * buf,uint32_t claimed)4266 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4267 uint32_t claimed)
4268 {
4269 return (FC_UNCLAIMED);
4270 }
4271
4272 /*
4273 * Function: fcp_statec_callback
4274 *
4275 * Description: The purpose of this function is to handle a port state change.
4276 * It is called from fp/fctl and, in a few instances, internally.
4277 *
4278 * Argument: ulph fp/fctl port handle
4279 * port_handle fcp_port structure
4280 * port_state Physical state of the port
4281 * port_top Topology
4282 * *devlist Pointer to the first entry of a table
4283 * containing the remote ports that can be
4284 * reached.
4285 * dev_cnt Number of entries pointed by devlist.
4286 * port_sid Port ID of the local port.
4287 *
4288 * Return Value: None
4289 */
4290 /*ARGSUSED*/
4291 static void
fcp_statec_callback(opaque_t ulph,opaque_t port_handle,uint32_t port_state,uint32_t port_top,fc_portmap_t * devlist,uint32_t dev_cnt,uint32_t port_sid)4292 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4293 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4294 uint32_t dev_cnt, uint32_t port_sid)
4295 {
4296 uint32_t link_count;
4297 int map_len = 0;
4298 struct fcp_port *pptr;
4299 fcp_map_tag_t *map_tag = NULL;
4300
4301 if ((pptr = fcp_get_port(port_handle)) == NULL) {
4302 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4303 return; /* nothing to work with! */
4304 }
4305
4306 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4307 fcp_trace, FCP_BUF_LEVEL_2, 0,
4308 "fcp_statec_callback: port state/dev_cnt/top ="
4309 "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4310 dev_cnt, port_top);
4311
4312 mutex_enter(&pptr->port_mutex);
4313
4314 /*
4315 * If a thread is in detach, don't do anything.
4316 */
4317 if (pptr->port_state & (FCP_STATE_DETACHING |
4318 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4319 mutex_exit(&pptr->port_mutex);
4320 return;
4321 }
4322
4323 /*
4324 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4325 * init_pkt is called, it knows whether or not the target's status
4326 * (or pd) might be changing.
4327 */
4328
4329 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4330 pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4331 }
4332
4333 /*
4334 * the transport doesn't allocate or probe unless being
4335 * asked to by either the applications or ULPs
4336 *
4337 * in cases where the port is OFFLINE at the time of port
4338 * attach callback and the link comes ONLINE later, for
4339 * easier automatic node creation (i.e. without you having to
4340 * go out and run the utility to perform LOGINs) the
4341 * following conditional is helpful
4342 */
4343 pptr->port_phys_state = port_state;
4344
4345 if (dev_cnt) {
4346 mutex_exit(&pptr->port_mutex);
4347
4348 map_len = sizeof (*map_tag) * dev_cnt;
4349 map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4350 if (map_tag == NULL) {
4351 fcp_log(CE_WARN, pptr->port_dip,
4352 "!fcp%d: failed to allocate for map tags; "
4353 " state change will not be processed",
4354 pptr->port_instance);
4355
4356 mutex_enter(&pptr->port_mutex);
4357 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4358 mutex_exit(&pptr->port_mutex);
4359
4360 return;
4361 }
4362
4363 mutex_enter(&pptr->port_mutex);
4364 }
4365
4366 if (pptr->port_id != port_sid) {
4367 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4368 fcp_trace, FCP_BUF_LEVEL_3, 0,
4369 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4370 port_sid);
4371 /*
4372 * The local port changed ID. It is the first time a port ID
4373 * is assigned or something drastic happened. We might have
4374 * been unplugged and replugged on another loop or fabric port
4375 * or somebody grabbed the AL_PA we had or somebody rezoned
4376 * the fabric we were plugged into.
4377 */
4378 pptr->port_id = port_sid;
4379 }
4380
4381 switch (FC_PORT_STATE_MASK(port_state)) {
4382 case FC_STATE_OFFLINE:
4383 case FC_STATE_RESET_REQUESTED:
4384 /*
4385 * link has gone from online to offline -- just update the
4386 * state of this port to BUSY and MARKed to go offline
4387 */
4388 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4389 fcp_trace, FCP_BUF_LEVEL_3, 0,
4390 "link went offline");
4391 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4392 /*
4393 * We were offline a while ago and this one
4394 * seems to indicate that the loop has gone
4395 * dead forever.
4396 */
4397 pptr->port_tmp_cnt += dev_cnt;
4398 pptr->port_state &= ~FCP_STATE_OFFLINE;
4399 pptr->port_state |= FCP_STATE_INIT;
4400 link_count = pptr->port_link_cnt;
4401 fcp_handle_devices(pptr, devlist, dev_cnt,
4402 link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4403 } else {
4404 pptr->port_link_cnt++;
4405 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4406 fcp_update_state(pptr, (FCP_LUN_BUSY |
4407 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4408 if (pptr->port_mpxio) {
4409 fcp_update_mpxio_path_verifybusy(pptr);
4410 }
4411 pptr->port_state |= FCP_STATE_OFFLINE;
4412 pptr->port_state &=
4413 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4414 pptr->port_tmp_cnt = 0;
4415 }
4416 mutex_exit(&pptr->port_mutex);
4417 break;
4418
4419 case FC_STATE_ONLINE:
4420 case FC_STATE_LIP:
4421 case FC_STATE_LIP_LBIT_SET:
4422 /*
4423 * link has gone from offline to online
4424 */
4425 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4426 fcp_trace, FCP_BUF_LEVEL_3, 0,
4427 "link went online");
4428
4429 pptr->port_link_cnt++;
4430
4431 while (pptr->port_ipkt_cnt) {
4432 mutex_exit(&pptr->port_mutex);
4433 delay(drv_usectohz(1000000));
4434 mutex_enter(&pptr->port_mutex);
4435 }
4436
4437 pptr->port_topology = port_top;
4438
4439 /*
4440 * The state of the targets and luns accessible through this
4441 * port is updated.
4442 */
4443 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4444 FCP_CAUSE_LINK_CHANGE);
4445
4446 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4447 pptr->port_state |= FCP_STATE_ONLINING;
4448 pptr->port_tmp_cnt = dev_cnt;
4449 link_count = pptr->port_link_cnt;
4450
4451 pptr->port_deadline = fcp_watchdog_time +
4452 FCP_ICMD_DEADLINE;
4453
4454 if (!dev_cnt) {
4455 /*
4456 * We go directly to the online state if no remote
4457 * ports were discovered.
4458 */
4459 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4460 fcp_trace, FCP_BUF_LEVEL_3, 0,
4461 "No remote ports discovered");
4462
4463 pptr->port_state &= ~FCP_STATE_ONLINING;
4464 pptr->port_state |= FCP_STATE_ONLINE;
4465 }
4466
4467 switch (port_top) {
4468 case FC_TOP_FABRIC:
4469 case FC_TOP_PUBLIC_LOOP:
4470 case FC_TOP_PRIVATE_LOOP:
4471 case FC_TOP_PT_PT:
4472
4473 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4474 fcp_retry_ns_registry(pptr, port_sid);
4475 }
4476
4477 fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4478 map_tag, FCP_CAUSE_LINK_CHANGE);
4479 break;
4480
4481 default:
4482 /*
4483 * We got here because we were provided with an unknown
4484 * topology.
4485 */
4486 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4487 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4488 }
4489
4490 pptr->port_tmp_cnt -= dev_cnt;
4491 fcp_log(CE_WARN, pptr->port_dip,
4492 "!unknown/unsupported topology (0x%x)", port_top);
4493 break;
4494 }
4495 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4496 fcp_trace, FCP_BUF_LEVEL_3, 0,
4497 "Notify ssd of the reset to reinstate the reservations");
4498
4499 scsi_hba_reset_notify_callback(&pptr->port_mutex,
4500 &pptr->port_reset_notify_listf);
4501
4502 mutex_exit(&pptr->port_mutex);
4503
4504 break;
4505
4506 case FC_STATE_RESET:
4507 ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4508 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4509 fcp_trace, FCP_BUF_LEVEL_3, 0,
4510 "RESET state, waiting for Offline/Online state_cb");
4511 mutex_exit(&pptr->port_mutex);
4512 break;
4513
4514 case FC_STATE_DEVICE_CHANGE:
4515 /*
4516 * We come here when an application has requested
4517 * Dynamic node creation/deletion in Fabric connectivity.
4518 */
4519 if (pptr->port_state & (FCP_STATE_OFFLINE |
4520 FCP_STATE_INIT)) {
4521 /*
4522 * This case can happen when the FCTL is in the
4523 * process of giving us on online and the host on
4524 * the other side issues a PLOGI/PLOGO. Ideally
4525 * the state changes should be serialized unless
4526 * they are opposite (online-offline).
4527 * The transport will give us a final state change
4528 * so we can ignore this for the time being.
4529 */
4530 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4531 mutex_exit(&pptr->port_mutex);
4532 break;
4533 }
4534
4535 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4536 fcp_retry_ns_registry(pptr, port_sid);
4537 }
4538
4539 /*
4540 * Extend the deadline under steady state conditions
4541 * to provide more time for the device-change-commands
4542 */
4543 if (!pptr->port_ipkt_cnt) {
4544 pptr->port_deadline = fcp_watchdog_time +
4545 FCP_ICMD_DEADLINE;
4546 }
4547
4548 /*
4549 * There is another race condition here, where if we were
4550 * in ONLINEING state and a devices in the map logs out,
4551 * fp will give another state change as DEVICE_CHANGE
4552 * and OLD. This will result in that target being offlined.
4553 * The pd_handle is freed. If from the first statec callback
4554 * we were going to fire a PLOGI/PRLI, the system will
4555 * panic in fc_ulp_transport with invalid pd_handle.
4556 * The fix is to check for the link_cnt before issuing
4557 * any command down.
4558 */
4559 fcp_update_targets(pptr, devlist, dev_cnt,
4560 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4561
4562 link_count = pptr->port_link_cnt;
4563
4564 fcp_handle_devices(pptr, devlist, dev_cnt,
4565 link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4566
4567 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4568
4569 mutex_exit(&pptr->port_mutex);
4570 break;
4571
4572 case FC_STATE_TARGET_PORT_RESET:
4573 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4574 fcp_retry_ns_registry(pptr, port_sid);
4575 }
4576
4577 /* Do nothing else */
4578 mutex_exit(&pptr->port_mutex);
4579 break;
4580
4581 default:
4582 fcp_log(CE_WARN, pptr->port_dip,
4583 "!Invalid state change=0x%x", port_state);
4584 mutex_exit(&pptr->port_mutex);
4585 break;
4586 }
4587
4588 if (map_tag) {
4589 kmem_free(map_tag, map_len);
4590 }
4591 }
4592
4593 /*
4594 * Function: fcp_handle_devices
4595 *
4596 * Description: This function updates the devices currently known by
4597 * walking the list provided by the caller. The list passed
4598 * by the caller is supposed to be the list of reachable
4599 * devices.
4600 *
4601 * Argument: *pptr Fcp port structure.
4602 * *devlist Pointer to the first entry of a table
4603 * containing the remote ports that can be
4604 * reached.
4605 * dev_cnt Number of entries pointed by devlist.
4606 * link_cnt Link state count.
4607 * *map_tag Array of fcp_map_tag_t structures.
4608 * cause What caused this function to be called.
4609 *
4610 * Return Value: None
4611 *
4612 * Notes: The pptr->port_mutex must be held.
4613 */
4614 static void
fcp_handle_devices(struct fcp_port * pptr,fc_portmap_t devlist[],uint32_t dev_cnt,int link_cnt,fcp_map_tag_t * map_tag,int cause)4615 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4616 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4617 {
4618 int i;
4619 int check_finish_init = 0;
4620 fc_portmap_t *map_entry;
4621 struct fcp_tgt *ptgt = NULL;
4622
4623 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4624 fcp_trace, FCP_BUF_LEVEL_3, 0,
4625 "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4626
4627 if (dev_cnt) {
4628 ASSERT(map_tag != NULL);
4629 }
4630
4631 /*
4632 * The following code goes through the list of remote ports that are
4633 * accessible through this (pptr) local port (The list walked is the
4634 * one provided by the caller which is the list of the remote ports
4635 * currently reachable). It checks if any of them was already
4636 * known by looking for the corresponding target structure based on
4637 * the world wide name. If a target is part of the list it is tagged
4638 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4639 *
4640 * Old comment
4641 * -----------
4642 * Before we drop port mutex; we MUST get the tags updated; This
4643 * two step process is somewhat slow, but more reliable.
4644 */
4645 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4646 map_entry = &(devlist[i]);
4647
4648 /*
4649 * get ptr to this map entry in our port's
4650 * list (if any)
4651 */
4652 ptgt = fcp_lookup_target(pptr,
4653 (uchar_t *)&(map_entry->map_pwwn));
4654
4655 if (ptgt) {
4656 map_tag[i] = ptgt->tgt_change_cnt;
4657 if (cause == FCP_CAUSE_LINK_CHANGE) {
4658 ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4659 }
4660 }
4661 }
4662
4663 /*
4664 * At this point we know which devices of the new list were already
4665 * known (The field tgt_aux_state of the target structure has been
4666 * set to FCP_TGT_TAGGED).
4667 *
4668 * The following code goes through the list of targets currently known
4669 * by the local port (the list is actually a hashing table). If a
4670 * target is found and is not tagged, it means the target cannot
4671 * be reached anymore through the local port (pptr). It is offlined.
4672 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4673 */
4674 for (i = 0; i < FCP_NUM_HASH; i++) {
4675 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4676 ptgt = ptgt->tgt_next) {
4677 mutex_enter(&ptgt->tgt_mutex);
4678 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4679 (cause == FCP_CAUSE_LINK_CHANGE) &&
4680 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4681 fcp_offline_target_now(pptr, ptgt,
4682 link_cnt, ptgt->tgt_change_cnt, 0);
4683 }
4684 mutex_exit(&ptgt->tgt_mutex);
4685 }
4686 }
4687
4688 /*
4689 * At this point, the devices that were known but cannot be reached
4690 * anymore, have most likely been offlined.
4691 *
4692 * The following section of code seems to go through the list of
4693 * remote ports that can now be reached. For every single one it
4694 * checks if it is already known or if it is a new port.
4695 */
4696 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4697
4698 if (check_finish_init) {
4699 ASSERT(i > 0);
4700 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4701 map_tag[i - 1], cause);
4702 check_finish_init = 0;
4703 }
4704
4705 /* get a pointer to this map entry */
4706 map_entry = &(devlist[i]);
4707
4708 /*
4709 * Check for the duplicate map entry flag. If we have marked
4710 * this entry as a duplicate we skip it since the correct
4711 * (perhaps even same) state change will be encountered
4712 * later in the list.
4713 */
4714 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4715 continue;
4716 }
4717
4718 /* get ptr to this map entry in our port's list (if any) */
4719 ptgt = fcp_lookup_target(pptr,
4720 (uchar_t *)&(map_entry->map_pwwn));
4721
4722 if (ptgt) {
4723 /*
4724 * This device was already known. The field
4725 * tgt_aux_state is reset (was probably set to
4726 * FCP_TGT_TAGGED previously in this routine).
4727 */
4728 ptgt->tgt_aux_state = 0;
4729 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4730 fcp_trace, FCP_BUF_LEVEL_3, 0,
4731 "handle_devices: map did/state/type/flags = "
4732 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4733 "tgt_state=%d",
4734 map_entry->map_did.port_id, map_entry->map_state,
4735 map_entry->map_type, map_entry->map_flags,
4736 ptgt->tgt_d_id, ptgt->tgt_state);
4737 }
4738
4739 if (map_entry->map_type == PORT_DEVICE_OLD ||
4740 map_entry->map_type == PORT_DEVICE_NEW ||
4741 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4742 map_entry->map_type == PORT_DEVICE_CHANGED) {
4743 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4744 fcp_trace, FCP_BUF_LEVEL_2, 0,
4745 "map_type=%x, did = %x",
4746 map_entry->map_type,
4747 map_entry->map_did.port_id);
4748 }
4749
4750 switch (map_entry->map_type) {
4751 case PORT_DEVICE_NOCHANGE:
4752 case PORT_DEVICE_USER_CREATE:
4753 case PORT_DEVICE_USER_LOGIN:
4754 case PORT_DEVICE_NEW:
4755 case PORT_DEVICE_REPORTLUN_CHANGED:
4756 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4757
4758 if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4759 link_cnt, (ptgt) ? map_tag[i] : 0,
4760 cause) == TRUE) {
4761
4762 FCP_TGT_TRACE(ptgt, map_tag[i],
4763 FCP_TGT_TRACE_2);
4764 check_finish_init++;
4765 }
4766 break;
4767
4768 case PORT_DEVICE_OLD:
4769 if (ptgt != NULL) {
4770 FCP_TGT_TRACE(ptgt, map_tag[i],
4771 FCP_TGT_TRACE_3);
4772
4773 mutex_enter(&ptgt->tgt_mutex);
4774 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4775 /*
4776 * Must do an in-line wait for I/Os
4777 * to get drained
4778 */
4779 mutex_exit(&ptgt->tgt_mutex);
4780 mutex_exit(&pptr->port_mutex);
4781
4782 mutex_enter(&ptgt->tgt_mutex);
4783 while (ptgt->tgt_ipkt_cnt ||
4784 fcp_outstanding_lun_cmds(ptgt)
4785 == FC_SUCCESS) {
4786 mutex_exit(&ptgt->tgt_mutex);
4787 delay(drv_usectohz(1000000));
4788 mutex_enter(&ptgt->tgt_mutex);
4789 }
4790 mutex_exit(&ptgt->tgt_mutex);
4791
4792 mutex_enter(&pptr->port_mutex);
4793 mutex_enter(&ptgt->tgt_mutex);
4794
4795 (void) fcp_offline_target(pptr, ptgt,
4796 link_cnt, map_tag[i], 0, 0);
4797 }
4798 mutex_exit(&ptgt->tgt_mutex);
4799 }
4800 check_finish_init++;
4801 break;
4802
4803 case PORT_DEVICE_USER_DELETE:
4804 case PORT_DEVICE_USER_LOGOUT:
4805 if (ptgt != NULL) {
4806 FCP_TGT_TRACE(ptgt, map_tag[i],
4807 FCP_TGT_TRACE_4);
4808
4809 mutex_enter(&ptgt->tgt_mutex);
4810 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4811 (void) fcp_offline_target(pptr, ptgt,
4812 link_cnt, map_tag[i], 1, 0);
4813 }
4814 mutex_exit(&ptgt->tgt_mutex);
4815 }
4816 check_finish_init++;
4817 break;
4818
4819 case PORT_DEVICE_CHANGED:
4820 if (ptgt != NULL) {
4821 FCP_TGT_TRACE(ptgt, map_tag[i],
4822 FCP_TGT_TRACE_5);
4823
4824 if (fcp_device_changed(pptr, ptgt,
4825 map_entry, link_cnt, map_tag[i],
4826 cause) == TRUE) {
4827 check_finish_init++;
4828 }
4829 } else {
4830 if (fcp_handle_mapflags(pptr, ptgt,
4831 map_entry, link_cnt, 0, cause) == TRUE) {
4832 check_finish_init++;
4833 }
4834 }
4835 break;
4836
4837 default:
4838 fcp_log(CE_WARN, pptr->port_dip,
4839 "!Invalid map_type=0x%x", map_entry->map_type);
4840 check_finish_init++;
4841 break;
4842 }
4843 }
4844
4845 if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4846 ASSERT(i > 0);
4847 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4848 map_tag[i-1], cause);
4849 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4850 fcp_offline_all(pptr, link_cnt, cause);
4851 }
4852 }
4853
4854 static int
fcp_handle_reportlun_changed(struct fcp_tgt * ptgt,int cause)4855 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4856 {
4857 struct fcp_lun *plun;
4858 struct fcp_port *pptr;
4859 int rscn_count;
4860 int lun0_newalloc;
4861 int ret = TRUE;
4862
4863 ASSERT(ptgt);
4864 pptr = ptgt->tgt_port;
4865 lun0_newalloc = 0;
4866 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4867 /*
4868 * no LUN struct for LUN 0 yet exists,
4869 * so create one
4870 */
4871 plun = fcp_alloc_lun(ptgt);
4872 if (plun == NULL) {
4873 fcp_log(CE_WARN, pptr->port_dip,
4874 "!Failed to allocate lun 0 for"
4875 " D_ID=%x", ptgt->tgt_d_id);
4876 return (ret);
4877 }
4878 lun0_newalloc = 1;
4879 }
4880
4881 mutex_enter(&ptgt->tgt_mutex);
4882 /*
4883 * consider lun 0 as device not connected if it is
4884 * offlined or newly allocated
4885 */
4886 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4887 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4888 }
4889 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4890 plun->lun_state &= ~FCP_LUN_OFFLINE;
4891 ptgt->tgt_lun_cnt = 1;
4892 ptgt->tgt_report_lun_cnt = 0;
4893 mutex_exit(&ptgt->tgt_mutex);
4894
4895 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4896 if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4897 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4898 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4899 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4900 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4901 "to D_ID=%x", ptgt->tgt_d_id);
4902 } else {
4903 ret = FALSE;
4904 }
4905
4906 return (ret);
4907 }
4908
4909 /*
4910 * Function: fcp_handle_mapflags
4911 *
4912 * Description: This function creates a target structure if the ptgt passed
4913 * is NULL. It also kicks off the PLOGI if we are not logged
4914 * into the target yet or the PRLI if we are logged into the
4915 * target already. The rest of the treatment is done in the
4916 * callbacks of the PLOGI or PRLI.
4917 *
4918 * Argument: *pptr FCP Port structure.
4919 * *ptgt Target structure.
4920 * *map_entry Array of fc_portmap_t structures.
4921 * link_cnt Link state count.
4922 * tgt_cnt Target state count.
4923 * cause What caused this function to be called.
4924 *
4925 * Return Value: TRUE Failed
4926 * FALSE Succeeded
4927 *
4928 * Notes: pptr->port_mutex must be owned.
4929 */
4930 static int
fcp_handle_mapflags(struct fcp_port * pptr,struct fcp_tgt * ptgt,fc_portmap_t * map_entry,int link_cnt,int tgt_cnt,int cause)4931 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt,
4932 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4933 {
4934 int lcount;
4935 int tcount;
4936 int ret = TRUE;
4937 int alloc;
4938 struct fcp_ipkt *icmd;
4939 struct fcp_lun *pseq_lun = NULL;
4940 uchar_t opcode;
4941 int valid_ptgt_was_passed = FALSE;
4942
4943 ASSERT(mutex_owned(&pptr->port_mutex));
4944
4945 /*
4946 * This case is possible where the FCTL has come up and done discovery
4947 * before FCP was loaded and attached. FCTL would have discovered the
4948 * devices and later the ULP came online. In this case ULP's would get
4949 * PORT_DEVICE_NOCHANGE but target would be NULL.
4950 */
4951 if (ptgt == NULL) {
4952 /* don't already have a target */
4953 mutex_exit(&pptr->port_mutex);
4954 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4955 mutex_enter(&pptr->port_mutex);
4956
4957 if (ptgt == NULL) {
4958 fcp_log(CE_WARN, pptr->port_dip,
4959 "!FC target allocation failed");
4960 return (ret);
4961 }
4962 mutex_enter(&ptgt->tgt_mutex);
4963 ptgt->tgt_statec_cause = cause;
4964 ptgt->tgt_tmp_cnt = 1;
4965 mutex_exit(&ptgt->tgt_mutex);
4966 } else {
4967 valid_ptgt_was_passed = TRUE;
4968 }
4969
4970 /*
4971 * Copy in the target parameters
4972 */
4973 mutex_enter(&ptgt->tgt_mutex);
4974 ptgt->tgt_d_id = map_entry->map_did.port_id;
4975 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4976 ptgt->tgt_pd_handle = map_entry->map_pd;
4977 ptgt->tgt_fca_dev = NULL;
4978
4979 /* Copy port and node WWNs */
4980 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4981 FC_WWN_SIZE);
4982 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4983 FC_WWN_SIZE);
4984
4985 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4986 (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4987 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4988 valid_ptgt_was_passed) {
4989 /*
4990 * determine if there are any tape LUNs on this target
4991 */
4992 for (pseq_lun = ptgt->tgt_lun;
4993 pseq_lun != NULL;
4994 pseq_lun = pseq_lun->lun_next) {
4995 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4996 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
4997 fcp_update_tgt_state(ptgt, FCP_RESET,
4998 FCP_LUN_MARK);
4999 mutex_exit(&ptgt->tgt_mutex);
5000 return (ret);
5001 }
5002 }
5003 }
5004
5005 /*
5006 * if UA'REPORT_LUN_CHANGED received,
5007 * send out REPORT LUN promptly, skip PLOGI/PRLI process
5008 */
5009 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5010 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5011 mutex_exit(&ptgt->tgt_mutex);
5012 mutex_exit(&pptr->port_mutex);
5013
5014 ret = fcp_handle_reportlun_changed(ptgt, cause);
5015
5016 mutex_enter(&pptr->port_mutex);
5017 return (ret);
5018 }
5019
5020 /*
5021 * If ptgt was NULL when this function was entered, then tgt_node_state
5022 * was never specifically initialized but zeroed out which means
5023 * FCP_TGT_NODE_NONE.
5024 */
5025 switch (ptgt->tgt_node_state) {
5026 case FCP_TGT_NODE_NONE:
5027 case FCP_TGT_NODE_ON_DEMAND:
5028 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5029 !fcp_enable_auto_configuration &&
5030 map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5031 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5032 } else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5033 fcp_enable_auto_configuration &&
5034 (ptgt->tgt_manual_config_only == 1) &&
5035 map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5036 /*
5037 * If auto configuration is set and
5038 * the tgt_manual_config_only flag is set then
5039 * we only want the user to be able to change
5040 * the state through create_on_demand.
5041 */
5042 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5043 } else {
5044 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5045 }
5046 break;
5047
5048 case FCP_TGT_NODE_PRESENT:
5049 break;
5050 }
5051 /*
5052 * If we are booting from a fabric device, make sure we
5053 * mark the node state appropriately for this target to be
5054 * enumerated
5055 */
5056 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5057 if (bcmp((caddr_t)pptr->port_boot_wwn,
5058 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5059 sizeof (ptgt->tgt_port_wwn)) == 0) {
5060 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5061 }
5062 }
5063 mutex_exit(&ptgt->tgt_mutex);
5064
5065 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5066 fcp_trace, FCP_BUF_LEVEL_3, 0,
5067 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5068 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5069 map_entry->map_rscn_info.ulp_rscn_count);
5070
5071 mutex_enter(&ptgt->tgt_mutex);
5072
5073 /*
5074 * Reset target OFFLINE state and mark the target BUSY
5075 */
5076 ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5077 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5078
5079 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5080 lcount = link_cnt;
5081
5082 mutex_exit(&ptgt->tgt_mutex);
5083 mutex_exit(&pptr->port_mutex);
5084
5085 /*
5086 * if we are already logged in, then we do a PRLI, else
5087 * we do a PLOGI first (to get logged in)
5088 *
5089 * We will not check if we are the PLOGI initiator
5090 */
5091 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5092 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5093
5094 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5095
5096 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5097 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5098 cause, map_entry->map_rscn_info.ulp_rscn_count);
5099
5100 if (icmd == NULL) {
5101 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5102 /*
5103 * We've exited port_mutex before calling fcp_icmd_alloc,
5104 * we need to make sure we reacquire it before returning.
5105 */
5106 mutex_enter(&pptr->port_mutex);
5107 return (FALSE);
5108 }
5109
5110 /* TRUE is only returned while target is intended skipped */
5111 ret = FALSE;
5112 /* discover info about this target */
5113 if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5114 lcount, tcount, cause)) == DDI_SUCCESS) {
5115 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5116 } else {
5117 fcp_icmd_free(pptr, icmd);
5118 ret = TRUE;
5119 }
5120 mutex_enter(&pptr->port_mutex);
5121
5122 return (ret);
5123 }
5124
5125 /*
5126 * Function: fcp_send_els
5127 *
5128 * Description: Sends an ELS to the target specified by the caller. Supports
5129 * PLOGI and PRLI.
5130 *
5131 * Argument: *pptr Fcp port.
5132 * *ptgt Target to send the ELS to.
5133 * *icmd Internal packet
5134 * opcode ELS opcode
5135 * lcount Link state change counter
5136 * tcount Target state change counter
5137 * cause What caused the call
5138 *
5139 * Return Value: DDI_SUCCESS
5140 * Others
5141 */
5142 static int
fcp_send_els(struct fcp_port * pptr,struct fcp_tgt * ptgt,struct fcp_ipkt * icmd,uchar_t opcode,int lcount,int tcount,int cause)5143 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5144 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5145 {
5146 fc_packet_t *fpkt;
5147 fc_frame_hdr_t *hp;
5148 int internal = 0;
5149 int alloc;
5150 int cmd_len;
5151 int resp_len;
5152 int res = DDI_FAILURE; /* default result */
5153 int rval = DDI_FAILURE;
5154
5155 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5156 ASSERT(ptgt->tgt_port == pptr);
5157
5158 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5159 fcp_trace, FCP_BUF_LEVEL_5, 0,
5160 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5161 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5162
5163 if (opcode == LA_ELS_PLOGI) {
5164 cmd_len = sizeof (la_els_logi_t);
5165 resp_len = sizeof (la_els_logi_t);
5166 } else {
5167 ASSERT(opcode == LA_ELS_PRLI);
5168 cmd_len = sizeof (la_els_prli_t);
5169 resp_len = sizeof (la_els_prli_t);
5170 }
5171
5172 if (icmd == NULL) {
5173 alloc = FCP_MAX(sizeof (la_els_logi_t),
5174 sizeof (la_els_prli_t));
5175 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5176 pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5177 lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5178 if (icmd == NULL) {
5179 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5180 return (res);
5181 }
5182 internal++;
5183 }
5184 fpkt = icmd->ipkt_fpkt;
5185
5186 fpkt->pkt_cmdlen = cmd_len;
5187 fpkt->pkt_rsplen = resp_len;
5188 fpkt->pkt_datalen = 0;
5189 icmd->ipkt_retries = 0;
5190
5191 /* fill in fpkt info */
5192 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5193 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5194 fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5195
5196 /* get ptr to frame hdr in fpkt */
5197 hp = &fpkt->pkt_cmd_fhdr;
5198
5199 /*
5200 * fill in frame hdr
5201 */
5202 hp->r_ctl = R_CTL_ELS_REQ;
5203 hp->s_id = pptr->port_id; /* source ID */
5204 hp->d_id = ptgt->tgt_d_id; /* dest ID */
5205 hp->type = FC_TYPE_EXTENDED_LS;
5206 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5207 hp->seq_id = 0;
5208 hp->rsvd = 0;
5209 hp->df_ctl = 0;
5210 hp->seq_cnt = 0;
5211 hp->ox_id = 0xffff; /* i.e. none */
5212 hp->rx_id = 0xffff; /* i.e. none */
5213 hp->ro = 0;
5214
5215 /*
5216 * at this point we have a filled in cmd pkt
5217 *
5218 * fill in the respective info, then use the transport to send
5219 * the packet
5220 *
5221 * for a PLOGI call fc_ulp_login(), and
5222 * for a PRLI call fc_ulp_issue_els()
5223 */
5224 switch (opcode) {
5225 case LA_ELS_PLOGI: {
5226 struct la_els_logi logi;
5227
5228 bzero(&logi, sizeof (struct la_els_logi));
5229
5230 hp = &fpkt->pkt_cmd_fhdr;
5231 hp->r_ctl = R_CTL_ELS_REQ;
5232 logi.ls_code.ls_code = LA_ELS_PLOGI;
5233 logi.ls_code.mbz = 0;
5234
5235 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5236 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5237
5238 icmd->ipkt_opcode = LA_ELS_PLOGI;
5239
5240 mutex_enter(&pptr->port_mutex);
5241 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5242
5243 mutex_exit(&pptr->port_mutex);
5244
5245 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5246 if (rval == FC_SUCCESS) {
5247 res = DDI_SUCCESS;
5248 break;
5249 }
5250
5251 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5252
5253 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5254 rval, "PLOGI");
5255 } else {
5256 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5257 fcp_trace, FCP_BUF_LEVEL_5, 0,
5258 "fcp_send_els1: state change occured"
5259 " for D_ID=0x%x", ptgt->tgt_d_id);
5260 mutex_exit(&pptr->port_mutex);
5261 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5262 }
5263 break;
5264 }
5265
5266 case LA_ELS_PRLI: {
5267 struct la_els_prli prli;
5268 struct fcp_prli *fprli;
5269
5270 bzero(&prli, sizeof (struct la_els_prli));
5271
5272 hp = &fpkt->pkt_cmd_fhdr;
5273 hp->r_ctl = R_CTL_ELS_REQ;
5274
5275 /* fill in PRLI cmd ELS fields */
5276 prli.ls_code = LA_ELS_PRLI;
5277 prli.page_length = 0x10; /* huh? */
5278 prli.payload_length = sizeof (struct la_els_prli);
5279
5280 icmd->ipkt_opcode = LA_ELS_PRLI;
5281
5282 /* get ptr to PRLI service params */
5283 fprli = (struct fcp_prli *)prli.service_params;
5284
5285 /* fill in service params */
5286 fprli->type = 0x08;
5287 fprli->resvd1 = 0;
5288 fprli->orig_process_assoc_valid = 0;
5289 fprli->resp_process_assoc_valid = 0;
5290 fprli->establish_image_pair = 1;
5291 fprli->resvd2 = 0;
5292 fprli->resvd3 = 0;
5293 fprli->obsolete_1 = 0;
5294 fprli->obsolete_2 = 0;
5295 fprli->data_overlay_allowed = 0;
5296 fprli->initiator_fn = 1;
5297 fprli->confirmed_compl_allowed = 1;
5298
5299 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5300 fprli->target_fn = 1;
5301 } else {
5302 fprli->target_fn = 0;
5303 }
5304
5305 fprli->retry = 1;
5306 fprli->read_xfer_rdy_disabled = 1;
5307 fprli->write_xfer_rdy_disabled = 0;
5308
5309 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5310 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5311
5312 /* issue the PRLI request */
5313
5314 mutex_enter(&pptr->port_mutex);
5315 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5316
5317 mutex_exit(&pptr->port_mutex);
5318
5319 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5320 if (rval == FC_SUCCESS) {
5321 res = DDI_SUCCESS;
5322 break;
5323 }
5324
5325 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5326
5327 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5328 rval, "PRLI");
5329 } else {
5330 mutex_exit(&pptr->port_mutex);
5331 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5332 }
5333 break;
5334 }
5335
5336 default:
5337 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5338 break;
5339 }
5340
5341 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5342 fcp_trace, FCP_BUF_LEVEL_5, 0,
5343 "fcp_send_els: returning %d", res);
5344
5345 if (res != DDI_SUCCESS) {
5346 if (internal) {
5347 fcp_icmd_free(pptr, icmd);
5348 }
5349 }
5350
5351 return (res);
5352 }
5353
5354
5355 /*
5356 * called internally update the state of all of the tgts and each LUN
5357 * for this port (i.e. each target known to be attached to this port)
5358 * if they are not already offline
5359 *
5360 * must be called with the port mutex owned
5361 *
5362 * acquires and releases the target mutexes for each target attached
5363 * to this port
5364 */
5365 void
fcp_update_state(struct fcp_port * pptr,uint32_t state,int cause)5366 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5367 {
5368 int i;
5369 struct fcp_tgt *ptgt;
5370
5371 ASSERT(mutex_owned(&pptr->port_mutex));
5372
5373 for (i = 0; i < FCP_NUM_HASH; i++) {
5374 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5375 ptgt = ptgt->tgt_next) {
5376 mutex_enter(&ptgt->tgt_mutex);
5377 fcp_update_tgt_state(ptgt, FCP_SET, state);
5378 ptgt->tgt_change_cnt++;
5379 ptgt->tgt_statec_cause = cause;
5380 ptgt->tgt_tmp_cnt = 1;
5381 ptgt->tgt_done = 0;
5382 mutex_exit(&ptgt->tgt_mutex);
5383 }
5384 }
5385 }
5386
5387
5388 static void
fcp_offline_all(struct fcp_port * pptr,int lcount,int cause)5389 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5390 {
5391 int i;
5392 int ndevs;
5393 struct fcp_tgt *ptgt;
5394
5395 ASSERT(mutex_owned(&pptr->port_mutex));
5396
5397 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5398 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5399 ptgt = ptgt->tgt_next) {
5400 ndevs++;
5401 }
5402 }
5403
5404 if (ndevs == 0) {
5405 return;
5406 }
5407 pptr->port_tmp_cnt = ndevs;
5408
5409 for (i = 0; i < FCP_NUM_HASH; i++) {
5410 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5411 ptgt = ptgt->tgt_next) {
5412 (void) fcp_call_finish_init_held(pptr, ptgt,
5413 lcount, ptgt->tgt_change_cnt, cause);
5414 }
5415 }
5416 }
5417
5418 /*
5419 * Function: fcp_update_tgt_state
5420 *
5421 * Description: This function updates the field tgt_state of a target. That
5422 * field is a bitmap and which bit can be set or reset
5423 * individually. The action applied to the target state is also
5424 * applied to all the LUNs belonging to the target (provided the
5425 * LUN is not offline). A side effect of applying the state
5426 * modification to the target and the LUNs is the field tgt_trace
5427 * of the target and lun_trace of the LUNs is set to zero.
5428 *
5429 *
5430 * Argument: *ptgt Target structure.
5431 * flag Flag indication what action to apply (set/reset).
5432 * state State bits to update.
5433 *
5434 * Return Value: None
5435 *
5436 * Context: Interrupt, Kernel or User context.
5437 * The mutex of the target (ptgt->tgt_mutex) must be owned when
5438 * calling this function.
5439 */
5440 void
fcp_update_tgt_state(struct fcp_tgt * ptgt,int flag,uint32_t state)5441 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5442 {
5443 struct fcp_lun *plun;
5444
5445 ASSERT(mutex_owned(&ptgt->tgt_mutex));
5446
5447 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5448 /* The target is not offline. */
5449 if (flag == FCP_SET) {
5450 ptgt->tgt_state |= state;
5451 ptgt->tgt_trace = 0;
5452 } else {
5453 ptgt->tgt_state &= ~state;
5454 }
5455
5456 for (plun = ptgt->tgt_lun; plun != NULL;
5457 plun = plun->lun_next) {
5458 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5459 /* The LUN is not offline. */
5460 if (flag == FCP_SET) {
5461 plun->lun_state |= state;
5462 plun->lun_trace = 0;
5463 } else {
5464 plun->lun_state &= ~state;
5465 }
5466 }
5467 }
5468 }
5469 }
5470
5471 /*
5472 * Function: fcp_update_tgt_state
5473 *
5474 * Description: This function updates the field lun_state of a LUN. That
5475 * field is a bitmap and which bit can be set or reset
5476 * individually.
5477 *
5478 * Argument: *plun LUN structure.
5479 * flag Flag indication what action to apply (set/reset).
5480 * state State bits to update.
5481 *
5482 * Return Value: None
5483 *
5484 * Context: Interrupt, Kernel or User context.
5485 * The mutex of the target (ptgt->tgt_mutex) must be owned when
5486 * calling this function.
5487 */
5488 void
fcp_update_lun_state(struct fcp_lun * plun,int flag,uint32_t state)5489 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5490 {
5491 struct fcp_tgt *ptgt = plun->lun_tgt;
5492
5493 ASSERT(mutex_owned(&ptgt->tgt_mutex));
5494
5495 if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5496 if (flag == FCP_SET) {
5497 plun->lun_state |= state;
5498 } else {
5499 plun->lun_state &= ~state;
5500 }
5501 }
5502 }
5503
5504 /*
5505 * Function: fcp_get_port
5506 *
5507 * Description: This function returns the fcp_port structure from the opaque
5508 * handle passed by the caller. That opaque handle is the handle
5509 * used by fp/fctl to identify a particular local port. That
5510 * handle has been stored in the corresponding fcp_port
5511 * structure. This function is going to walk the global list of
5512 * fcp_port structures till one has a port_fp_handle that matches
5513 * the handle passed by the caller. This function enters the
5514 * mutex fcp_global_mutex while walking the global list and then
5515 * releases it.
5516 *
5517 * Argument: port_handle Opaque handle that fp/fctl uses to identify a
5518 * particular port.
5519 *
5520 * Return Value: NULL Not found.
5521 * Not NULL Pointer to the fcp_port structure.
5522 *
5523 * Context: Interrupt, Kernel or User context.
5524 */
5525 static struct fcp_port *
fcp_get_port(opaque_t port_handle)5526 fcp_get_port(opaque_t port_handle)
5527 {
5528 struct fcp_port *pptr;
5529
5530 ASSERT(port_handle != NULL);
5531
5532 mutex_enter(&fcp_global_mutex);
5533 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5534 if (pptr->port_fp_handle == port_handle) {
5535 break;
5536 }
5537 }
5538 mutex_exit(&fcp_global_mutex);
5539
5540 return (pptr);
5541 }
5542
5543
5544 static void
fcp_unsol_callback(fc_packet_t * fpkt)5545 fcp_unsol_callback(fc_packet_t *fpkt)
5546 {
5547 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5548 struct fcp_port *pptr = icmd->ipkt_port;
5549
5550 if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5551 caddr_t state, reason, action, expln;
5552
5553 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
5554 &action, &expln);
5555
5556 fcp_log(CE_WARN, pptr->port_dip,
5557 "!couldn't post response to unsolicited request: "
5558 " state=%s reason=%s rx_id=%x ox_id=%x",
5559 state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5560 fpkt->pkt_cmd_fhdr.rx_id);
5561 }
5562 fcp_icmd_free(pptr, icmd);
5563 }
5564
5565
5566 /*
5567 * Perform general purpose preparation of a response to an unsolicited request
5568 */
5569 static void
fcp_unsol_resp_init(fc_packet_t * pkt,fc_unsol_buf_t * buf,uchar_t r_ctl,uchar_t type)5570 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5571 uchar_t r_ctl, uchar_t type)
5572 {
5573 pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5574 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5575 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5576 pkt->pkt_cmd_fhdr.type = type;
5577 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5578 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5579 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl;
5580 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5581 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5582 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5583 pkt->pkt_cmd_fhdr.ro = 0;
5584 pkt->pkt_cmd_fhdr.rsvd = 0;
5585 pkt->pkt_comp = fcp_unsol_callback;
5586 pkt->pkt_pd = NULL;
5587 pkt->pkt_ub_resp_token = (opaque_t)buf;
5588 }
5589
5590
5591 /*ARGSUSED*/
5592 static int
fcp_unsol_prli(struct fcp_port * pptr,fc_unsol_buf_t * buf)5593 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5594 {
5595 fc_packet_t *fpkt;
5596 struct la_els_prli prli;
5597 struct fcp_prli *fprli;
5598 struct fcp_ipkt *icmd;
5599 struct la_els_prli *from;
5600 struct fcp_prli *orig;
5601 struct fcp_tgt *ptgt;
5602 int tcount = 0;
5603 int lcount;
5604
5605 from = (struct la_els_prli *)buf->ub_buffer;
5606 orig = (struct fcp_prli *)from->service_params;
5607 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5608 NULL) {
5609 mutex_enter(&ptgt->tgt_mutex);
5610 tcount = ptgt->tgt_change_cnt;
5611 mutex_exit(&ptgt->tgt_mutex);
5612 }
5613
5614 mutex_enter(&pptr->port_mutex);
5615 lcount = pptr->port_link_cnt;
5616 mutex_exit(&pptr->port_mutex);
5617
5618 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5619 sizeof (la_els_prli_t), 0,
5620 pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5621 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5622 return (FC_FAILURE);
5623 }
5624
5625 fpkt = icmd->ipkt_fpkt;
5626 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5627 fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5628 fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5629 fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5630 fpkt->pkt_rsplen = 0;
5631 fpkt->pkt_datalen = 0;
5632
5633 icmd->ipkt_opcode = LA_ELS_PRLI;
5634
5635 bzero(&prli, sizeof (struct la_els_prli));
5636 fprli = (struct fcp_prli *)prli.service_params;
5637 prli.ls_code = LA_ELS_ACC;
5638 prli.page_length = 0x10;
5639 prli.payload_length = sizeof (struct la_els_prli);
5640
5641 /* fill in service params */
5642 fprli->type = 0x08;
5643 fprli->resvd1 = 0;
5644 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5645 fprli->orig_process_associator = orig->orig_process_associator;
5646 fprli->resp_process_assoc_valid = 0;
5647 fprli->establish_image_pair = 1;
5648 fprli->resvd2 = 0;
5649 fprli->resvd3 = 0;
5650 fprli->obsolete_1 = 0;
5651 fprli->obsolete_2 = 0;
5652 fprli->data_overlay_allowed = 0;
5653 fprli->initiator_fn = 1;
5654 fprli->confirmed_compl_allowed = 1;
5655
5656 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5657 fprli->target_fn = 1;
5658 } else {
5659 fprli->target_fn = 0;
5660 }
5661
5662 fprli->retry = 1;
5663 fprli->read_xfer_rdy_disabled = 1;
5664 fprli->write_xfer_rdy_disabled = 0;
5665
5666 /* save the unsol prli payload first */
5667 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5668 fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5669
5670 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5671 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5672
5673 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5674
5675 mutex_enter(&pptr->port_mutex);
5676 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5677 int rval;
5678 mutex_exit(&pptr->port_mutex);
5679
5680 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5681 FC_SUCCESS) {
5682 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5683 ptgt != NULL) {
5684 fcp_queue_ipkt(pptr, fpkt);
5685 return (FC_SUCCESS);
5686 }
5687 /* Let it timeout */
5688 fcp_icmd_free(pptr, icmd);
5689 return (FC_FAILURE);
5690 }
5691 } else {
5692 mutex_exit(&pptr->port_mutex);
5693 fcp_icmd_free(pptr, icmd);
5694 return (FC_FAILURE);
5695 }
5696
5697 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5698
5699 return (FC_SUCCESS);
5700 }
5701
5702 /*
5703 * Function: fcp_icmd_alloc
5704 *
5705 * Description: This function allocated a fcp_ipkt structure. The pkt_comp
5706 * field is initialized to fcp_icmd_callback. Sometimes it is
5707 * modified by the caller (such as fcp_send_scsi). The
5708 * structure is also tied to the state of the line and of the
5709 * target at a particular time. That link is established by
5710 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5711 * and tcount which came respectively from pptr->link_cnt and
5712 * ptgt->tgt_change_cnt.
5713 *
5714 * Argument: *pptr Fcp port.
5715 * *ptgt Target (destination of the command).
5716 * cmd_len Length of the command.
5717 * resp_len Length of the expected response.
5718 * data_len Length of the data.
5719 * nodma Indicates weither the command and response.
5720 * will be transfer through DMA or not.
5721 * lcount Link state change counter.
5722 * tcount Target state change counter.
5723 * cause Reason that lead to this call.
5724 *
5725 * Return Value: NULL Failed.
5726 * Not NULL Internal packet address.
5727 */
5728 static struct fcp_ipkt *
fcp_icmd_alloc(struct fcp_port * pptr,struct fcp_tgt * ptgt,int cmd_len,int resp_len,int data_len,int nodma,int lcount,int tcount,int cause,uint32_t rscn_count)5729 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5730 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5731 uint32_t rscn_count)
5732 {
5733 int dma_setup = 0;
5734 fc_packet_t *fpkt;
5735 struct fcp_ipkt *icmd = NULL;
5736
5737 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5738 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5739 KM_NOSLEEP);
5740 if (icmd == NULL) {
5741 fcp_log(CE_WARN, pptr->port_dip,
5742 "!internal packet allocation failed");
5743 return (NULL);
5744 }
5745
5746 /*
5747 * initialize the allocated packet
5748 */
5749 icmd->ipkt_nodma = nodma;
5750 icmd->ipkt_next = icmd->ipkt_prev = NULL;
5751 icmd->ipkt_lun = NULL;
5752
5753 icmd->ipkt_link_cnt = lcount;
5754 icmd->ipkt_change_cnt = tcount;
5755 icmd->ipkt_cause = cause;
5756
5757 mutex_enter(&pptr->port_mutex);
5758 icmd->ipkt_port = pptr;
5759 mutex_exit(&pptr->port_mutex);
5760
5761 /* keep track of amt of data to be sent in pkt */
5762 icmd->ipkt_cmdlen = cmd_len;
5763 icmd->ipkt_resplen = resp_len;
5764 icmd->ipkt_datalen = data_len;
5765
5766 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5767 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5768
5769 /* set pkt's private ptr to point to cmd pkt */
5770 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5771
5772 /* set FCA private ptr to memory just beyond */
5773 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5774 ((char *)icmd + sizeof (struct fcp_ipkt) +
5775 pptr->port_dmacookie_sz);
5776
5777 /* get ptr to fpkt substruct and fill it in */
5778 fpkt = icmd->ipkt_fpkt;
5779 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5780 sizeof (struct fcp_ipkt));
5781
5782 if (ptgt != NULL) {
5783 icmd->ipkt_tgt = ptgt;
5784 fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5785 }
5786
5787 fpkt->pkt_comp = fcp_icmd_callback;
5788 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5789 fpkt->pkt_cmdlen = cmd_len;
5790 fpkt->pkt_rsplen = resp_len;
5791 fpkt->pkt_datalen = data_len;
5792
5793 /*
5794 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5795 * rscn_count as fcp knows down to the transport. If a valid count was
5796 * passed into this function, we allocate memory to actually pass down
5797 * this info.
5798 *
5799 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5800 * basically mean that fcp will not be able to help transport
5801 * distinguish if a new RSCN has come after fcp was last informed about
5802 * it. In such cases, it might lead to the problem mentioned in CR/bug #
5803 * 5068068 where the device might end up going offline in case of RSCN
5804 * storms.
5805 */
5806 fpkt->pkt_ulp_rscn_infop = NULL;
5807 if (rscn_count != FC_INVALID_RSCN_COUNT) {
5808 fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5809 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5810 if (fpkt->pkt_ulp_rscn_infop == NULL) {
5811 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5812 fcp_trace, FCP_BUF_LEVEL_6, 0,
5813 "Failed to alloc memory to pass rscn info");
5814 }
5815 }
5816
5817 if (fpkt->pkt_ulp_rscn_infop != NULL) {
5818 fc_ulp_rscn_info_t *rscnp;
5819
5820 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5821 rscnp->ulp_rscn_count = rscn_count;
5822 }
5823
5824 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5825 goto fail;
5826 }
5827 dma_setup++;
5828
5829 /*
5830 * Must hold target mutex across setting of pkt_pd and call to
5831 * fc_ulp_init_packet to ensure the handle to the target doesn't go
5832 * away while we're not looking.
5833 */
5834 if (ptgt != NULL) {
5835 mutex_enter(&ptgt->tgt_mutex);
5836 fpkt->pkt_pd = ptgt->tgt_pd_handle;
5837
5838 /* ask transport to do its initialization on this pkt */
5839 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5840 != FC_SUCCESS) {
5841 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5842 fcp_trace, FCP_BUF_LEVEL_6, 0,
5843 "fc_ulp_init_packet failed");
5844 mutex_exit(&ptgt->tgt_mutex);
5845 goto fail;
5846 }
5847 mutex_exit(&ptgt->tgt_mutex);
5848 } else {
5849 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5850 != FC_SUCCESS) {
5851 FCP_TRACE(fcp_logq, pptr->port_instbuf,
5852 fcp_trace, FCP_BUF_LEVEL_6, 0,
5853 "fc_ulp_init_packet failed");
5854 goto fail;
5855 }
5856 }
5857
5858 mutex_enter(&pptr->port_mutex);
5859 if (pptr->port_state & (FCP_STATE_DETACHING |
5860 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5861 int rval;
5862
5863 mutex_exit(&pptr->port_mutex);
5864
5865 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5866 ASSERT(rval == FC_SUCCESS);
5867
5868 goto fail;
5869 }
5870
5871 if (ptgt != NULL) {
5872 mutex_enter(&ptgt->tgt_mutex);
5873 ptgt->tgt_ipkt_cnt++;
5874 mutex_exit(&ptgt->tgt_mutex);
5875 }
5876
5877 pptr->port_ipkt_cnt++;
5878
5879 mutex_exit(&pptr->port_mutex);
5880
5881 return (icmd);
5882
5883 fail:
5884 if (fpkt->pkt_ulp_rscn_infop != NULL) {
5885 kmem_free(fpkt->pkt_ulp_rscn_infop,
5886 sizeof (fc_ulp_rscn_info_t));
5887 fpkt->pkt_ulp_rscn_infop = NULL;
5888 }
5889
5890 if (dma_setup) {
5891 fcp_free_dma(pptr, icmd);
5892 }
5893 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5894 (size_t)pptr->port_dmacookie_sz);
5895
5896 return (NULL);
5897 }
5898
5899 /*
5900 * Function: fcp_icmd_free
5901 *
5902 * Description: Frees the internal command passed by the caller.
5903 *
5904 * Argument: *pptr Fcp port.
5905 * *icmd Internal packet to free.
5906 *
5907 * Return Value: None
5908 */
5909 static void
fcp_icmd_free(struct fcp_port * pptr,struct fcp_ipkt * icmd)5910 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5911 {
5912 struct fcp_tgt *ptgt = icmd->ipkt_tgt;
5913
5914 /* Let the underlying layers do their cleanup. */
5915 (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5916 icmd->ipkt_fpkt);
5917
5918 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5919 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5920 sizeof (fc_ulp_rscn_info_t));
5921 }
5922
5923 fcp_free_dma(pptr, icmd);
5924
5925 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5926 (size_t)pptr->port_dmacookie_sz);
5927
5928 mutex_enter(&pptr->port_mutex);
5929
5930 if (ptgt) {
5931 mutex_enter(&ptgt->tgt_mutex);
5932 ptgt->tgt_ipkt_cnt--;
5933 mutex_exit(&ptgt->tgt_mutex);
5934 }
5935
5936 pptr->port_ipkt_cnt--;
5937 mutex_exit(&pptr->port_mutex);
5938 }
5939
5940 /*
5941 * Function: fcp_alloc_dma
5942 *
5943 * Description: Allocated the DMA resources required for the internal
5944 * packet.
5945 *
5946 * Argument: *pptr FCP port.
5947 * *icmd Internal FCP packet.
5948 * nodma Indicates if the Cmd and Resp will be DMAed.
5949 * flags Allocation flags (Sleep or NoSleep).
5950 *
5951 * Return Value: FC_SUCCESS
5952 * FC_NOMEM
5953 */
5954 static int
fcp_alloc_dma(struct fcp_port * pptr,struct fcp_ipkt * icmd,int nodma,int flags)5955 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5956 int nodma, int flags)
5957 {
5958 int rval;
5959 size_t real_size;
5960 uint_t ccount;
5961 int bound = 0;
5962 int cmd_resp = 0;
5963 fc_packet_t *fpkt;
5964 ddi_dma_cookie_t pkt_data_cookie;
5965 ddi_dma_cookie_t *cp;
5966 uint32_t cnt;
5967
5968 fpkt = &icmd->ipkt_fc_packet;
5969
5970 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5971 fpkt->pkt_resp_dma == NULL);
5972
5973 icmd->ipkt_nodma = nodma;
5974
5975 if (nodma) {
5976 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5977 if (fpkt->pkt_cmd == NULL) {
5978 goto fail;
5979 }
5980
5981 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5982 if (fpkt->pkt_resp == NULL) {
5983 goto fail;
5984 }
5985 } else {
5986 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5987
5988 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5989 if (rval == FC_FAILURE) {
5990 ASSERT(fpkt->pkt_cmd_dma == NULL &&
5991 fpkt->pkt_resp_dma == NULL);
5992 goto fail;
5993 }
5994 cmd_resp++;
5995 }
5996
5997 if ((fpkt->pkt_datalen != 0) &&
5998 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
5999 /*
6000 * set up DMA handle and memory for the data in this packet
6001 */
6002 if (ddi_dma_alloc_handle(pptr->port_dip,
6003 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6004 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6005 goto fail;
6006 }
6007
6008 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6009 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6010 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6011 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6012 goto fail;
6013 }
6014
6015 /* was DMA mem size gotten < size asked for/needed ?? */
6016 if (real_size < fpkt->pkt_datalen) {
6017 goto fail;
6018 }
6019
6020 /* bind DMA address and handle together */
6021 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6022 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6023 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6024 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6025 goto fail;
6026 }
6027 bound++;
6028
6029 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6030 goto fail;
6031 }
6032
6033 fpkt->pkt_data_cookie_cnt = ccount;
6034
6035 cp = fpkt->pkt_data_cookie;
6036 *cp = pkt_data_cookie;
6037 cp++;
6038
6039 for (cnt = 1; cnt < ccount; cnt++, cp++) {
6040 ddi_dma_nextcookie(fpkt->pkt_data_dma,
6041 &pkt_data_cookie);
6042 *cp = pkt_data_cookie;
6043 }
6044
6045 } else if (fpkt->pkt_datalen != 0) {
6046 /*
6047 * If it's a pseudo FCA, then it can't support DMA even in
6048 * SCSI data phase.
6049 */
6050 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6051 if (fpkt->pkt_data == NULL) {
6052 goto fail;
6053 }
6054
6055 }
6056
6057 return (FC_SUCCESS);
6058
6059 fail:
6060 if (bound) {
6061 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6062 }
6063
6064 if (fpkt->pkt_data_dma) {
6065 if (fpkt->pkt_data) {
6066 ddi_dma_mem_free(&fpkt->pkt_data_acc);
6067 }
6068 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6069 } else {
6070 if (fpkt->pkt_data) {
6071 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6072 }
6073 }
6074
6075 if (nodma) {
6076 if (fpkt->pkt_cmd) {
6077 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6078 }
6079 if (fpkt->pkt_resp) {
6080 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6081 }
6082 } else {
6083 if (cmd_resp) {
6084 fcp_free_cmd_resp(pptr, fpkt);
6085 }
6086 }
6087
6088 return (FC_NOMEM);
6089 }
6090
6091
6092 static void
fcp_free_dma(struct fcp_port * pptr,struct fcp_ipkt * icmd)6093 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6094 {
6095 fc_packet_t *fpkt = icmd->ipkt_fpkt;
6096
6097 if (fpkt->pkt_data_dma) {
6098 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6099 if (fpkt->pkt_data) {
6100 ddi_dma_mem_free(&fpkt->pkt_data_acc);
6101 }
6102 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6103 } else {
6104 if (fpkt->pkt_data) {
6105 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6106 }
6107 /*
6108 * Need we reset pkt_* to zero???
6109 */
6110 }
6111
6112 if (icmd->ipkt_nodma) {
6113 if (fpkt->pkt_cmd) {
6114 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6115 }
6116 if (fpkt->pkt_resp) {
6117 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6118 }
6119 } else {
6120 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6121
6122 fcp_free_cmd_resp(pptr, fpkt);
6123 }
6124 }
6125
6126 /*
6127 * Function: fcp_lookup_target
6128 *
6129 * Description: Finds a target given a WWN.
6130 *
6131 * Argument: *pptr FCP port.
6132 * *wwn World Wide Name of the device to look for.
6133 *
6134 * Return Value: NULL No target found
6135 * Not NULL Target structure
6136 *
6137 * Context: Interrupt context.
6138 * The mutex pptr->port_mutex must be owned.
6139 */
6140 /* ARGSUSED */
6141 static struct fcp_tgt *
fcp_lookup_target(struct fcp_port * pptr,uchar_t * wwn)6142 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6143 {
6144 int hash;
6145 struct fcp_tgt *ptgt;
6146
6147 ASSERT(mutex_owned(&pptr->port_mutex));
6148
6149 hash = FCP_HASH(wwn);
6150
6151 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6152 ptgt = ptgt->tgt_next) {
6153 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6154 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6155 sizeof (ptgt->tgt_port_wwn)) == 0) {
6156 break;
6157 }
6158 }
6159
6160 return (ptgt);
6161 }
6162
6163
6164 /*
6165 * Find target structure given a port identifier
6166 */
6167 static struct fcp_tgt *
fcp_get_target_by_did(struct fcp_port * pptr,uint32_t d_id)6168 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6169 {
6170 fc_portid_t port_id;
6171 la_wwn_t pwwn;
6172 struct fcp_tgt *ptgt = NULL;
6173
6174 port_id.priv_lilp_posit = 0;
6175 port_id.port_id = d_id;
6176 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6177 &pwwn) == FC_SUCCESS) {
6178 mutex_enter(&pptr->port_mutex);
6179 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6180 mutex_exit(&pptr->port_mutex);
6181 }
6182
6183 return (ptgt);
6184 }
6185
6186
6187 /*
6188 * the packet completion callback routine for info cmd pkts
6189 *
6190 * this means fpkt pts to a response to either a PLOGI or a PRLI
6191 *
6192 * if there is an error an attempt is made to call a routine to resend
6193 * the command that failed
6194 */
6195 static void
fcp_icmd_callback(fc_packet_t * fpkt)6196 fcp_icmd_callback(fc_packet_t *fpkt)
6197 {
6198 struct fcp_ipkt *icmd;
6199 struct fcp_port *pptr;
6200 struct fcp_tgt *ptgt;
6201 struct la_els_prli *prli;
6202 struct la_els_prli prli_s;
6203 struct fcp_prli *fprli;
6204 struct fcp_lun *plun;
6205 int free_pkt = 1;
6206 int rval;
6207 ls_code_t resp;
6208 uchar_t prli_acc = 0;
6209 uint32_t rscn_count = FC_INVALID_RSCN_COUNT;
6210 int lun0_newalloc;
6211
6212 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6213
6214 /* get ptrs to the port and target structs for the cmd */
6215 pptr = icmd->ipkt_port;
6216 ptgt = icmd->ipkt_tgt;
6217
6218 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6219
6220 if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6221 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6222 sizeof (prli_s));
6223 prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6224 }
6225
6226 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6227 fcp_trace, FCP_BUF_LEVEL_2, 0,
6228 "ELS (%x) callback state=0x%x reason=0x%x for %x",
6229 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6230 ptgt->tgt_d_id);
6231
6232 if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6233 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6234
6235 mutex_enter(&ptgt->tgt_mutex);
6236 if (ptgt->tgt_pd_handle == NULL) {
6237 /*
6238 * in a fabric environment the port device handles
6239 * get created only after successful LOGIN into the
6240 * transport, so the transport makes this port
6241 * device (pd) handle available in this packet, so
6242 * save it now
6243 */
6244 ASSERT(fpkt->pkt_pd != NULL);
6245 ptgt->tgt_pd_handle = fpkt->pkt_pd;
6246 }
6247 mutex_exit(&ptgt->tgt_mutex);
6248
6249 /* which ELS cmd is this response for ?? */
6250 switch (icmd->ipkt_opcode) {
6251 case LA_ELS_PLOGI:
6252 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6253 fcp_trace, FCP_BUF_LEVEL_5, 0,
6254 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6255 ptgt->tgt_d_id,
6256 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6257 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6258
6259 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6260 FCP_TGT_TRACE_15);
6261
6262 /* Note that we are not allocating a new icmd */
6263 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6264 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6265 icmd->ipkt_cause) != DDI_SUCCESS) {
6266 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6267 FCP_TGT_TRACE_16);
6268 goto fail;
6269 }
6270 break;
6271
6272 case LA_ELS_PRLI:
6273 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6274 fcp_trace, FCP_BUF_LEVEL_5, 0,
6275 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6276
6277 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6278 FCP_TGT_TRACE_17);
6279
6280 prli = &prli_s;
6281
6282 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6283 sizeof (prli_s));
6284
6285 fprli = (struct fcp_prli *)prli->service_params;
6286
6287 mutex_enter(&ptgt->tgt_mutex);
6288 ptgt->tgt_icap = fprli->initiator_fn;
6289 ptgt->tgt_tcap = fprli->target_fn;
6290 mutex_exit(&ptgt->tgt_mutex);
6291
6292 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6293 /*
6294 * this FCP device does not support target mode
6295 */
6296 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6297 FCP_TGT_TRACE_18);
6298 goto fail;
6299 }
6300 if (fprli->retry == 1) {
6301 fc_ulp_disable_relogin(pptr->port_fp_handle,
6302 &ptgt->tgt_port_wwn);
6303 }
6304
6305 /* target is no longer offline */
6306 mutex_enter(&pptr->port_mutex);
6307 mutex_enter(&ptgt->tgt_mutex);
6308 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6309 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6310 FCP_TGT_MARK);
6311 } else {
6312 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6313 fcp_trace, FCP_BUF_LEVEL_2, 0,
6314 "fcp_icmd_callback,1: state change "
6315 " occured for D_ID=0x%x", ptgt->tgt_d_id);
6316 mutex_exit(&ptgt->tgt_mutex);
6317 mutex_exit(&pptr->port_mutex);
6318 goto fail;
6319 }
6320 mutex_exit(&ptgt->tgt_mutex);
6321 mutex_exit(&pptr->port_mutex);
6322
6323 /*
6324 * lun 0 should always respond to inquiry, so
6325 * get the LUN struct for LUN 0
6326 *
6327 * Currently we deal with first level of addressing.
6328 * If / when we start supporting 0x device types
6329 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6330 * this logic will need revisiting.
6331 */
6332 lun0_newalloc = 0;
6333 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6334 /*
6335 * no LUN struct for LUN 0 yet exists,
6336 * so create one
6337 */
6338 plun = fcp_alloc_lun(ptgt);
6339 if (plun == NULL) {
6340 fcp_log(CE_WARN, pptr->port_dip,
6341 "!Failed to allocate lun 0 for"
6342 " D_ID=%x", ptgt->tgt_d_id);
6343 goto fail;
6344 }
6345 lun0_newalloc = 1;
6346 }
6347
6348 /* fill in LUN info */
6349 mutex_enter(&ptgt->tgt_mutex);
6350 /*
6351 * consider lun 0 as device not connected if it is
6352 * offlined or newly allocated
6353 */
6354 if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6355 lun0_newalloc) {
6356 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6357 }
6358 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6359 plun->lun_state &= ~FCP_LUN_OFFLINE;
6360 ptgt->tgt_lun_cnt = 1;
6361 ptgt->tgt_report_lun_cnt = 0;
6362 mutex_exit(&ptgt->tgt_mutex);
6363
6364 /* Retrieve the rscn count (if a valid one exists) */
6365 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6366 rscn_count = ((fc_ulp_rscn_info_t *)
6367 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6368 ->ulp_rscn_count;
6369 } else {
6370 rscn_count = FC_INVALID_RSCN_COUNT;
6371 }
6372
6373 /* send Report Lun request to target */
6374 if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6375 sizeof (struct fcp_reportlun_resp),
6376 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6377 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6378 mutex_enter(&pptr->port_mutex);
6379 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6380 fcp_log(CE_WARN, pptr->port_dip,
6381 "!Failed to send REPORT LUN to"
6382 " D_ID=%x", ptgt->tgt_d_id);
6383 } else {
6384 FCP_TRACE(fcp_logq,
6385 pptr->port_instbuf, fcp_trace,
6386 FCP_BUF_LEVEL_5, 0,
6387 "fcp_icmd_callback,2:state change"
6388 " occured for D_ID=0x%x",
6389 ptgt->tgt_d_id);
6390 }
6391 mutex_exit(&pptr->port_mutex);
6392
6393 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6394 FCP_TGT_TRACE_19);
6395
6396 goto fail;
6397 } else {
6398 free_pkt = 0;
6399 fcp_icmd_free(pptr, icmd);
6400 }
6401 break;
6402
6403 default:
6404 fcp_log(CE_WARN, pptr->port_dip,
6405 "!fcp_icmd_callback Invalid opcode");
6406 goto fail;
6407 }
6408
6409 return;
6410 }
6411
6412
6413 /*
6414 * Other PLOGI failures are not retried as the
6415 * transport does it already
6416 */
6417 if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6418 if (fcp_is_retryable(icmd) &&
6419 icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6420
6421 if (FCP_MUST_RETRY(fpkt)) {
6422 fcp_queue_ipkt(pptr, fpkt);
6423 return;
6424 }
6425
6426 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6427 fcp_trace, FCP_BUF_LEVEL_2, 0,
6428 "ELS PRLI is retried for d_id=0x%x, state=%x,"
6429 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6430 fpkt->pkt_reason);
6431
6432 /*
6433 * Retry by recalling the routine that
6434 * originally queued this packet
6435 */
6436 mutex_enter(&pptr->port_mutex);
6437 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6438 caddr_t msg;
6439
6440 mutex_exit(&pptr->port_mutex);
6441
6442 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6443
6444 if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6445 fpkt->pkt_timeout +=
6446 FCP_TIMEOUT_DELTA;
6447 }
6448
6449 rval = fc_ulp_issue_els(pptr->port_fp_handle,
6450 fpkt);
6451 if (rval == FC_SUCCESS) {
6452 return;
6453 }
6454
6455 if (rval == FC_STATEC_BUSY ||
6456 rval == FC_OFFLINE) {
6457 fcp_queue_ipkt(pptr, fpkt);
6458 return;
6459 }
6460 (void) fc_ulp_error(rval, &msg);
6461
6462 fcp_log(CE_NOTE, pptr->port_dip,
6463 "!ELS 0x%x failed to d_id=0x%x;"
6464 " %s", icmd->ipkt_opcode,
6465 ptgt->tgt_d_id, msg);
6466 } else {
6467 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6468 fcp_trace, FCP_BUF_LEVEL_2, 0,
6469 "fcp_icmd_callback,3: state change "
6470 " occured for D_ID=0x%x", ptgt->tgt_d_id);
6471 mutex_exit(&pptr->port_mutex);
6472 }
6473 }
6474 } else {
6475 if (fcp_is_retryable(icmd) &&
6476 icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6477 if (FCP_MUST_RETRY(fpkt)) {
6478 fcp_queue_ipkt(pptr, fpkt);
6479 return;
6480 }
6481 }
6482 mutex_enter(&pptr->port_mutex);
6483 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6484 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6485 mutex_exit(&pptr->port_mutex);
6486 fcp_print_error(fpkt);
6487 } else {
6488 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6489 fcp_trace, FCP_BUF_LEVEL_2, 0,
6490 "fcp_icmd_callback,4: state change occured"
6491 " for D_ID=0x%x", ptgt->tgt_d_id);
6492 mutex_exit(&pptr->port_mutex);
6493 }
6494 }
6495
6496 fail:
6497 if (free_pkt) {
6498 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6499 icmd->ipkt_change_cnt, icmd->ipkt_cause);
6500 fcp_icmd_free(pptr, icmd);
6501 }
6502 }
6503
6504
6505 /*
6506 * called internally to send an info cmd using the transport
6507 *
6508 * sends either an INQ or a REPORT_LUN
6509 *
6510 * when the packet is completed fcp_scsi_callback is called
6511 */
6512 static int
fcp_send_scsi(struct fcp_lun * plun,uchar_t opcode,int alloc_len,int lcount,int tcount,int cause,uint32_t rscn_count)6513 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6514 int lcount, int tcount, int cause, uint32_t rscn_count)
6515 {
6516 int nodma;
6517 struct fcp_ipkt *icmd;
6518 struct fcp_tgt *ptgt;
6519 struct fcp_port *pptr;
6520 fc_frame_hdr_t *hp;
6521 fc_packet_t *fpkt;
6522 struct fcp_cmd fcp_cmd;
6523 struct fcp_cmd *fcmd;
6524 union scsi_cdb *scsi_cdb;
6525
6526 ASSERT(plun != NULL);
6527
6528 ptgt = plun->lun_tgt;
6529 ASSERT(ptgt != NULL);
6530
6531 pptr = ptgt->tgt_port;
6532 ASSERT(pptr != NULL);
6533
6534 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6535 fcp_trace, FCP_BUF_LEVEL_5, 0,
6536 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6537
6538 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6539 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6540 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6541 rscn_count);
6542
6543 if (icmd == NULL) {
6544 return (DDI_FAILURE);
6545 }
6546
6547 fpkt = icmd->ipkt_fpkt;
6548 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6549 icmd->ipkt_retries = 0;
6550 icmd->ipkt_opcode = opcode;
6551 icmd->ipkt_lun = plun;
6552
6553 if (nodma) {
6554 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6555 } else {
6556 fcmd = &fcp_cmd;
6557 }
6558 bzero(fcmd, sizeof (struct fcp_cmd));
6559
6560 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6561
6562 hp = &fpkt->pkt_cmd_fhdr;
6563
6564 hp->s_id = pptr->port_id;
6565 hp->d_id = ptgt->tgt_d_id;
6566 hp->r_ctl = R_CTL_COMMAND;
6567 hp->type = FC_TYPE_SCSI_FCP;
6568 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6569 hp->rsvd = 0;
6570 hp->seq_id = 0;
6571 hp->seq_cnt = 0;
6572 hp->ox_id = 0xffff;
6573 hp->rx_id = 0xffff;
6574 hp->ro = 0;
6575
6576 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6577
6578 /*
6579 * Request SCSI target for expedited processing
6580 */
6581
6582 /*
6583 * Set up for untagged queuing because we do not
6584 * know if the fibre device supports queuing.
6585 */
6586 fcmd->fcp_cntl.cntl_reserved_0 = 0;
6587 fcmd->fcp_cntl.cntl_reserved_1 = 0;
6588 fcmd->fcp_cntl.cntl_reserved_2 = 0;
6589 fcmd->fcp_cntl.cntl_reserved_3 = 0;
6590 fcmd->fcp_cntl.cntl_reserved_4 = 0;
6591 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6592 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6593
6594 switch (opcode) {
6595 case SCMD_INQUIRY_PAGE83:
6596 /*
6597 * Prepare to get the Inquiry VPD page 83 information
6598 */
6599 fcmd->fcp_cntl.cntl_read_data = 1;
6600 fcmd->fcp_cntl.cntl_write_data = 0;
6601 fcmd->fcp_data_len = alloc_len;
6602
6603 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6604 fpkt->pkt_comp = fcp_scsi_callback;
6605
6606 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6607 scsi_cdb->g0_addr2 = 0x01;
6608 scsi_cdb->g0_addr1 = 0x83;
6609 scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6610 break;
6611
6612 case SCMD_INQUIRY:
6613 fcmd->fcp_cntl.cntl_read_data = 1;
6614 fcmd->fcp_cntl.cntl_write_data = 0;
6615 fcmd->fcp_data_len = alloc_len;
6616
6617 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6618 fpkt->pkt_comp = fcp_scsi_callback;
6619
6620 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6621 scsi_cdb->g0_count0 = SUN_INQSIZE;
6622 break;
6623
6624 case SCMD_REPORT_LUN: {
6625 fc_portid_t d_id;
6626 opaque_t fca_dev;
6627
6628 ASSERT(alloc_len >= 16);
6629
6630 d_id.priv_lilp_posit = 0;
6631 d_id.port_id = ptgt->tgt_d_id;
6632
6633 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6634
6635 mutex_enter(&ptgt->tgt_mutex);
6636 ptgt->tgt_fca_dev = fca_dev;
6637 mutex_exit(&ptgt->tgt_mutex);
6638
6639 fcmd->fcp_cntl.cntl_read_data = 1;
6640 fcmd->fcp_cntl.cntl_write_data = 0;
6641 fcmd->fcp_data_len = alloc_len;
6642
6643 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6644 fpkt->pkt_comp = fcp_scsi_callback;
6645
6646 scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6647 scsi_cdb->scc5_count0 = alloc_len & 0xff;
6648 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6649 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6650 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6651 break;
6652 }
6653
6654 default:
6655 fcp_log(CE_WARN, pptr->port_dip,
6656 "!fcp_send_scsi Invalid opcode");
6657 break;
6658 }
6659
6660 if (!nodma) {
6661 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6662 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6663 }
6664
6665 mutex_enter(&pptr->port_mutex);
6666 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6667
6668 mutex_exit(&pptr->port_mutex);
6669 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6670 FC_SUCCESS) {
6671 fcp_icmd_free(pptr, icmd);
6672 return (DDI_FAILURE);
6673 }
6674 return (DDI_SUCCESS);
6675 } else {
6676 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6677 fcp_trace, FCP_BUF_LEVEL_2, 0,
6678 "fcp_send_scsi,1: state change occured"
6679 " for D_ID=0x%x", ptgt->tgt_d_id);
6680 mutex_exit(&pptr->port_mutex);
6681 fcp_icmd_free(pptr, icmd);
6682 return (DDI_FAILURE);
6683 }
6684 }
6685
6686
6687 /*
6688 * called by fcp_scsi_callback to check to handle the case where
6689 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6690 */
6691 static int
fcp_check_reportlun(struct fcp_rsp * rsp,fc_packet_t * fpkt)6692 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6693 {
6694 uchar_t rqlen;
6695 int rval = DDI_FAILURE;
6696 struct scsi_extended_sense sense_info, *sense;
6697 struct fcp_ipkt *icmd = (struct fcp_ipkt *)
6698 fpkt->pkt_ulp_private;
6699 struct fcp_tgt *ptgt = icmd->ipkt_tgt;
6700 struct fcp_port *pptr = ptgt->tgt_port;
6701
6702 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6703
6704 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6705 /*
6706 * SCSI-II Reserve Release support. Some older FC drives return
6707 * Reservation conflict for Report Luns command.
6708 */
6709 if (icmd->ipkt_nodma) {
6710 rsp->fcp_u.fcp_status.rsp_len_set = 0;
6711 rsp->fcp_u.fcp_status.sense_len_set = 0;
6712 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6713 } else {
6714 fcp_rsp_t new_resp;
6715
6716 FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6717 fpkt->pkt_resp_acc, sizeof (new_resp));
6718
6719 new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6720 new_resp.fcp_u.fcp_status.sense_len_set = 0;
6721 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6722
6723 FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6724 fpkt->pkt_resp_acc, sizeof (new_resp));
6725 }
6726
6727 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6728 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6729
6730 return (DDI_SUCCESS);
6731 }
6732
6733 sense = &sense_info;
6734 if (!rsp->fcp_u.fcp_status.sense_len_set) {
6735 /* no need to continue if sense length is not set */
6736 return (rval);
6737 }
6738
6739 /* casting 64-bit integer to 8-bit */
6740 rqlen = (uchar_t)min(rsp->fcp_sense_len,
6741 sizeof (struct scsi_extended_sense));
6742
6743 if (rqlen < 14) {
6744 /* no need to continue if request length isn't long enough */
6745 return (rval);
6746 }
6747
6748 if (icmd->ipkt_nodma) {
6749 /*
6750 * We can safely use fcp_response_len here since the
6751 * only path that calls fcp_check_reportlun,
6752 * fcp_scsi_callback, has already called
6753 * fcp_validate_fcp_response.
6754 */
6755 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6756 sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6757 } else {
6758 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6759 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6760 sizeof (struct scsi_extended_sense));
6761 }
6762
6763 if (!FCP_SENSE_NO_LUN(sense)) {
6764 mutex_enter(&ptgt->tgt_mutex);
6765 /* clear the flag if any */
6766 ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6767 mutex_exit(&ptgt->tgt_mutex);
6768 }
6769
6770 if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6771 (sense->es_add_code == 0x20)) {
6772 if (icmd->ipkt_nodma) {
6773 rsp->fcp_u.fcp_status.rsp_len_set = 0;
6774 rsp->fcp_u.fcp_status.sense_len_set = 0;
6775 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6776 } else {
6777 fcp_rsp_t new_resp;
6778
6779 FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6780 fpkt->pkt_resp_acc, sizeof (new_resp));
6781
6782 new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6783 new_resp.fcp_u.fcp_status.sense_len_set = 0;
6784 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6785
6786 FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6787 fpkt->pkt_resp_acc, sizeof (new_resp));
6788 }
6789
6790 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6791 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6792
6793 return (DDI_SUCCESS);
6794 }
6795
6796 /*
6797 * This is for the STK library which returns a check condition,
6798 * to indicate device is not ready, manual assistance needed.
6799 * This is to a report lun command when the door is open.
6800 */
6801 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6802 if (icmd->ipkt_nodma) {
6803 rsp->fcp_u.fcp_status.rsp_len_set = 0;
6804 rsp->fcp_u.fcp_status.sense_len_set = 0;
6805 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6806 } else {
6807 fcp_rsp_t new_resp;
6808
6809 FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6810 fpkt->pkt_resp_acc, sizeof (new_resp));
6811
6812 new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6813 new_resp.fcp_u.fcp_status.sense_len_set = 0;
6814 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6815
6816 FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6817 fpkt->pkt_resp_acc, sizeof (new_resp));
6818 }
6819
6820 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6821 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6822
6823 return (DDI_SUCCESS);
6824 }
6825
6826 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6827 (FCP_SENSE_NO_LUN(sense))) {
6828 mutex_enter(&ptgt->tgt_mutex);
6829 if ((FCP_SENSE_NO_LUN(sense)) &&
6830 (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6831 ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6832 mutex_exit(&ptgt->tgt_mutex);
6833 /*
6834 * reconfig was triggred by ILLEGAL REQUEST but
6835 * got ILLEGAL REQUEST again
6836 */
6837 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6838 fcp_trace, FCP_BUF_LEVEL_3, 0,
6839 "!FCP: Unable to obtain Report Lun data"
6840 " target=%x", ptgt->tgt_d_id);
6841 } else {
6842 if (ptgt->tgt_tid == NULL) {
6843 timeout_id_t tid;
6844 /*
6845 * REPORT LUN data has changed. Kick off
6846 * rediscovery
6847 */
6848 tid = timeout(fcp_reconfigure_luns,
6849 (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6850
6851 ptgt->tgt_tid = tid;
6852 ptgt->tgt_state |= FCP_TGT_BUSY;
6853 }
6854 if (FCP_SENSE_NO_LUN(sense)) {
6855 ptgt->tgt_state |= FCP_TGT_ILLREQ;
6856 }
6857 mutex_exit(&ptgt->tgt_mutex);
6858 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6859 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6860 fcp_trace, FCP_BUF_LEVEL_3, 0,
6861 "!FCP:Report Lun Has Changed"
6862 " target=%x", ptgt->tgt_d_id);
6863 } else if (FCP_SENSE_NO_LUN(sense)) {
6864 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6865 fcp_trace, FCP_BUF_LEVEL_3, 0,
6866 "!FCP:LU Not Supported"
6867 " target=%x", ptgt->tgt_d_id);
6868 }
6869 }
6870 rval = DDI_SUCCESS;
6871 }
6872
6873 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6874 fcp_trace, FCP_BUF_LEVEL_5, 0,
6875 "D_ID=%x, sense=%x, status=%x",
6876 fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6877 rsp->fcp_u.fcp_status.scsi_status);
6878
6879 return (rval);
6880 }
6881
6882 /*
6883 * Function: fcp_scsi_callback
6884 *
6885 * Description: This is the callback routine set by fcp_send_scsi() after
6886 * it calls fcp_icmd_alloc(). The SCSI command completed here
6887 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and
6888 * INQUIRY_PAGE83.
6889 *
6890 * Argument: *fpkt FC packet used to convey the command
6891 *
6892 * Return Value: None
6893 */
6894 static void
fcp_scsi_callback(fc_packet_t * fpkt)6895 fcp_scsi_callback(fc_packet_t *fpkt)
6896 {
6897 struct fcp_ipkt *icmd = (struct fcp_ipkt *)
6898 fpkt->pkt_ulp_private;
6899 struct fcp_rsp_info fcp_rsp_err, *bep;
6900 struct fcp_port *pptr;
6901 struct fcp_tgt *ptgt;
6902 struct fcp_lun *plun;
6903 struct fcp_rsp response, *rsp;
6904
6905 ptgt = icmd->ipkt_tgt;
6906 pptr = ptgt->tgt_port;
6907 plun = icmd->ipkt_lun;
6908
6909 if (icmd->ipkt_nodma) {
6910 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6911 } else {
6912 rsp = &response;
6913 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6914 sizeof (struct fcp_rsp));
6915 }
6916
6917 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6918 fcp_trace, FCP_BUF_LEVEL_2, 0,
6919 "SCSI callback state=0x%x for %x, op_code=0x%x, "
6920 "status=%x, lun num=%x",
6921 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6922 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6923
6924 /*
6925 * Pre-init LUN GUID with NWWN if it is not a device that
6926 * supports multiple luns and we know it's not page83
6927 * compliant. Although using a NWWN is not lun unique,
6928 * we will be fine since there is only one lun behind the taget
6929 * in this case.
6930 */
6931 if ((plun->lun_guid_size == 0) &&
6932 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6933 (fcp_symmetric_device_probe(plun) == 0)) {
6934
6935 char ascii_wwn[FC_WWN_SIZE*2+1];
6936 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6937 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6938 }
6939
6940 /*
6941 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6942 * when thay have more data than what is asked in CDB. An overrun
6943 * is really when FCP_DL is smaller than the data length in CDB.
6944 * In the case here we know that REPORT LUN command we formed within
6945 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6946 * behavior. In reality this is FC_SUCCESS.
6947 */
6948 if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6949 (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6950 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6951 fpkt->pkt_state = FC_PKT_SUCCESS;
6952 }
6953
6954 if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6955 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6956 fcp_trace, FCP_BUF_LEVEL_2, 0,
6957 "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6958 ptgt->tgt_d_id);
6959
6960 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6961 /*
6962 * Inquiry VPD page command on A5K SES devices would
6963 * result in data CRC errors.
6964 */
6965 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6966 (void) fcp_handle_page83(fpkt, icmd, 1);
6967 return;
6968 }
6969 }
6970 if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6971 FCP_MUST_RETRY(fpkt)) {
6972 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6973 fcp_retry_scsi_cmd(fpkt);
6974 return;
6975 }
6976
6977 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6978 FCP_TGT_TRACE_20);
6979
6980 mutex_enter(&pptr->port_mutex);
6981 mutex_enter(&ptgt->tgt_mutex);
6982 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6983 mutex_exit(&ptgt->tgt_mutex);
6984 mutex_exit(&pptr->port_mutex);
6985 fcp_print_error(fpkt);
6986 } else {
6987 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6988 fcp_trace, FCP_BUF_LEVEL_2, 0,
6989 "fcp_scsi_callback,1: state change occured"
6990 " for D_ID=0x%x", ptgt->tgt_d_id);
6991 mutex_exit(&ptgt->tgt_mutex);
6992 mutex_exit(&pptr->port_mutex);
6993 }
6994 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6995 icmd->ipkt_change_cnt, icmd->ipkt_cause);
6996 fcp_icmd_free(pptr, icmd);
6997 return;
6998 }
6999
7000 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7001
7002 mutex_enter(&pptr->port_mutex);
7003 mutex_enter(&ptgt->tgt_mutex);
7004 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7005 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7006 fcp_trace, FCP_BUF_LEVEL_2, 0,
7007 "fcp_scsi_callback,2: state change occured"
7008 " for D_ID=0x%x", ptgt->tgt_d_id);
7009 mutex_exit(&ptgt->tgt_mutex);
7010 mutex_exit(&pptr->port_mutex);
7011 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7012 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7013 fcp_icmd_free(pptr, icmd);
7014 return;
7015 }
7016 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7017
7018 mutex_exit(&ptgt->tgt_mutex);
7019 mutex_exit(&pptr->port_mutex);
7020
7021 if (icmd->ipkt_nodma) {
7022 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7023 sizeof (struct fcp_rsp));
7024 } else {
7025 bep = &fcp_rsp_err;
7026 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7027 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7028 }
7029
7030 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7031 fcp_retry_scsi_cmd(fpkt);
7032 return;
7033 }
7034
7035 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7036 FCP_NO_FAILURE) {
7037 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7038 fcp_trace, FCP_BUF_LEVEL_2, 0,
7039 "rsp_code=0x%x, rsp_len_set=0x%x",
7040 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7041 fcp_retry_scsi_cmd(fpkt);
7042 return;
7043 }
7044
7045 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7046 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7047 fcp_queue_ipkt(pptr, fpkt);
7048 return;
7049 }
7050
7051 /*
7052 * Devices that do not support INQUIRY_PAGE83, return check condition
7053 * with illegal request as per SCSI spec.
7054 * Crossbridge is one such device and Daktari's SES node is another.
7055 * We want to ideally enumerate these devices as a non-mpxio devices.
7056 * SES nodes (Daktari only currently) are an exception to this.
7057 */
7058 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7059 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7060
7061 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7062 fcp_trace, FCP_BUF_LEVEL_3, 0,
7063 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7064 "check condition. May enumerate as non-mpxio device",
7065 ptgt->tgt_d_id, plun->lun_type);
7066
7067 /*
7068 * If we let Daktari's SES be enumerated as a non-mpxio
7069 * device, there will be a discrepency in that the other
7070 * internal FC disks will get enumerated as mpxio devices.
7071 * Applications like luxadm expect this to be consistent.
7072 *
7073 * So, we put in a hack here to check if this is an SES device
7074 * and handle it here.
7075 */
7076 if (plun->lun_type == DTYPE_ESI) {
7077 /*
7078 * Since, pkt_state is actually FC_PKT_SUCCESS
7079 * at this stage, we fake a failure here so that
7080 * fcp_handle_page83 will create a device path using
7081 * the WWN instead of the GUID which is not there anyway
7082 */
7083 fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7084 (void) fcp_handle_page83(fpkt, icmd, 1);
7085 return;
7086 }
7087
7088 mutex_enter(&ptgt->tgt_mutex);
7089 plun->lun_state &= ~(FCP_LUN_OFFLINE |
7090 FCP_LUN_MARK | FCP_LUN_BUSY);
7091 mutex_exit(&ptgt->tgt_mutex);
7092
7093 (void) fcp_call_finish_init(pptr, ptgt,
7094 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7095 icmd->ipkt_cause);
7096 fcp_icmd_free(pptr, icmd);
7097 return;
7098 }
7099
7100 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7101 int rval = DDI_FAILURE;
7102
7103 /*
7104 * handle cases where report lun isn't supported
7105 * by faking up our own REPORT_LUN response or
7106 * UNIT ATTENTION
7107 */
7108 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7109 rval = fcp_check_reportlun(rsp, fpkt);
7110
7111 /*
7112 * fcp_check_reportlun might have modified the
7113 * FCP response. Copy it in again to get an updated
7114 * FCP response
7115 */
7116 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7117 rsp = &response;
7118
7119 FCP_CP_IN(fpkt->pkt_resp, rsp,
7120 fpkt->pkt_resp_acc,
7121 sizeof (struct fcp_rsp));
7122 }
7123 }
7124
7125 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7126 if (rval == DDI_SUCCESS) {
7127 (void) fcp_call_finish_init(pptr, ptgt,
7128 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7129 icmd->ipkt_cause);
7130 fcp_icmd_free(pptr, icmd);
7131 } else {
7132 fcp_retry_scsi_cmd(fpkt);
7133 }
7134
7135 return;
7136 }
7137 } else {
7138 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7139 mutex_enter(&ptgt->tgt_mutex);
7140 ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7141 mutex_exit(&ptgt->tgt_mutex);
7142 }
7143 }
7144
7145 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7146 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7147 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7148 DDI_DMA_SYNC_FORCPU);
7149 }
7150
7151 switch (icmd->ipkt_opcode) {
7152 case SCMD_INQUIRY:
7153 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7154 fcp_handle_inquiry(fpkt, icmd);
7155 break;
7156
7157 case SCMD_REPORT_LUN:
7158 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7159 FCP_TGT_TRACE_22);
7160 fcp_handle_reportlun(fpkt, icmd);
7161 break;
7162
7163 case SCMD_INQUIRY_PAGE83:
7164 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7165 (void) fcp_handle_page83(fpkt, icmd, 0);
7166 break;
7167
7168 default:
7169 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7170 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7171 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7172 fcp_icmd_free(pptr, icmd);
7173 break;
7174 }
7175 }
7176
7177
7178 static void
fcp_retry_scsi_cmd(fc_packet_t * fpkt)7179 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7180 {
7181 struct fcp_ipkt *icmd = (struct fcp_ipkt *)
7182 fpkt->pkt_ulp_private;
7183 struct fcp_tgt *ptgt = icmd->ipkt_tgt;
7184 struct fcp_port *pptr = ptgt->tgt_port;
7185
7186 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7187 fcp_is_retryable(icmd)) {
7188 mutex_enter(&pptr->port_mutex);
7189 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7190 mutex_exit(&pptr->port_mutex);
7191 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7192 fcp_trace, FCP_BUF_LEVEL_3, 0,
7193 "Retrying %s to %x; state=%x, reason=%x",
7194 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7195 "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7196 fpkt->pkt_state, fpkt->pkt_reason);
7197
7198 fcp_queue_ipkt(pptr, fpkt);
7199 } else {
7200 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7201 fcp_trace, FCP_BUF_LEVEL_3, 0,
7202 "fcp_retry_scsi_cmd,1: state change occured"
7203 " for D_ID=0x%x", ptgt->tgt_d_id);
7204 mutex_exit(&pptr->port_mutex);
7205 (void) fcp_call_finish_init(pptr, ptgt,
7206 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7207 icmd->ipkt_cause);
7208 fcp_icmd_free(pptr, icmd);
7209 }
7210 } else {
7211 fcp_print_error(fpkt);
7212 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7213 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7214 fcp_icmd_free(pptr, icmd);
7215 }
7216 }
7217
7218 /*
7219 * Function: fcp_handle_page83
7220 *
7221 * Description: Treats the response to INQUIRY_PAGE83.
7222 *
7223 * Argument: *fpkt FC packet used to convey the command.
7224 * *icmd Original fcp_ipkt structure.
7225 * ignore_page83_data
7226 * if it's 1, that means it's a special devices's
7227 * page83 response, it should be enumerated under mpxio
7228 *
7229 * Return Value: None
7230 */
7231 static void
fcp_handle_page83(fc_packet_t * fpkt,struct fcp_ipkt * icmd,int ignore_page83_data)7232 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7233 int ignore_page83_data)
7234 {
7235 struct fcp_port *pptr;
7236 struct fcp_lun *plun;
7237 struct fcp_tgt *ptgt;
7238 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7239 int fail = 0;
7240 ddi_devid_t devid;
7241 char *guid = NULL;
7242 int ret;
7243
7244 ASSERT(icmd != NULL && fpkt != NULL);
7245
7246 pptr = icmd->ipkt_port;
7247 ptgt = icmd->ipkt_tgt;
7248 plun = icmd->ipkt_lun;
7249
7250 if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7251 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7252
7253 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7254 SCMD_MAX_INQUIRY_PAGE83_SIZE);
7255
7256 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7257 fcp_trace, FCP_BUF_LEVEL_5, 0,
7258 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7259 "dtype=0x%x, lun num=%x",
7260 pptr->port_instance, ptgt->tgt_d_id,
7261 dev_id_page[0], plun->lun_num);
7262
7263 ret = ddi_devid_scsi_encode(
7264 DEVID_SCSI_ENCODE_VERSION_LATEST,
7265 NULL, /* driver name */
7266 (unsigned char *) &plun->lun_inq, /* standard inquiry */
7267 sizeof (plun->lun_inq), /* size of standard inquiry */
7268 NULL, /* page 80 data */
7269 0, /* page 80 len */
7270 dev_id_page, /* page 83 data */
7271 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7272 &devid);
7273
7274 if (ret == DDI_SUCCESS) {
7275
7276 guid = ddi_devid_to_guid(devid);
7277
7278 if (guid) {
7279 /*
7280 * Check our current guid. If it's non null
7281 * and it has changed, we need to copy it into
7282 * lun_old_guid since we might still need it.
7283 */
7284 if (plun->lun_guid &&
7285 strcmp(guid, plun->lun_guid)) {
7286 unsigned int len;
7287
7288 /*
7289 * If the guid of the LUN changes,
7290 * reconfiguration should be triggered
7291 * to reflect the changes.
7292 * i.e. we should offline the LUN with
7293 * the old guid, and online the LUN with
7294 * the new guid.
7295 */
7296 plun->lun_state |= FCP_LUN_CHANGED;
7297
7298 if (plun->lun_old_guid) {
7299 kmem_free(plun->lun_old_guid,
7300 plun->lun_old_guid_size);
7301 }
7302
7303 len = plun->lun_guid_size;
7304 plun->lun_old_guid_size = len;
7305
7306 plun->lun_old_guid = kmem_zalloc(len,
7307 KM_NOSLEEP);
7308
7309 if (plun->lun_old_guid) {
7310 /*
7311 * The alloc was successful then
7312 * let's do the copy.
7313 */
7314 bcopy(plun->lun_guid,
7315 plun->lun_old_guid, len);
7316 } else {
7317 fail = 1;
7318 plun->lun_old_guid_size = 0;
7319 }
7320 }
7321 if (!fail) {
7322 if (fcp_copy_guid_2_lun_block(
7323 plun, guid)) {
7324 fail = 1;
7325 }
7326 }
7327 ddi_devid_free_guid(guid);
7328
7329 } else {
7330 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7331 fcp_trace, FCP_BUF_LEVEL_2, 0,
7332 "fcp_handle_page83: unable to create "
7333 "GUID");
7334
7335 /* couldn't create good guid from devid */
7336 fail = 1;
7337 }
7338 ddi_devid_free(devid);
7339
7340 } else if (ret == DDI_NOT_WELL_FORMED) {
7341 /* NULL filled data for page 83 */
7342 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7343 fcp_trace, FCP_BUF_LEVEL_2, 0,
7344 "fcp_handle_page83: retry GUID");
7345
7346 icmd->ipkt_retries = 0;
7347 fcp_retry_scsi_cmd(fpkt);
7348 return;
7349 } else {
7350 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7351 fcp_trace, FCP_BUF_LEVEL_2, 0,
7352 "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7353 ret);
7354 /*
7355 * Since the page83 validation
7356 * introduced late, we are being
7357 * tolerant to the existing devices
7358 * that already found to be working
7359 * under mpxio, like A5200's SES device,
7360 * its page83 response will not be standard-compliant,
7361 * but we still want it to be enumerated under mpxio.
7362 */
7363 if (fcp_symmetric_device_probe(plun) != 0) {
7364 fail = 1;
7365 }
7366 }
7367
7368 } else {
7369 /* bad packet state */
7370 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7371
7372 /*
7373 * For some special devices (A5K SES and Daktari's SES devices),
7374 * they should be enumerated under mpxio
7375 * or "luxadm dis" will fail
7376 */
7377 if (ignore_page83_data) {
7378 fail = 0;
7379 } else {
7380 fail = 1;
7381 }
7382 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7383 fcp_trace, FCP_BUF_LEVEL_2, 0,
7384 "!Devid page cmd failed. "
7385 "fpkt_state: %x fpkt_reason: %x",
7386 "ignore_page83: %d",
7387 fpkt->pkt_state, fpkt->pkt_reason,
7388 ignore_page83_data);
7389 }
7390
7391 mutex_enter(&pptr->port_mutex);
7392 mutex_enter(&plun->lun_mutex);
7393 /*
7394 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7395 * mismatch between lun_cip and lun_mpxio.
7396 */
7397 if (plun->lun_cip == NULL) {
7398 /*
7399 * If we don't have a guid for this lun it's because we were
7400 * unable to glean one from the page 83 response. Set the
7401 * control flag to 0 here to make sure that we don't attempt to
7402 * enumerate it under mpxio.
7403 */
7404 if (fail || pptr->port_mpxio == 0) {
7405 plun->lun_mpxio = 0;
7406 } else {
7407 plun->lun_mpxio = 1;
7408 }
7409 }
7410 mutex_exit(&plun->lun_mutex);
7411 mutex_exit(&pptr->port_mutex);
7412
7413 mutex_enter(&ptgt->tgt_mutex);
7414 plun->lun_state &=
7415 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7416 mutex_exit(&ptgt->tgt_mutex);
7417
7418 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7419 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7420
7421 fcp_icmd_free(pptr, icmd);
7422 }
7423
7424 /*
7425 * Function: fcp_handle_inquiry
7426 *
7427 * Description: Called by fcp_scsi_callback to handle the response to an
7428 * INQUIRY request.
7429 *
7430 * Argument: *fpkt FC packet used to convey the command.
7431 * *icmd Original fcp_ipkt structure.
7432 *
7433 * Return Value: None
7434 */
7435 static void
fcp_handle_inquiry(fc_packet_t * fpkt,struct fcp_ipkt * icmd)7436 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7437 {
7438 struct fcp_port *pptr;
7439 struct fcp_lun *plun;
7440 struct fcp_tgt *ptgt;
7441 uchar_t dtype;
7442 uchar_t pqual;
7443 uint32_t rscn_count = FC_INVALID_RSCN_COUNT;
7444
7445 ASSERT(icmd != NULL && fpkt != NULL);
7446
7447 pptr = icmd->ipkt_port;
7448 ptgt = icmd->ipkt_tgt;
7449 plun = icmd->ipkt_lun;
7450
7451 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7452 sizeof (struct scsi_inquiry));
7453
7454 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7455 pqual = plun->lun_inq.inq_dtype >> 5;
7456
7457 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7458 fcp_trace, FCP_BUF_LEVEL_5, 0,
7459 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7460 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7461 plun->lun_num, dtype, pqual);
7462
7463 if (pqual != 0) {
7464 /*
7465 * Non-zero peripheral qualifier
7466 */
7467 fcp_log(CE_CONT, pptr->port_dip,
7468 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7469 "Device type=0x%x Peripheral qual=0x%x\n",
7470 ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7471
7472 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7473 fcp_trace, FCP_BUF_LEVEL_5, 0,
7474 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7475 "Device type=0x%x Peripheral qual=0x%x\n",
7476 ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7477
7478 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7479
7480 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7481 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7482 fcp_icmd_free(pptr, icmd);
7483 return;
7484 }
7485
7486 /*
7487 * If the device is already initialized, check the dtype
7488 * for a change. If it has changed then update the flags
7489 * so the create_luns will offline the old device and
7490 * create the new device. Refer to bug: 4764752
7491 */
7492 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7493 plun->lun_state |= FCP_LUN_CHANGED;
7494 }
7495 plun->lun_type = plun->lun_inq.inq_dtype;
7496
7497 /*
7498 * This code is setting/initializing the throttling in the FCA
7499 * driver.
7500 */
7501 mutex_enter(&pptr->port_mutex);
7502 if (!pptr->port_notify) {
7503 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7504 uint32_t cmd = 0;
7505 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7506 ((cmd & 0xFFFFFF00 >> 8) |
7507 FCP_SVE_THROTTLE << 8));
7508 pptr->port_notify = 1;
7509 mutex_exit(&pptr->port_mutex);
7510 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7511 mutex_enter(&pptr->port_mutex);
7512 }
7513 }
7514
7515 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7516 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7517 fcp_trace, FCP_BUF_LEVEL_2, 0,
7518 "fcp_handle_inquiry,1:state change occured"
7519 " for D_ID=0x%x", ptgt->tgt_d_id);
7520 mutex_exit(&pptr->port_mutex);
7521
7522 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7523 (void) fcp_call_finish_init(pptr, ptgt,
7524 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7525 icmd->ipkt_cause);
7526 fcp_icmd_free(pptr, icmd);
7527 return;
7528 }
7529 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7530 mutex_exit(&pptr->port_mutex);
7531
7532 /* Retrieve the rscn count (if a valid one exists) */
7533 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7534 rscn_count = ((fc_ulp_rscn_info_t *)
7535 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7536 } else {
7537 rscn_count = FC_INVALID_RSCN_COUNT;
7538 }
7539
7540 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7541 SCMD_MAX_INQUIRY_PAGE83_SIZE,
7542 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7543 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7544 fcp_log(CE_WARN, NULL, "!failed to send page 83");
7545 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7546 (void) fcp_call_finish_init(pptr, ptgt,
7547 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7548 icmd->ipkt_cause);
7549 }
7550
7551 /*
7552 * Read Inquiry VPD Page 0x83 to uniquely
7553 * identify this logical unit.
7554 */
7555 fcp_icmd_free(pptr, icmd);
7556 }
7557
7558 /*
7559 * Function: fcp_handle_reportlun
7560 *
7561 * Description: Called by fcp_scsi_callback to handle the response to a
7562 * REPORT_LUN request.
7563 *
7564 * Argument: *fpkt FC packet used to convey the command.
7565 * *icmd Original fcp_ipkt structure.
7566 *
7567 * Return Value: None
7568 */
7569 static void
fcp_handle_reportlun(fc_packet_t * fpkt,struct fcp_ipkt * icmd)7570 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7571 {
7572 int i;
7573 int nluns_claimed;
7574 int nluns_bufmax;
7575 int len;
7576 uint16_t lun_num;
7577 uint32_t rscn_count = FC_INVALID_RSCN_COUNT;
7578 struct fcp_port *pptr;
7579 struct fcp_tgt *ptgt;
7580 struct fcp_lun *plun;
7581 struct fcp_reportlun_resp *report_lun;
7582
7583 pptr = icmd->ipkt_port;
7584 ptgt = icmd->ipkt_tgt;
7585 len = fpkt->pkt_datalen;
7586
7587 if ((len < FCP_LUN_HEADER) ||
7588 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7589 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7590 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7591 fcp_icmd_free(pptr, icmd);
7592 return;
7593 }
7594
7595 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7596 fpkt->pkt_datalen);
7597
7598 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7599 fcp_trace, FCP_BUF_LEVEL_5, 0,
7600 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7601 pptr->port_instance, ptgt->tgt_d_id);
7602
7603 /*
7604 * Get the number of luns (which is supplied as LUNS * 8) the
7605 * device claims it has.
7606 */
7607 nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7608
7609 /*
7610 * Get the maximum number of luns the buffer submitted can hold.
7611 */
7612 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7613
7614 /*
7615 * Due to limitations of certain hardware, we support only 16 bit LUNs
7616 */
7617 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7618 kmem_free(report_lun, len);
7619
7620 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7621 " 0x%x number of LUNs for target=%x", nluns_claimed,
7622 ptgt->tgt_d_id);
7623
7624 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7625 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7626 fcp_icmd_free(pptr, icmd);
7627 return;
7628 }
7629
7630 /*
7631 * If there are more LUNs than we have allocated memory for,
7632 * allocate more space and send down yet another report lun if
7633 * the maximum number of attempts hasn't been reached.
7634 */
7635 mutex_enter(&ptgt->tgt_mutex);
7636
7637 if ((nluns_claimed > nluns_bufmax) &&
7638 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7639
7640 struct fcp_lun *plun;
7641
7642 ptgt->tgt_report_lun_cnt++;
7643 plun = ptgt->tgt_lun;
7644 ASSERT(plun != NULL);
7645 mutex_exit(&ptgt->tgt_mutex);
7646
7647 kmem_free(report_lun, len);
7648
7649 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7650 fcp_trace, FCP_BUF_LEVEL_5, 0,
7651 "!Dynamically discovered %d LUNs for D_ID=%x",
7652 nluns_claimed, ptgt->tgt_d_id);
7653
7654 /* Retrieve the rscn count (if a valid one exists) */
7655 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7656 rscn_count = ((fc_ulp_rscn_info_t *)
7657 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7658 ulp_rscn_count;
7659 } else {
7660 rscn_count = FC_INVALID_RSCN_COUNT;
7661 }
7662
7663 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7664 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7665 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7666 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7667 (void) fcp_call_finish_init(pptr, ptgt,
7668 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7669 icmd->ipkt_cause);
7670 }
7671
7672 fcp_icmd_free(pptr, icmd);
7673 return;
7674 }
7675
7676 if (nluns_claimed > nluns_bufmax) {
7677 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7678 fcp_trace, FCP_BUF_LEVEL_5, 0,
7679 "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7680 " Number of LUNs lost=%x",
7681 ptgt->tgt_port_wwn.raw_wwn[0],
7682 ptgt->tgt_port_wwn.raw_wwn[1],
7683 ptgt->tgt_port_wwn.raw_wwn[2],
7684 ptgt->tgt_port_wwn.raw_wwn[3],
7685 ptgt->tgt_port_wwn.raw_wwn[4],
7686 ptgt->tgt_port_wwn.raw_wwn[5],
7687 ptgt->tgt_port_wwn.raw_wwn[6],
7688 ptgt->tgt_port_wwn.raw_wwn[7],
7689 nluns_claimed - nluns_bufmax);
7690
7691 nluns_claimed = nluns_bufmax;
7692 }
7693 ptgt->tgt_lun_cnt = nluns_claimed;
7694
7695 /*
7696 * Identify missing LUNs and print warning messages
7697 */
7698 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7699 int offline;
7700 int exists = 0;
7701
7702 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7703
7704 for (i = 0; i < nluns_claimed && exists == 0; i++) {
7705 uchar_t *lun_string;
7706
7707 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7708
7709 switch (lun_string[0] & 0xC0) {
7710 case FCP_LUN_ADDRESSING:
7711 case FCP_PD_ADDRESSING:
7712 case FCP_VOLUME_ADDRESSING:
7713 lun_num = ((lun_string[0] & 0x3F) << 8) |
7714 lun_string[1];
7715 if (plun->lun_num == lun_num) {
7716 exists++;
7717 break;
7718 }
7719 break;
7720
7721 default:
7722 break;
7723 }
7724 }
7725
7726 if (!exists && !offline) {
7727 mutex_exit(&ptgt->tgt_mutex);
7728
7729 mutex_enter(&pptr->port_mutex);
7730 mutex_enter(&ptgt->tgt_mutex);
7731 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7732 /*
7733 * set disappear flag when device was connected
7734 */
7735 if (!(plun->lun_state &
7736 FCP_LUN_DEVICE_NOT_CONNECTED)) {
7737 plun->lun_state |= FCP_LUN_DISAPPEARED;
7738 }
7739 mutex_exit(&ptgt->tgt_mutex);
7740 mutex_exit(&pptr->port_mutex);
7741 if (!(plun->lun_state &
7742 FCP_LUN_DEVICE_NOT_CONNECTED)) {
7743 fcp_log(CE_NOTE, pptr->port_dip,
7744 "!Lun=%x for target=%x disappeared",
7745 plun->lun_num, ptgt->tgt_d_id);
7746 }
7747 mutex_enter(&ptgt->tgt_mutex);
7748 } else {
7749 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7750 fcp_trace, FCP_BUF_LEVEL_5, 0,
7751 "fcp_handle_reportlun,1: state change"
7752 " occured for D_ID=0x%x", ptgt->tgt_d_id);
7753 mutex_exit(&ptgt->tgt_mutex);
7754 mutex_exit(&pptr->port_mutex);
7755 kmem_free(report_lun, len);
7756 (void) fcp_call_finish_init(pptr, ptgt,
7757 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7758 icmd->ipkt_cause);
7759 fcp_icmd_free(pptr, icmd);
7760 return;
7761 }
7762 } else if (exists) {
7763 /*
7764 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7765 * actually exists in REPORT_LUN response
7766 */
7767 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7768 plun->lun_state &=
7769 ~FCP_LUN_DEVICE_NOT_CONNECTED;
7770 }
7771 if (offline || plun->lun_num == 0) {
7772 if (plun->lun_state & FCP_LUN_DISAPPEARED) {
7773 plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7774 mutex_exit(&ptgt->tgt_mutex);
7775 fcp_log(CE_NOTE, pptr->port_dip,
7776 "!Lun=%x for target=%x reappeared",
7777 plun->lun_num, ptgt->tgt_d_id);
7778 mutex_enter(&ptgt->tgt_mutex);
7779 }
7780 }
7781 }
7782 }
7783
7784 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7785 mutex_exit(&ptgt->tgt_mutex);
7786
7787 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7788 fcp_trace, FCP_BUF_LEVEL_5, 0,
7789 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7790 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7791
7792 /* scan each lun */
7793 for (i = 0; i < nluns_claimed; i++) {
7794 uchar_t *lun_string;
7795
7796 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7797
7798 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7799 fcp_trace, FCP_BUF_LEVEL_5, 0,
7800 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7801 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7802 lun_string[0]);
7803
7804 switch (lun_string[0] & 0xC0) {
7805 case FCP_LUN_ADDRESSING:
7806 case FCP_PD_ADDRESSING:
7807 case FCP_VOLUME_ADDRESSING:
7808 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7809
7810 /* We will skip masked LUNs because of the blacklist. */
7811 if (fcp_lun_blacklist != NULL) {
7812 mutex_enter(&ptgt->tgt_mutex);
7813 if (fcp_should_mask(&ptgt->tgt_port_wwn,
7814 lun_num) == TRUE) {
7815 ptgt->tgt_lun_cnt--;
7816 mutex_exit(&ptgt->tgt_mutex);
7817 break;
7818 }
7819 mutex_exit(&ptgt->tgt_mutex);
7820 }
7821
7822 /* see if this LUN is already allocated */
7823 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7824 plun = fcp_alloc_lun(ptgt);
7825 if (plun == NULL) {
7826 fcp_log(CE_NOTE, pptr->port_dip,
7827 "!Lun allocation failed"
7828 " target=%x lun=%x",
7829 ptgt->tgt_d_id, lun_num);
7830 break;
7831 }
7832 }
7833
7834 mutex_enter(&plun->lun_tgt->tgt_mutex);
7835 /* convert to LUN */
7836 plun->lun_addr.ent_addr_0 =
7837 BE_16(*(uint16_t *)&(lun_string[0]));
7838 plun->lun_addr.ent_addr_1 =
7839 BE_16(*(uint16_t *)&(lun_string[2]));
7840 plun->lun_addr.ent_addr_2 =
7841 BE_16(*(uint16_t *)&(lun_string[4]));
7842 plun->lun_addr.ent_addr_3 =
7843 BE_16(*(uint16_t *)&(lun_string[6]));
7844
7845 plun->lun_num = lun_num;
7846 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7847 plun->lun_state &= ~FCP_LUN_OFFLINE;
7848 mutex_exit(&plun->lun_tgt->tgt_mutex);
7849
7850 /* Retrieve the rscn count (if a valid one exists) */
7851 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7852 rscn_count = ((fc_ulp_rscn_info_t *)
7853 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7854 ulp_rscn_count;
7855 } else {
7856 rscn_count = FC_INVALID_RSCN_COUNT;
7857 }
7858
7859 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7860 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7861 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7862 mutex_enter(&pptr->port_mutex);
7863 mutex_enter(&plun->lun_tgt->tgt_mutex);
7864 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7865 fcp_log(CE_NOTE, pptr->port_dip,
7866 "!failed to send INQUIRY"
7867 " target=%x lun=%x",
7868 ptgt->tgt_d_id, plun->lun_num);
7869 } else {
7870 FCP_TRACE(fcp_logq,
7871 pptr->port_instbuf, fcp_trace,
7872 FCP_BUF_LEVEL_5, 0,
7873 "fcp_handle_reportlun,2: state"
7874 " change occured for D_ID=0x%x",
7875 ptgt->tgt_d_id);
7876 }
7877 mutex_exit(&plun->lun_tgt->tgt_mutex);
7878 mutex_exit(&pptr->port_mutex);
7879 } else {
7880 continue;
7881 }
7882 break;
7883
7884 default:
7885 fcp_log(CE_WARN, NULL,
7886 "!Unsupported LUN Addressing method %x "
7887 "in response to REPORT_LUN", lun_string[0]);
7888 break;
7889 }
7890
7891 /*
7892 * each time through this loop we should decrement
7893 * the tmp_cnt by one -- since we go through this loop
7894 * one time for each LUN, the tmp_cnt should never be <=0
7895 */
7896 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7897 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7898 }
7899
7900 if (i == 0) {
7901 fcp_log(CE_WARN, pptr->port_dip,
7902 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7903 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7904 icmd->ipkt_change_cnt, icmd->ipkt_cause);
7905 }
7906
7907 kmem_free(report_lun, len);
7908 fcp_icmd_free(pptr, icmd);
7909 }
7910
7911
7912 /*
7913 * called internally to return a LUN given a target and a LUN number
7914 */
7915 static struct fcp_lun *
fcp_get_lun(struct fcp_tgt * ptgt,uint16_t lun_num)7916 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7917 {
7918 struct fcp_lun *plun;
7919
7920 mutex_enter(&ptgt->tgt_mutex);
7921 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7922 if (plun->lun_num == lun_num) {
7923 mutex_exit(&ptgt->tgt_mutex);
7924 return (plun);
7925 }
7926 }
7927 mutex_exit(&ptgt->tgt_mutex);
7928
7929 return (NULL);
7930 }
7931
7932
7933 /*
7934 * handle finishing one target for fcp_finish_init
7935 *
7936 * return true (non-zero) if we want finish_init to continue with the
7937 * next target
7938 *
7939 * called with the port mutex held
7940 */
7941 /*ARGSUSED*/
7942 static int
fcp_finish_tgt(struct fcp_port * pptr,struct fcp_tgt * ptgt,int link_cnt,int tgt_cnt,int cause)7943 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7944 int link_cnt, int tgt_cnt, int cause)
7945 {
7946 int rval = 1;
7947 ASSERT(pptr != NULL);
7948 ASSERT(ptgt != NULL);
7949
7950 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7951 fcp_trace, FCP_BUF_LEVEL_5, 0,
7952 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7953 ptgt->tgt_state);
7954
7955 ASSERT(mutex_owned(&pptr->port_mutex));
7956
7957 if ((pptr->port_link_cnt != link_cnt) ||
7958 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7959 /*
7960 * oh oh -- another link reset or target change
7961 * must have occurred while we are in here
7962 */
7963 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7964
7965 return (0);
7966 } else {
7967 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7968 }
7969
7970 mutex_enter(&ptgt->tgt_mutex);
7971
7972 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7973 /*
7974 * tgt is not offline -- is it marked (i.e. needs
7975 * to be offlined) ??
7976 */
7977 if (ptgt->tgt_state & FCP_TGT_MARK) {
7978 /*
7979 * this target not offline *and*
7980 * marked
7981 */
7982 ptgt->tgt_state &= ~FCP_TGT_MARK;
7983 rval = fcp_offline_target(pptr, ptgt, link_cnt,
7984 tgt_cnt, 0, 0);
7985 } else {
7986 ptgt->tgt_state &= ~FCP_TGT_BUSY;
7987
7988 /* create the LUNs */
7989 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7990 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7991 fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7992 cause);
7993 ptgt->tgt_device_created = 1;
7994 } else {
7995 fcp_update_tgt_state(ptgt, FCP_RESET,
7996 FCP_LUN_BUSY);
7997 }
7998 }
7999 }
8000
8001 mutex_exit(&ptgt->tgt_mutex);
8002
8003 return (rval);
8004 }
8005
8006
8007 /*
8008 * this routine is called to finish port initialization
8009 *
8010 * Each port has a "temp" counter -- when a state change happens (e.g.
8011 * port online), the temp count is set to the number of devices in the map.
8012 * Then, as each device gets "discovered", the temp counter is decremented
8013 * by one. When this count reaches zero we know that all of the devices
8014 * in the map have been discovered (or an error has occurred), so we can
8015 * then finish initialization -- which is done by this routine (well, this
8016 * and fcp-finish_tgt())
8017 *
8018 * acquires and releases the global mutex
8019 *
8020 * called with the port mutex owned
8021 */
8022 static void
fcp_finish_init(struct fcp_port * pptr)8023 fcp_finish_init(struct fcp_port *pptr)
8024 {
8025 #ifdef DEBUG
8026 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8027 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8028 FCP_STACK_DEPTH);
8029 #endif /* DEBUG */
8030
8031 ASSERT(mutex_owned(&pptr->port_mutex));
8032
8033 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8034 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8035 " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8036
8037 if ((pptr->port_state & FCP_STATE_ONLINING) &&
8038 !(pptr->port_state & (FCP_STATE_SUSPENDED |
8039 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8040 pptr->port_state &= ~FCP_STATE_ONLINING;
8041 pptr->port_state |= FCP_STATE_ONLINE;
8042 }
8043
8044 /* Wake up threads waiting on config done */
8045 cv_broadcast(&pptr->port_config_cv);
8046 }
8047
8048
8049 /*
8050 * called from fcp_finish_init to create the LUNs for a target
8051 *
8052 * called with the port mutex owned
8053 */
8054 static void
fcp_create_luns(struct fcp_tgt * ptgt,int link_cnt,int tgt_cnt,int cause)8055 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8056 {
8057 struct fcp_lun *plun;
8058 struct fcp_port *pptr;
8059 child_info_t *cip = NULL;
8060
8061 ASSERT(ptgt != NULL);
8062 ASSERT(mutex_owned(&ptgt->tgt_mutex));
8063
8064 pptr = ptgt->tgt_port;
8065
8066 ASSERT(pptr != NULL);
8067
8068 /* scan all LUNs for this target */
8069 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8070 if (plun->lun_state & FCP_LUN_OFFLINE) {
8071 continue;
8072 }
8073
8074 if (plun->lun_state & FCP_LUN_MARK) {
8075 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8076 fcp_trace, FCP_BUF_LEVEL_2, 0,
8077 "fcp_create_luns: offlining marked LUN!");
8078 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8079 continue;
8080 }
8081
8082 plun->lun_state &= ~FCP_LUN_BUSY;
8083
8084 /*
8085 * There are conditions in which FCP_LUN_INIT flag is cleared
8086 * but we have a valid plun->lun_cip. To cover this case also
8087 * CLEAR_BUSY whenever we have a valid lun_cip.
8088 */
8089 if (plun->lun_mpxio && plun->lun_cip &&
8090 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8091 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8092 0, 0))) {
8093 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8094 fcp_trace, FCP_BUF_LEVEL_2, 0,
8095 "fcp_create_luns: enable lun %p failed!",
8096 plun);
8097 }
8098
8099 if (plun->lun_state & FCP_LUN_INIT &&
8100 !(plun->lun_state & FCP_LUN_CHANGED)) {
8101 continue;
8102 }
8103
8104 if (cause == FCP_CAUSE_USER_CREATE) {
8105 continue;
8106 }
8107
8108 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8109 fcp_trace, FCP_BUF_LEVEL_6, 0,
8110 "create_luns: passing ONLINE elem to HP thread");
8111
8112 /*
8113 * If lun has changed, prepare for offlining the old path.
8114 * Do not offline the old path right now, since it may be
8115 * still opened.
8116 */
8117 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8118 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8119 }
8120
8121 /* pass an ONLINE element to the hotplug thread */
8122 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8123 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8124
8125 /*
8126 * We can not synchronous attach (i.e pass
8127 * NDI_ONLINE_ATTACH) here as we might be
8128 * coming from an interrupt or callback
8129 * thread.
8130 */
8131 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8132 link_cnt, tgt_cnt, 0, 0)) {
8133 fcp_log(CE_CONT, pptr->port_dip,
8134 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8135 plun->lun_tgt->tgt_d_id, plun->lun_num);
8136 }
8137 }
8138 }
8139 }
8140
8141
8142 /*
8143 * function to online/offline devices
8144 */
8145 static int
fcp_trigger_lun(struct fcp_lun * plun,child_info_t * cip,int old_mpxio,int online,int lcount,int tcount,int flags)8146 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8147 int online, int lcount, int tcount, int flags)
8148 {
8149 int rval = NDI_FAILURE;
8150 int circ;
8151 child_info_t *ccip;
8152 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
8153 int is_mpxio = pptr->port_mpxio;
8154 dev_info_t *cdip, *pdip;
8155 char *devname;
8156
8157 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8158 /*
8159 * When this event gets serviced, lun_cip and lun_mpxio
8160 * has changed, so it should be invalidated now.
8161 */
8162 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8163 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8164 "plun: %p, cip: %p, what:%d", plun, cip, online);
8165 return (rval);
8166 }
8167
8168 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8169 fcp_trace, FCP_BUF_LEVEL_2, 0,
8170 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8171 "flags=%x mpxio=%x\n",
8172 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8173 plun->lun_mpxio);
8174
8175 /*
8176 * lun_mpxio needs checking here because we can end up in a race
8177 * condition where this task has been dispatched while lun_mpxio is
8178 * set, but an earlier FCP_ONLINE task for the same LUN tried to
8179 * enable MPXIO for the LUN, but was unable to, and hence cleared
8180 * the flag. We rely on the serialization of the tasks here. We return
8181 * NDI_SUCCESS so any callers continue without reporting spurious
8182 * errors, and the still think we're an MPXIO LUN.
8183 */
8184
8185 if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8186 online == FCP_MPXIO_PATH_SET_BUSY) {
8187 if (plun->lun_mpxio) {
8188 rval = fcp_update_mpxio_path(plun, cip, online);
8189 } else {
8190 rval = NDI_SUCCESS;
8191 }
8192 return (rval);
8193 }
8194
8195 /*
8196 * Explicit devfs_clean() due to ndi_devi_offline() not
8197 * executing devfs_clean() if parent lock is held.
8198 */
8199 ASSERT(!servicing_interrupt());
8200 if (online == FCP_OFFLINE) {
8201 if (plun->lun_mpxio == 0) {
8202 if (plun->lun_cip == cip) {
8203 cdip = DIP(plun->lun_cip);
8204 } else {
8205 cdip = DIP(cip);
8206 }
8207 } else if ((plun->lun_cip == cip) && plun->lun_cip) {
8208 cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8209 } else if ((plun->lun_cip != cip) && cip) {
8210 /*
8211 * This means a DTYPE/GUID change, we shall get the
8212 * dip of the old cip instead of the current lun_cip.
8213 */
8214 cdip = mdi_pi_get_client(PIP(cip));
8215 }
8216 if (cdip) {
8217 if (i_ddi_devi_attached(cdip)) {
8218 pdip = ddi_get_parent(cdip);
8219 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8220 ndi_devi_enter(pdip, &circ);
8221 (void) ddi_deviname(cdip, devname);
8222 ndi_devi_exit(pdip, circ);
8223 /*
8224 * Release parent lock before calling
8225 * devfs_clean().
8226 */
8227 rval = devfs_clean(pdip, devname + 1,
8228 DV_CLEAN_FORCE);
8229 kmem_free(devname, MAXNAMELEN + 1);
8230 /*
8231 * Return if devfs_clean() fails for
8232 * non-MPXIO case.
8233 * For MPXIO case, another path could be
8234 * offlined.
8235 */
8236 if (rval && plun->lun_mpxio == 0) {
8237 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8238 fcp_trace, FCP_BUF_LEVEL_3, 0,
8239 "fcp_trigger_lun: devfs_clean "
8240 "failed rval=%x dip=%p",
8241 rval, pdip);
8242 return (NDI_FAILURE);
8243 }
8244 }
8245 }
8246 }
8247
8248 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8249 return (NDI_FAILURE);
8250 }
8251
8252 if (is_mpxio) {
8253 mdi_devi_enter(pptr->port_dip, &circ);
8254 } else {
8255 ndi_devi_enter(pptr->port_dip, &circ);
8256 }
8257
8258 mutex_enter(&pptr->port_mutex);
8259 mutex_enter(&plun->lun_mutex);
8260
8261 if (online == FCP_ONLINE) {
8262 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8263 if (ccip == NULL) {
8264 goto fail;
8265 }
8266 } else {
8267 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8268 goto fail;
8269 }
8270 ccip = cip;
8271 }
8272
8273 if (online == FCP_ONLINE) {
8274 rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8275 &circ);
8276 fc_ulp_log_device_event(pptr->port_fp_handle,
8277 FC_ULP_DEVICE_ONLINE);
8278 } else {
8279 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8280 &circ);
8281 fc_ulp_log_device_event(pptr->port_fp_handle,
8282 FC_ULP_DEVICE_OFFLINE);
8283 }
8284
8285 fail: mutex_exit(&plun->lun_mutex);
8286 mutex_exit(&pptr->port_mutex);
8287
8288 if (is_mpxio) {
8289 mdi_devi_exit(pptr->port_dip, circ);
8290 } else {
8291 ndi_devi_exit(pptr->port_dip, circ);
8292 }
8293
8294 fc_ulp_idle_port(pptr->port_fp_handle);
8295
8296 return (rval);
8297 }
8298
8299
8300 /*
8301 * take a target offline by taking all of its LUNs offline
8302 */
8303 /*ARGSUSED*/
8304 static int
fcp_offline_target(struct fcp_port * pptr,struct fcp_tgt * ptgt,int link_cnt,int tgt_cnt,int nowait,int flags)8305 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8306 int link_cnt, int tgt_cnt, int nowait, int flags)
8307 {
8308 struct fcp_tgt_elem *elem;
8309
8310 ASSERT(mutex_owned(&pptr->port_mutex));
8311 ASSERT(mutex_owned(&ptgt->tgt_mutex));
8312
8313 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8314
8315 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8316 ptgt->tgt_change_cnt)) {
8317 mutex_exit(&ptgt->tgt_mutex);
8318 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8319 mutex_enter(&ptgt->tgt_mutex);
8320
8321 return (0);
8322 }
8323
8324 ptgt->tgt_pd_handle = NULL;
8325 mutex_exit(&ptgt->tgt_mutex);
8326 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8327 mutex_enter(&ptgt->tgt_mutex);
8328
8329 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8330
8331 if (ptgt->tgt_tcap &&
8332 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8333 elem->flags = flags;
8334 elem->time = fcp_watchdog_time;
8335 if (nowait == 0) {
8336 elem->time += fcp_offline_delay;
8337 }
8338 elem->ptgt = ptgt;
8339 elem->link_cnt = link_cnt;
8340 elem->tgt_cnt = tgt_cnt;
8341 elem->next = pptr->port_offline_tgts;
8342 pptr->port_offline_tgts = elem;
8343 } else {
8344 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8345 }
8346
8347 return (1);
8348 }
8349
8350
8351 static void
fcp_offline_target_now(struct fcp_port * pptr,struct fcp_tgt * ptgt,int link_cnt,int tgt_cnt,int flags)8352 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8353 int link_cnt, int tgt_cnt, int flags)
8354 {
8355 ASSERT(mutex_owned(&pptr->port_mutex));
8356 ASSERT(mutex_owned(&ptgt->tgt_mutex));
8357
8358 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8359 ptgt->tgt_state = FCP_TGT_OFFLINE;
8360 ptgt->tgt_pd_handle = NULL;
8361 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8362 }
8363
8364
8365 static void
fcp_offline_tgt_luns(struct fcp_tgt * ptgt,int link_cnt,int tgt_cnt,int flags)8366 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8367 int flags)
8368 {
8369 struct fcp_lun *plun;
8370
8371 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8372 ASSERT(mutex_owned(&ptgt->tgt_mutex));
8373
8374 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8375 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8376 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8377 }
8378 }
8379 }
8380
8381
8382 /*
8383 * take a LUN offline
8384 *
8385 * enters and leaves with the target mutex held, releasing it in the process
8386 *
8387 * allocates memory in non-sleep mode
8388 */
8389 static void
fcp_offline_lun(struct fcp_lun * plun,int link_cnt,int tgt_cnt,int nowait,int flags)8390 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8391 int nowait, int flags)
8392 {
8393 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
8394 struct fcp_lun_elem *elem;
8395
8396 ASSERT(plun != NULL);
8397 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8398
8399 if (nowait) {
8400 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8401 return;
8402 }
8403
8404 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8405 elem->flags = flags;
8406 elem->time = fcp_watchdog_time;
8407 if (nowait == 0) {
8408 elem->time += fcp_offline_delay;
8409 }
8410 elem->plun = plun;
8411 elem->link_cnt = link_cnt;
8412 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8413 elem->next = pptr->port_offline_luns;
8414 pptr->port_offline_luns = elem;
8415 } else {
8416 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8417 }
8418 }
8419
8420
8421 static void
fcp_prepare_offline_lun(struct fcp_lun * plun,int link_cnt,int tgt_cnt)8422 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8423 {
8424 struct fcp_pkt *head = NULL;
8425
8426 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8427
8428 mutex_exit(&LUN_TGT->tgt_mutex);
8429
8430 head = fcp_scan_commands(plun);
8431 if (head != NULL) {
8432 fcp_abort_commands(head, LUN_PORT);
8433 }
8434
8435 mutex_enter(&LUN_TGT->tgt_mutex);
8436
8437 if (plun->lun_cip && plun->lun_mpxio) {
8438 /*
8439 * Intimate MPxIO lun busy is cleared
8440 */
8441 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8442 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8443 0, 0)) {
8444 fcp_log(CE_NOTE, LUN_PORT->port_dip,
8445 "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8446 LUN_TGT->tgt_d_id, plun->lun_num);
8447 }
8448 /*
8449 * Intimate MPxIO that the lun is now marked for offline
8450 */
8451 mutex_exit(&LUN_TGT->tgt_mutex);
8452 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8453 mutex_enter(&LUN_TGT->tgt_mutex);
8454 }
8455 }
8456
8457 static void
fcp_offline_lun_now(struct fcp_lun * plun,int link_cnt,int tgt_cnt,int flags)8458 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8459 int flags)
8460 {
8461 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8462
8463 mutex_exit(&LUN_TGT->tgt_mutex);
8464 fcp_update_offline_flags(plun);
8465 mutex_enter(&LUN_TGT->tgt_mutex);
8466
8467 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8468
8469 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8470 fcp_trace, FCP_BUF_LEVEL_4, 0,
8471 "offline_lun: passing OFFLINE elem to HP thread");
8472
8473 if (plun->lun_cip) {
8474 fcp_log(CE_NOTE, LUN_PORT->port_dip,
8475 "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8476 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8477 LUN_TGT->tgt_trace);
8478
8479 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8480 link_cnt, tgt_cnt, flags, 0)) {
8481 fcp_log(CE_CONT, LUN_PORT->port_dip,
8482 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8483 LUN_TGT->tgt_d_id, plun->lun_num);
8484 }
8485 }
8486 }
8487
8488 static void
fcp_scan_offline_luns(struct fcp_port * pptr)8489 fcp_scan_offline_luns(struct fcp_port *pptr)
8490 {
8491 struct fcp_lun_elem *elem;
8492 struct fcp_lun_elem *prev;
8493 struct fcp_lun_elem *next;
8494
8495 ASSERT(MUTEX_HELD(&pptr->port_mutex));
8496
8497 prev = NULL;
8498 elem = pptr->port_offline_luns;
8499 while (elem) {
8500 next = elem->next;
8501 if (elem->time <= fcp_watchdog_time) {
8502 int changed = 1;
8503 struct fcp_tgt *ptgt = elem->plun->lun_tgt;
8504
8505 mutex_enter(&ptgt->tgt_mutex);
8506 if (pptr->port_link_cnt == elem->link_cnt &&
8507 ptgt->tgt_change_cnt == elem->tgt_cnt) {
8508 changed = 0;
8509 }
8510
8511 if (!changed &&
8512 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8513 fcp_offline_lun_now(elem->plun,
8514 elem->link_cnt, elem->tgt_cnt, elem->flags);
8515 }
8516 mutex_exit(&ptgt->tgt_mutex);
8517
8518 kmem_free(elem, sizeof (*elem));
8519
8520 if (prev) {
8521 prev->next = next;
8522 } else {
8523 pptr->port_offline_luns = next;
8524 }
8525 } else {
8526 prev = elem;
8527 }
8528 elem = next;
8529 }
8530 }
8531
8532
8533 static void
fcp_scan_offline_tgts(struct fcp_port * pptr)8534 fcp_scan_offline_tgts(struct fcp_port *pptr)
8535 {
8536 struct fcp_tgt_elem *elem;
8537 struct fcp_tgt_elem *prev;
8538 struct fcp_tgt_elem *next;
8539
8540 ASSERT(MUTEX_HELD(&pptr->port_mutex));
8541
8542 prev = NULL;
8543 elem = pptr->port_offline_tgts;
8544 while (elem) {
8545 next = elem->next;
8546 if (elem->time <= fcp_watchdog_time) {
8547 int outdated = 1;
8548 struct fcp_tgt *ptgt = elem->ptgt;
8549
8550 mutex_enter(&ptgt->tgt_mutex);
8551
8552 if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8553 /* No change on tgt since elem was created. */
8554 outdated = 0;
8555 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8556 pptr->port_link_cnt == elem->link_cnt + 1 &&
8557 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8558 /*
8559 * Exactly one thing happened to the target
8560 * inbetween: the local port went offline.
8561 * For fp the remote port is already gone so
8562 * it will not tell us again to offline the
8563 * target. We must offline it now.
8564 */
8565 outdated = 0;
8566 }
8567
8568 if (!outdated && !(ptgt->tgt_state &
8569 FCP_TGT_OFFLINE)) {
8570 fcp_offline_target_now(pptr,
8571 ptgt, elem->link_cnt, elem->tgt_cnt,
8572 elem->flags);
8573 }
8574
8575 mutex_exit(&ptgt->tgt_mutex);
8576
8577 kmem_free(elem, sizeof (*elem));
8578
8579 if (prev) {
8580 prev->next = next;
8581 } else {
8582 pptr->port_offline_tgts = next;
8583 }
8584 } else {
8585 prev = elem;
8586 }
8587 elem = next;
8588 }
8589 }
8590
8591
8592 static void
fcp_update_offline_flags(struct fcp_lun * plun)8593 fcp_update_offline_flags(struct fcp_lun *plun)
8594 {
8595 struct fcp_port *pptr = LUN_PORT;
8596 ASSERT(plun != NULL);
8597
8598 mutex_enter(&LUN_TGT->tgt_mutex);
8599 plun->lun_state |= FCP_LUN_OFFLINE;
8600 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8601
8602 mutex_enter(&plun->lun_mutex);
8603 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8604 dev_info_t *cdip = NULL;
8605
8606 mutex_exit(&LUN_TGT->tgt_mutex);
8607
8608 if (plun->lun_mpxio == 0) {
8609 cdip = DIP(plun->lun_cip);
8610 } else if (plun->lun_cip) {
8611 cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8612 }
8613
8614 mutex_exit(&plun->lun_mutex);
8615 if (cdip) {
8616 (void) ndi_event_retrieve_cookie(
8617 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8618 &fcp_remove_eid, NDI_EVENT_NOPASS);
8619 (void) ndi_event_run_callbacks(
8620 pptr->port_ndi_event_hdl, cdip,
8621 fcp_remove_eid, NULL);
8622 }
8623 } else {
8624 mutex_exit(&plun->lun_mutex);
8625 mutex_exit(&LUN_TGT->tgt_mutex);
8626 }
8627 }
8628
8629
8630 /*
8631 * Scan all of the command pkts for this port, moving pkts that
8632 * match our LUN onto our own list (headed by "head")
8633 */
8634 static struct fcp_pkt *
fcp_scan_commands(struct fcp_lun * plun)8635 fcp_scan_commands(struct fcp_lun *plun)
8636 {
8637 struct fcp_port *pptr = LUN_PORT;
8638
8639 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */
8640 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */
8641 struct fcp_pkt *pcmd = NULL; /* the previous command */
8642
8643 struct fcp_pkt *head = NULL; /* head of our list */
8644 struct fcp_pkt *tail = NULL; /* tail of our list */
8645
8646 int cmds_found = 0;
8647
8648 mutex_enter(&pptr->port_pkt_mutex);
8649 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8650 struct fcp_lun *tlun =
8651 ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8652
8653 ncmd = cmd->cmd_next; /* set next command */
8654
8655 /*
8656 * if this pkt is for a different LUN or the
8657 * command is sent down, skip it.
8658 */
8659 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8660 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8661 pcmd = cmd;
8662 continue;
8663 }
8664 cmds_found++;
8665 if (pcmd != NULL) {
8666 ASSERT(pptr->port_pkt_head != cmd);
8667 pcmd->cmd_next = cmd->cmd_next;
8668 } else {
8669 ASSERT(cmd == pptr->port_pkt_head);
8670 pptr->port_pkt_head = cmd->cmd_next;
8671 }
8672
8673 if (cmd == pptr->port_pkt_tail) {
8674 pptr->port_pkt_tail = pcmd;
8675 if (pcmd) {
8676 pcmd->cmd_next = NULL;
8677 }
8678 }
8679
8680 if (head == NULL) {
8681 head = tail = cmd;
8682 } else {
8683 ASSERT(tail != NULL);
8684
8685 tail->cmd_next = cmd;
8686 tail = cmd;
8687 }
8688 cmd->cmd_next = NULL;
8689 }
8690 mutex_exit(&pptr->port_pkt_mutex);
8691
8692 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8693 fcp_trace, FCP_BUF_LEVEL_8, 0,
8694 "scan commands: %d cmd(s) found", cmds_found);
8695
8696 return (head);
8697 }
8698
8699
8700 /*
8701 * Abort all the commands in the command queue
8702 */
8703 static void
fcp_abort_commands(struct fcp_pkt * head,struct fcp_port * pptr)8704 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8705 {
8706 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */
8707 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */
8708
8709 ASSERT(mutex_owned(&pptr->port_mutex));
8710
8711 /* scan through the pkts and invalid them */
8712 for (cmd = head; cmd != NULL; cmd = ncmd) {
8713 struct scsi_pkt *pkt = cmd->cmd_pkt;
8714
8715 ncmd = cmd->cmd_next;
8716 ASSERT(pkt != NULL);
8717
8718 /*
8719 * The lun is going to be marked offline. Indicate
8720 * the target driver not to requeue or retry this command
8721 * as the device is going to be offlined pretty soon.
8722 */
8723 pkt->pkt_reason = CMD_DEV_GONE;
8724 pkt->pkt_statistics = 0;
8725 pkt->pkt_state = 0;
8726
8727 /* reset cmd flags/state */
8728 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8729 cmd->cmd_state = FCP_PKT_IDLE;
8730
8731 /*
8732 * ensure we have a packet completion routine,
8733 * then call it.
8734 */
8735 ASSERT(pkt->pkt_comp != NULL);
8736
8737 mutex_exit(&pptr->port_mutex);
8738 fcp_post_callback(cmd);
8739 mutex_enter(&pptr->port_mutex);
8740 }
8741 }
8742
8743
8744 /*
8745 * the pkt_comp callback for command packets
8746 */
8747 static void
fcp_cmd_callback(fc_packet_t * fpkt)8748 fcp_cmd_callback(fc_packet_t *fpkt)
8749 {
8750 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8751 struct scsi_pkt *pkt = cmd->cmd_pkt;
8752 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8753
8754 ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8755
8756 if (cmd->cmd_state == FCP_PKT_IDLE) {
8757 cmn_err(CE_PANIC, "Packet already completed %p",
8758 (void *)cmd);
8759 }
8760
8761 /*
8762 * Watch thread should be freeing the packet, ignore the pkt.
8763 */
8764 if (cmd->cmd_state == FCP_PKT_ABORTING) {
8765 fcp_log(CE_CONT, pptr->port_dip,
8766 "!FCP: Pkt completed while aborting\n");
8767 return;
8768 }
8769 cmd->cmd_state = FCP_PKT_IDLE;
8770
8771 fcp_complete_pkt(fpkt);
8772
8773 #ifdef DEBUG
8774 mutex_enter(&pptr->port_pkt_mutex);
8775 pptr->port_npkts--;
8776 mutex_exit(&pptr->port_pkt_mutex);
8777 #endif /* DEBUG */
8778
8779 fcp_post_callback(cmd);
8780 }
8781
8782
8783 static void
fcp_complete_pkt(fc_packet_t * fpkt)8784 fcp_complete_pkt(fc_packet_t *fpkt)
8785 {
8786 int error = 0;
8787 struct fcp_pkt *cmd = (struct fcp_pkt *)
8788 fpkt->pkt_ulp_private;
8789 struct scsi_pkt *pkt = cmd->cmd_pkt;
8790 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8791 struct fcp_lun *plun;
8792 struct fcp_tgt *ptgt;
8793 struct fcp_rsp *rsp;
8794 struct scsi_address save;
8795
8796 #ifdef DEBUG
8797 save = pkt->pkt_address;
8798 #endif /* DEBUG */
8799
8800 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8801
8802 if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8803 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8804 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8805 sizeof (struct fcp_rsp));
8806 }
8807
8808 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8809 STATE_SENT_CMD | STATE_GOT_STATUS;
8810
8811 pkt->pkt_resid = 0;
8812
8813 if (fpkt->pkt_datalen) {
8814 pkt->pkt_state |= STATE_XFERRED_DATA;
8815 if (fpkt->pkt_data_resid) {
8816 error++;
8817 }
8818 }
8819
8820 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8821 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8822 /*
8823 * The next two checks make sure that if there
8824 * is no sense data or a valid response and
8825 * the command came back with check condition,
8826 * the command should be retried.
8827 */
8828 if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8829 !rsp->fcp_u.fcp_status.sense_len_set) {
8830 pkt->pkt_state &= ~STATE_XFERRED_DATA;
8831 pkt->pkt_resid = cmd->cmd_dmacount;
8832 }
8833 }
8834
8835 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8836 return;
8837 }
8838
8839 plun = ADDR2LUN(&pkt->pkt_address);
8840 ptgt = plun->lun_tgt;
8841 ASSERT(ptgt != NULL);
8842
8843 /*
8844 * Update the transfer resid, if appropriate
8845 */
8846 if (rsp->fcp_u.fcp_status.resid_over ||
8847 rsp->fcp_u.fcp_status.resid_under) {
8848 pkt->pkt_resid = rsp->fcp_resid;
8849 }
8850
8851 /*
8852 * First see if we got a FCP protocol error.
8853 */
8854 if (rsp->fcp_u.fcp_status.rsp_len_set) {
8855 struct fcp_rsp_info *bep;
8856 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8857 sizeof (struct fcp_rsp));
8858
8859 if (fcp_validate_fcp_response(rsp, pptr) !=
8860 FC_SUCCESS) {
8861 pkt->pkt_reason = CMD_CMPLT;
8862 *(pkt->pkt_scbp) = STATUS_CHECK;
8863
8864 fcp_log(CE_WARN, pptr->port_dip,
8865 "!SCSI command to d_id=0x%x lun=0x%x"
8866 " failed, Bad FCP response values:"
8867 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8868 " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8869 ptgt->tgt_d_id, plun->lun_num,
8870 rsp->reserved_0, rsp->reserved_1,
8871 rsp->fcp_u.fcp_status.reserved_0,
8872 rsp->fcp_u.fcp_status.reserved_1,
8873 rsp->fcp_response_len, rsp->fcp_sense_len);
8874
8875 return;
8876 }
8877
8878 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8879 FCP_CP_IN(fpkt->pkt_resp +
8880 sizeof (struct fcp_rsp), bep,
8881 fpkt->pkt_resp_acc,
8882 sizeof (struct fcp_rsp_info));
8883 }
8884
8885 if (bep->rsp_code != FCP_NO_FAILURE) {
8886 child_info_t *cip;
8887
8888 pkt->pkt_reason = CMD_TRAN_ERR;
8889
8890 mutex_enter(&plun->lun_mutex);
8891 cip = plun->lun_cip;
8892 mutex_exit(&plun->lun_mutex);
8893
8894 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8895 fcp_trace, FCP_BUF_LEVEL_2, 0,
8896 "FCP response error on cmd=%p"
8897 " target=0x%x, cip=%p", cmd,
8898 ptgt->tgt_d_id, cip);
8899 }
8900 }
8901
8902 /*
8903 * See if we got a SCSI error with sense data
8904 */
8905 if (rsp->fcp_u.fcp_status.sense_len_set) {
8906 uchar_t rqlen;
8907 caddr_t sense_from;
8908 child_info_t *cip;
8909 timeout_id_t tid;
8910 struct scsi_arq_status *arq;
8911 struct scsi_extended_sense *sense_to;
8912
8913 arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8914 sense_to = &arq->sts_sensedata;
8915
8916 rqlen = (uchar_t)min(rsp->fcp_sense_len,
8917 sizeof (struct scsi_extended_sense));
8918
8919 sense_from = (caddr_t)fpkt->pkt_resp +
8920 sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8921
8922 if (fcp_validate_fcp_response(rsp, pptr) !=
8923 FC_SUCCESS) {
8924 pkt->pkt_reason = CMD_CMPLT;
8925 *(pkt->pkt_scbp) = STATUS_CHECK;
8926
8927 fcp_log(CE_WARN, pptr->port_dip,
8928 "!SCSI command to d_id=0x%x lun=0x%x"
8929 " failed, Bad FCP response values:"
8930 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8931 " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8932 ptgt->tgt_d_id, plun->lun_num,
8933 rsp->reserved_0, rsp->reserved_1,
8934 rsp->fcp_u.fcp_status.reserved_0,
8935 rsp->fcp_u.fcp_status.reserved_1,
8936 rsp->fcp_response_len, rsp->fcp_sense_len);
8937
8938 return;
8939 }
8940
8941 /*
8942 * copy in sense information
8943 */
8944 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8945 FCP_CP_IN(sense_from, sense_to,
8946 fpkt->pkt_resp_acc, rqlen);
8947 } else {
8948 bcopy(sense_from, sense_to, rqlen);
8949 }
8950
8951 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8952 (FCP_SENSE_NO_LUN(sense_to))) {
8953 mutex_enter(&ptgt->tgt_mutex);
8954 if (ptgt->tgt_tid == NULL) {
8955 /*
8956 * Kick off rediscovery
8957 */
8958 tid = timeout(fcp_reconfigure_luns,
8959 (caddr_t)ptgt, drv_usectohz(1));
8960
8961 ptgt->tgt_tid = tid;
8962 ptgt->tgt_state |= FCP_TGT_BUSY;
8963 }
8964 mutex_exit(&ptgt->tgt_mutex);
8965 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8966 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8967 fcp_trace, FCP_BUF_LEVEL_3, 0,
8968 "!FCP: Report Lun Has Changed"
8969 " target=%x", ptgt->tgt_d_id);
8970 } else if (FCP_SENSE_NO_LUN(sense_to)) {
8971 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8972 fcp_trace, FCP_BUF_LEVEL_3, 0,
8973 "!FCP: LU Not Supported"
8974 " target=%x", ptgt->tgt_d_id);
8975 }
8976 }
8977 ASSERT(pkt->pkt_scbp != NULL);
8978
8979 pkt->pkt_state |= STATE_ARQ_DONE;
8980
8981 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8982
8983 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8984 arq->sts_rqpkt_reason = 0;
8985 arq->sts_rqpkt_statistics = 0;
8986
8987 arq->sts_rqpkt_state = STATE_GOT_BUS |
8988 STATE_GOT_TARGET | STATE_SENT_CMD |
8989 STATE_GOT_STATUS | STATE_ARQ_DONE |
8990 STATE_XFERRED_DATA;
8991
8992 mutex_enter(&plun->lun_mutex);
8993 cip = plun->lun_cip;
8994 mutex_exit(&plun->lun_mutex);
8995
8996 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8997 fcp_trace, FCP_BUF_LEVEL_8, 0,
8998 "SCSI Check condition on cmd=%p target=0x%x"
8999 " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
9000 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
9001 cmd->cmd_fcp_cmd.fcp_cdb[0],
9002 rsp->fcp_u.fcp_status.scsi_status,
9003 sense_to->es_key, sense_to->es_add_code,
9004 sense_to->es_qual_code);
9005 }
9006 } else {
9007 plun = ADDR2LUN(&pkt->pkt_address);
9008 ptgt = plun->lun_tgt;
9009 ASSERT(ptgt != NULL);
9010
9011 /*
9012 * Work harder to translate errors into target driver
9013 * understandable ones. Note with despair that the target
9014 * drivers don't decode pkt_state and pkt_reason exhaustively
9015 * They resort to using the big hammer most often, which
9016 * may not get fixed in the life time of this driver.
9017 */
9018 pkt->pkt_state = 0;
9019 pkt->pkt_statistics = 0;
9020
9021 switch (fpkt->pkt_state) {
9022 case FC_PKT_TRAN_ERROR:
9023 switch (fpkt->pkt_reason) {
9024 case FC_REASON_OVERRUN:
9025 pkt->pkt_reason = CMD_CMD_OVR;
9026 pkt->pkt_statistics |= STAT_ABORTED;
9027 break;
9028
9029 case FC_REASON_XCHG_BSY: {
9030 caddr_t ptr;
9031
9032 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9033
9034 ptr = (caddr_t)pkt->pkt_scbp;
9035 if (ptr) {
9036 *ptr = STATUS_BUSY;
9037 }
9038 break;
9039 }
9040
9041 case FC_REASON_ABORTED:
9042 pkt->pkt_reason = CMD_TRAN_ERR;
9043 pkt->pkt_statistics |= STAT_ABORTED;
9044 break;
9045
9046 case FC_REASON_ABORT_FAILED:
9047 pkt->pkt_reason = CMD_ABORT_FAIL;
9048 break;
9049
9050 case FC_REASON_NO_SEQ_INIT:
9051 case FC_REASON_CRC_ERROR:
9052 pkt->pkt_reason = CMD_TRAN_ERR;
9053 pkt->pkt_statistics |= STAT_ABORTED;
9054 break;
9055 default:
9056 pkt->pkt_reason = CMD_TRAN_ERR;
9057 break;
9058 }
9059 break;
9060
9061 case FC_PKT_PORT_OFFLINE: {
9062 dev_info_t *cdip = NULL;
9063 caddr_t ptr;
9064
9065 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9066 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9067 fcp_trace, FCP_BUF_LEVEL_8, 0,
9068 "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9069 ptgt->tgt_d_id);
9070 }
9071
9072 mutex_enter(&plun->lun_mutex);
9073 if (plun->lun_mpxio == 0) {
9074 cdip = DIP(plun->lun_cip);
9075 } else if (plun->lun_cip) {
9076 cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9077 }
9078
9079 mutex_exit(&plun->lun_mutex);
9080
9081 if (cdip) {
9082 (void) ndi_event_retrieve_cookie(
9083 pptr->port_ndi_event_hdl, cdip,
9084 FCAL_REMOVE_EVENT, &fcp_remove_eid,
9085 NDI_EVENT_NOPASS);
9086 (void) ndi_event_run_callbacks(
9087 pptr->port_ndi_event_hdl, cdip,
9088 fcp_remove_eid, NULL);
9089 }
9090
9091 /*
9092 * If the link goes off-line for a lip,
9093 * this will cause a error to the ST SG
9094 * SGEN drivers. By setting BUSY we will
9095 * give the drivers the chance to retry
9096 * before it blows of the job. ST will
9097 * remember how many times it has retried.
9098 */
9099
9100 if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9101 (plun->lun_type == DTYPE_CHANGER)) {
9102 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9103 ptr = (caddr_t)pkt->pkt_scbp;
9104 if (ptr) {
9105 *ptr = STATUS_BUSY;
9106 }
9107 } else {
9108 pkt->pkt_reason = CMD_TRAN_ERR;
9109 pkt->pkt_statistics |= STAT_BUS_RESET;
9110 }
9111 break;
9112 }
9113
9114 case FC_PKT_TRAN_BSY:
9115 /*
9116 * Use the ssd Qfull handling here.
9117 */
9118 *pkt->pkt_scbp = STATUS_INTERMEDIATE;
9119 pkt->pkt_state = STATE_GOT_BUS;
9120 break;
9121
9122 case FC_PKT_TIMEOUT:
9123 pkt->pkt_reason = CMD_TIMEOUT;
9124 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9125 pkt->pkt_statistics |= STAT_TIMEOUT;
9126 } else {
9127 pkt->pkt_statistics |= STAT_ABORTED;
9128 }
9129 break;
9130
9131 case FC_PKT_LOCAL_RJT:
9132 switch (fpkt->pkt_reason) {
9133 case FC_REASON_OFFLINE: {
9134 dev_info_t *cdip = NULL;
9135
9136 mutex_enter(&plun->lun_mutex);
9137 if (plun->lun_mpxio == 0) {
9138 cdip = DIP(plun->lun_cip);
9139 } else if (plun->lun_cip) {
9140 cdip = mdi_pi_get_client(
9141 PIP(plun->lun_cip));
9142 }
9143 mutex_exit(&plun->lun_mutex);
9144
9145 if (cdip) {
9146 (void) ndi_event_retrieve_cookie(
9147 pptr->port_ndi_event_hdl, cdip,
9148 FCAL_REMOVE_EVENT,
9149 &fcp_remove_eid,
9150 NDI_EVENT_NOPASS);
9151 (void) ndi_event_run_callbacks(
9152 pptr->port_ndi_event_hdl,
9153 cdip, fcp_remove_eid, NULL);
9154 }
9155
9156 pkt->pkt_reason = CMD_TRAN_ERR;
9157 pkt->pkt_statistics |= STAT_BUS_RESET;
9158
9159 break;
9160 }
9161
9162 case FC_REASON_NOMEM:
9163 case FC_REASON_QFULL: {
9164 caddr_t ptr;
9165
9166 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9167 ptr = (caddr_t)pkt->pkt_scbp;
9168 if (ptr) {
9169 *ptr = STATUS_BUSY;
9170 }
9171 break;
9172 }
9173
9174 case FC_REASON_DMA_ERROR:
9175 pkt->pkt_reason = CMD_DMA_DERR;
9176 pkt->pkt_statistics |= STAT_ABORTED;
9177 break;
9178
9179 case FC_REASON_CRC_ERROR:
9180 case FC_REASON_UNDERRUN: {
9181 uchar_t status;
9182 /*
9183 * Work around for Bugid: 4240945.
9184 * IB on A5k doesn't set the Underrun bit
9185 * in the fcp status, when it is transferring
9186 * less than requested amount of data. Work
9187 * around the ses problem to keep luxadm
9188 * happy till ibfirmware is fixed.
9189 */
9190 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9191 FCP_CP_IN(fpkt->pkt_resp, rsp,
9192 fpkt->pkt_resp_acc,
9193 sizeof (struct fcp_rsp));
9194 }
9195 status = rsp->fcp_u.fcp_status.scsi_status;
9196 if (((plun->lun_type & DTYPE_MASK) ==
9197 DTYPE_ESI) && (status == STATUS_GOOD)) {
9198 pkt->pkt_reason = CMD_CMPLT;
9199 *pkt->pkt_scbp = status;
9200 pkt->pkt_resid = 0;
9201 } else {
9202 pkt->pkt_reason = CMD_TRAN_ERR;
9203 pkt->pkt_statistics |= STAT_ABORTED;
9204 }
9205 break;
9206 }
9207
9208 case FC_REASON_NO_CONNECTION:
9209 case FC_REASON_UNSUPPORTED:
9210 case FC_REASON_ILLEGAL_REQ:
9211 case FC_REASON_BAD_SID:
9212 case FC_REASON_DIAG_BUSY:
9213 case FC_REASON_FCAL_OPN_FAIL:
9214 case FC_REASON_BAD_XID:
9215 default:
9216 pkt->pkt_reason = CMD_TRAN_ERR;
9217 pkt->pkt_statistics |= STAT_ABORTED;
9218 break;
9219
9220 }
9221 break;
9222
9223 case FC_PKT_NPORT_RJT:
9224 case FC_PKT_FABRIC_RJT:
9225 case FC_PKT_NPORT_BSY:
9226 case FC_PKT_FABRIC_BSY:
9227 default:
9228 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9229 fcp_trace, FCP_BUF_LEVEL_8, 0,
9230 "FC Status 0x%x, reason 0x%x",
9231 fpkt->pkt_state, fpkt->pkt_reason);
9232 pkt->pkt_reason = CMD_TRAN_ERR;
9233 pkt->pkt_statistics |= STAT_ABORTED;
9234 break;
9235 }
9236
9237 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9238 fcp_trace, FCP_BUF_LEVEL_9, 0,
9239 "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9240 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9241 fpkt->pkt_reason);
9242 }
9243
9244 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9245 }
9246
9247
9248 static int
fcp_validate_fcp_response(struct fcp_rsp * rsp,struct fcp_port * pptr)9249 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9250 {
9251 if (rsp->reserved_0 || rsp->reserved_1 ||
9252 rsp->fcp_u.fcp_status.reserved_0 ||
9253 rsp->fcp_u.fcp_status.reserved_1) {
9254 /*
9255 * These reserved fields should ideally be zero. FCP-2 does say
9256 * that the recipient need not check for reserved fields to be
9257 * zero. If they are not zero, we will not make a fuss about it
9258 * - just log it (in debug to both trace buffer and messages
9259 * file and to trace buffer only in non-debug) and move on.
9260 *
9261 * Non-zero reserved fields were seen with minnows.
9262 *
9263 * qlc takes care of some of this but we cannot assume that all
9264 * FCAs will do so.
9265 */
9266 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9267 FCP_BUF_LEVEL_5, 0,
9268 "Got fcp response packet with non-zero reserved fields "
9269 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9270 "status.reserved_0:0x%x, status.reserved_1:0x%x",
9271 rsp->reserved_0, rsp->reserved_1,
9272 rsp->fcp_u.fcp_status.reserved_0,
9273 rsp->fcp_u.fcp_status.reserved_1);
9274 }
9275
9276 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9277 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9278 return (FC_FAILURE);
9279 }
9280
9281 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9282 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9283 sizeof (struct fcp_rsp))) {
9284 return (FC_FAILURE);
9285 }
9286
9287 return (FC_SUCCESS);
9288 }
9289
9290
9291 /*
9292 * This is called when there is a change the in device state. The case we're
9293 * handling here is, if the d_id s does not match, offline this tgt and online
9294 * a new tgt with the new d_id. called from fcp_handle_devices with
9295 * port_mutex held.
9296 */
9297 static int
fcp_device_changed(struct fcp_port * pptr,struct fcp_tgt * ptgt,fc_portmap_t * map_entry,int link_cnt,int tgt_cnt,int cause)9298 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9299 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9300 {
9301 ASSERT(mutex_owned(&pptr->port_mutex));
9302
9303 FCP_TRACE(fcp_logq, pptr->port_instbuf,
9304 fcp_trace, FCP_BUF_LEVEL_3, 0,
9305 "Starting fcp_device_changed...");
9306
9307 /*
9308 * The two cases where the port_device_changed is called is
9309 * either it changes it's d_id or it's hard address.
9310 */
9311 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9312 (FC_TOP_EXTERNAL(pptr->port_topology) &&
9313 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9314
9315 /* offline this target */
9316 mutex_enter(&ptgt->tgt_mutex);
9317 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9318 (void) fcp_offline_target(pptr, ptgt, link_cnt,
9319 0, 1, NDI_DEVI_REMOVE);
9320 }
9321 mutex_exit(&ptgt->tgt_mutex);
9322
9323 fcp_log(CE_NOTE, pptr->port_dip,
9324 "Change in target properties: Old D_ID=%x New D_ID=%x"
9325 " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9326 map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9327 map_entry->map_hard_addr.hard_addr);
9328 }
9329
9330 return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9331 link_cnt, tgt_cnt, cause));
9332 }
9333
9334 /*
9335 * Function: fcp_alloc_lun
9336 *
9337 * Description: Creates a new lun structure and adds it to the list
9338 * of luns of the target.
9339 *
9340 * Argument: ptgt Target the lun will belong to.
9341 *
9342 * Return Value: NULL Failed
9343 * Not NULL Succeeded
9344 *
9345 * Context: Kernel context
9346 */
9347 static struct fcp_lun *
fcp_alloc_lun(struct fcp_tgt * ptgt)9348 fcp_alloc_lun(struct fcp_tgt *ptgt)
9349 {
9350 struct fcp_lun *plun;
9351
9352 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9353 if (plun != NULL) {
9354 /*
9355 * Initialize the mutex before putting in the target list
9356 * especially before releasing the target mutex.
9357 */
9358 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9359 plun->lun_tgt = ptgt;
9360
9361 mutex_enter(&ptgt->tgt_mutex);
9362 plun->lun_next = ptgt->tgt_lun;
9363 ptgt->tgt_lun = plun;
9364 plun->lun_old_guid = NULL;
9365 plun->lun_old_guid_size = 0;
9366 mutex_exit(&ptgt->tgt_mutex);
9367 }
9368
9369 return (plun);
9370 }
9371
9372 /*
9373 * Function: fcp_dealloc_lun
9374 *
9375 * Description: Frees the LUN structure passed by the caller.
9376 *
9377 * Argument: plun LUN structure to free.
9378 *
9379 * Return Value: None
9380 *
9381 * Context: Kernel context.
9382 */
9383 static void
fcp_dealloc_lun(struct fcp_lun * plun)9384 fcp_dealloc_lun(struct fcp_lun *plun)
9385 {
9386 mutex_enter(&plun->lun_mutex);
9387 if (plun->lun_cip) {
9388 fcp_remove_child(plun);
9389 }
9390 mutex_exit(&plun->lun_mutex);
9391
9392 mutex_destroy(&plun->lun_mutex);
9393 if (plun->lun_guid) {
9394 kmem_free(plun->lun_guid, plun->lun_guid_size);
9395 }
9396 if (plun->lun_old_guid) {
9397 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9398 }
9399 kmem_free(plun, sizeof (*plun));
9400 }
9401
9402 /*
9403 * Function: fcp_alloc_tgt
9404 *
9405 * Description: Creates a new target structure and adds it to the port
9406 * hash list.
9407 *
9408 * Argument: pptr fcp port structure
9409 * *map_entry entry describing the target to create
9410 * link_cnt Link state change counter
9411 *
9412 * Return Value: NULL Failed
9413 * Not NULL Succeeded
9414 *
9415 * Context: Kernel context.
9416 */
9417 static struct fcp_tgt *
fcp_alloc_tgt(struct fcp_port * pptr,fc_portmap_t * map_entry,int link_cnt)9418 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9419 {
9420 int hash;
9421 uchar_t *wwn;
9422 struct fcp_tgt *ptgt;
9423
9424 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9425 if (ptgt != NULL) {
9426 mutex_enter(&pptr->port_mutex);
9427 if (link_cnt != pptr->port_link_cnt) {
9428 /*
9429 * oh oh -- another link reset
9430 * in progress -- give up
9431 */
9432 mutex_exit(&pptr->port_mutex);
9433 kmem_free(ptgt, sizeof (*ptgt));
9434 ptgt = NULL;
9435 } else {
9436 /*
9437 * initialize the mutex before putting in the port
9438 * wwn list, especially before releasing the port
9439 * mutex.
9440 */
9441 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9442
9443 /* add new target entry to the port's hash list */
9444 wwn = (uchar_t *)&map_entry->map_pwwn;
9445 hash = FCP_HASH(wwn);
9446
9447 ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9448 pptr->port_tgt_hash_table[hash] = ptgt;
9449
9450 /* save cross-ptr */
9451 ptgt->tgt_port = pptr;
9452
9453 ptgt->tgt_change_cnt = 1;
9454
9455 /* initialize the target manual_config_only flag */
9456 if (fcp_enable_auto_configuration) {
9457 ptgt->tgt_manual_config_only = 0;
9458 } else {
9459 ptgt->tgt_manual_config_only = 1;
9460 }
9461
9462 mutex_exit(&pptr->port_mutex);
9463 }
9464 }
9465
9466 return (ptgt);
9467 }
9468
9469 /*
9470 * Function: fcp_dealloc_tgt
9471 *
9472 * Description: Frees the target structure passed by the caller.
9473 *
9474 * Argument: ptgt Target structure to free.
9475 *
9476 * Return Value: None
9477 *
9478 * Context: Kernel context.
9479 */
9480 static void
fcp_dealloc_tgt(struct fcp_tgt * ptgt)9481 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9482 {
9483 mutex_destroy(&ptgt->tgt_mutex);
9484 kmem_free(ptgt, sizeof (*ptgt));
9485 }
9486
9487
9488 /*
9489 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9490 *
9491 * Device discovery commands will not be retried for-ever as
9492 * this will have repercussions on other devices that need to
9493 * be submitted to the hotplug thread. After a quick glance
9494 * at the SCSI-3 spec, it was found that the spec doesn't
9495 * mandate a forever retry, rather recommends a delayed retry.
9496 *
9497 * Since Photon IB is single threaded, STATUS_BUSY is common
9498 * in a 4+initiator environment. Make sure the total time
9499 * spent on retries (including command timeout) does not
9500 * 60 seconds
9501 */
9502 static void
fcp_queue_ipkt(struct fcp_port * pptr,fc_packet_t * fpkt)9503 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9504 {
9505 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9506 struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9507
9508 mutex_enter(&pptr->port_mutex);
9509 mutex_enter(&ptgt->tgt_mutex);
9510 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9511 FCP_TRACE(fcp_logq, pptr->port_instbuf,
9512 fcp_trace, FCP_BUF_LEVEL_2, 0,
9513 "fcp_queue_ipkt,1:state change occured"
9514 " for D_ID=0x%x", ptgt->tgt_d_id);
9515 mutex_exit(&ptgt->tgt_mutex);
9516 mutex_exit(&pptr->port_mutex);
9517 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9518 icmd->ipkt_change_cnt, icmd->ipkt_cause);
9519 fcp_icmd_free(pptr, icmd);
9520 return;
9521 }
9522 mutex_exit(&ptgt->tgt_mutex);
9523
9524 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9525
9526 if (pptr->port_ipkt_list != NULL) {
9527 /* add pkt to front of doubly-linked list */
9528 pptr->port_ipkt_list->ipkt_prev = icmd;
9529 icmd->ipkt_next = pptr->port_ipkt_list;
9530 pptr->port_ipkt_list = icmd;
9531 icmd->ipkt_prev = NULL;
9532 } else {
9533 /* this is the first/only pkt on the list */
9534 pptr->port_ipkt_list = icmd;
9535 icmd->ipkt_next = NULL;
9536 icmd->ipkt_prev = NULL;
9537 }
9538 mutex_exit(&pptr->port_mutex);
9539 }
9540
9541 /*
9542 * Function: fcp_transport
9543 *
9544 * Description: This function submits the Fibre Channel packet to the transort
9545 * layer by calling fc_ulp_transport(). If fc_ulp_transport()
9546 * fails the submission, the treatment depends on the value of
9547 * the variable internal.
9548 *
9549 * Argument: port_handle fp/fctl port handle.
9550 * *fpkt Packet to submit to the transport layer.
9551 * internal Not zero when it's an internal packet.
9552 *
9553 * Return Value: FC_TRAN_BUSY
9554 * FC_STATEC_BUSY
9555 * FC_OFFLINE
9556 * FC_LOGINREQ
9557 * FC_DEVICE_BUSY
9558 * FC_SUCCESS
9559 */
9560 static int
fcp_transport(opaque_t port_handle,fc_packet_t * fpkt,int internal)9561 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9562 {
9563 int rval;
9564
9565 rval = fc_ulp_transport(port_handle, fpkt);
9566 if (rval == FC_SUCCESS) {
9567 return (rval);
9568 }
9569
9570 /*
9571 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9572 * a command, if the underlying modules see that there is a state
9573 * change, or if a port is OFFLINE, that means, that state change
9574 * hasn't reached FCP yet, so re-queue the command for deferred
9575 * submission.
9576 */
9577 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9578 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9579 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9580 /*
9581 * Defer packet re-submission. Life hang is possible on
9582 * internal commands if the port driver sends FC_STATEC_BUSY
9583 * for ever, but that shouldn't happen in a good environment.
9584 * Limiting re-transport for internal commands is probably a
9585 * good idea..
9586 * A race condition can happen when a port sees barrage of
9587 * link transitions offline to online. If the FCTL has
9588 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9589 * internal commands should be queued to do the discovery.
9590 * The race condition is when an online comes and FCP starts
9591 * its internal discovery and the link goes offline. It is
9592 * possible that the statec_callback has not reached FCP
9593 * and FCP is carrying on with its internal discovery.
9594 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9595 * that the link has gone offline. At this point FCP should
9596 * drop all the internal commands and wait for the
9597 * statec_callback. It will be facilitated by incrementing
9598 * port_link_cnt.
9599 *
9600 * For external commands, the (FC)pkt_timeout is decremented
9601 * by the QUEUE Delay added by our driver, Care is taken to
9602 * ensure that it doesn't become zero (zero means no timeout)
9603 * If the time expires right inside driver queue itself,
9604 * the watch thread will return it to the original caller
9605 * indicating that the command has timed-out.
9606 */
9607 if (internal) {
9608 char *op;
9609 struct fcp_ipkt *icmd;
9610
9611 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9612 switch (icmd->ipkt_opcode) {
9613 case SCMD_REPORT_LUN:
9614 op = "REPORT LUN";
9615 break;
9616
9617 case SCMD_INQUIRY:
9618 op = "INQUIRY";
9619 break;
9620
9621 case SCMD_INQUIRY_PAGE83:
9622 op = "INQUIRY-83";
9623 break;
9624
9625 default:
9626 op = "Internal SCSI COMMAND";
9627 break;
9628 }
9629
9630 if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9631 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9632 rval = FC_SUCCESS;
9633 }
9634 } else {
9635 struct fcp_pkt *cmd;
9636 struct fcp_port *pptr;
9637
9638 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9639 cmd->cmd_state = FCP_PKT_IDLE;
9640 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9641
9642 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9643 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9644 fcp_trace, FCP_BUF_LEVEL_9, 0,
9645 "fcp_transport: xport busy for pkt %p",
9646 cmd->cmd_pkt);
9647 rval = FC_TRAN_BUSY;
9648 } else {
9649 fcp_queue_pkt(pptr, cmd);
9650 rval = FC_SUCCESS;
9651 }
9652 }
9653 }
9654
9655 return (rval);
9656 }
9657
9658 /*VARARGS3*/
9659 static void
fcp_log(int level,dev_info_t * dip,const char * fmt,...)9660 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9661 {
9662 char buf[256];
9663 va_list ap;
9664
9665 if (dip == NULL) {
9666 dip = fcp_global_dip;
9667 }
9668
9669 va_start(ap, fmt);
9670 (void) vsprintf(buf, fmt, ap);
9671 va_end(ap);
9672
9673 scsi_log(dip, "fcp", level, buf);
9674 }
9675
9676 /*
9677 * This function retries NS registry of FC4 type.
9678 * It assumes that fcp_mutex is held.
9679 * The function does nothing if topology is not fabric
9680 * So, the topology has to be set before this function can be called
9681 */
9682 static void
fcp_retry_ns_registry(struct fcp_port * pptr,uint32_t s_id)9683 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9684 {
9685 int rval;
9686
9687 ASSERT(MUTEX_HELD(&pptr->port_mutex));
9688
9689 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9690 ((pptr->port_topology != FC_TOP_FABRIC) &&
9691 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9692 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9693 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9694 }
9695 return;
9696 }
9697 mutex_exit(&pptr->port_mutex);
9698 rval = fcp_do_ns_registry(pptr, s_id);
9699 mutex_enter(&pptr->port_mutex);
9700
9701 if (rval == 0) {
9702 /* Registry successful. Reset flag */
9703 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9704 }
9705 }
9706
9707 /*
9708 * This function registers the ULP with the switch by calling transport i/f
9709 */
9710 static int
fcp_do_ns_registry(struct fcp_port * pptr,uint32_t s_id)9711 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9712 {
9713 fc_ns_cmd_t ns_cmd;
9714 ns_rfc_type_t rfc;
9715 uint32_t types[8];
9716
9717 /*
9718 * Prepare the Name server structure to
9719 * register with the transport in case of
9720 * Fabric configuration.
9721 */
9722 bzero(&rfc, sizeof (rfc));
9723 bzero(types, sizeof (types));
9724
9725 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9726 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9727
9728 rfc.rfc_port_id.port_id = s_id;
9729 bcopy(types, rfc.rfc_types, sizeof (types));
9730
9731 ns_cmd.ns_flags = 0;
9732 ns_cmd.ns_cmd = NS_RFT_ID;
9733 ns_cmd.ns_req_len = sizeof (rfc);
9734 ns_cmd.ns_req_payload = (caddr_t)&rfc;
9735 ns_cmd.ns_resp_len = 0;
9736 ns_cmd.ns_resp_payload = NULL;
9737
9738 /*
9739 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9740 */
9741 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9742 fcp_log(CE_WARN, pptr->port_dip,
9743 "!ns_registry: failed name server registration");
9744 return (1);
9745 }
9746
9747 return (0);
9748 }
9749
9750 /*
9751 * Function: fcp_handle_port_attach
9752 *
9753 * Description: This function is called from fcp_port_attach() to attach a
9754 * new port. This routine does the following:
9755 *
9756 * 1) Allocates an fcp_port structure and initializes it.
9757 * 2) Tries to register the new FC-4 (FCP) capablity with the name
9758 * server.
9759 * 3) Kicks off the enumeration of the targets/luns visible
9760 * through this new port. That is done by calling
9761 * fcp_statec_callback() if the port is online.
9762 *
9763 * Argument: ulph fp/fctl port handle.
9764 * *pinfo Port information.
9765 * s_id Port ID.
9766 * instance Device instance number for the local port
9767 * (returned by ddi_get_instance()).
9768 *
9769 * Return Value: DDI_SUCCESS
9770 * DDI_FAILURE
9771 *
9772 * Context: User and Kernel context.
9773 */
9774 /*ARGSUSED*/
9775 int
fcp_handle_port_attach(opaque_t ulph,fc_ulp_port_info_t * pinfo,uint32_t s_id,int instance)9776 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9777 uint32_t s_id, int instance)
9778 {
9779 int res = DDI_FAILURE;
9780 scsi_hba_tran_t *tran;
9781 int mutex_initted = FALSE;
9782 int hba_attached = FALSE;
9783 int soft_state_linked = FALSE;
9784 int event_bind = FALSE;
9785 struct fcp_port *pptr;
9786 fc_portmap_t *tmp_list = NULL;
9787 uint32_t max_cnt, alloc_cnt;
9788 uchar_t *boot_wwn = NULL;
9789 uint_t nbytes;
9790 int manual_cfg;
9791
9792 /*
9793 * this port instance attaching for the first time (or after
9794 * being detached before)
9795 */
9796 FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9797 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9798
9799 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9800 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9801 "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9802 instance);
9803 return (res);
9804 }
9805
9806 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9807 /* this shouldn't happen */
9808 ddi_soft_state_free(fcp_softstate, instance);
9809 cmn_err(CE_WARN, "fcp: bad soft state");
9810 return (res);
9811 }
9812
9813 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9814
9815 /*
9816 * Make a copy of ulp_port_info as fctl allocates
9817 * a temp struct.
9818 */
9819 (void) fcp_cp_pinfo(pptr, pinfo);
9820
9821 /*
9822 * Check for manual_configuration_only property.
9823 * Enable manual configurtion if the property is
9824 * set to 1, otherwise disable manual configuration.
9825 */
9826 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9827 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9828 MANUAL_CFG_ONLY,
9829 -1)) != -1) {
9830 if (manual_cfg == 1) {
9831 char *pathname;
9832 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9833 (void) ddi_pathname(pptr->port_dip, pathname);
9834 cmn_err(CE_NOTE,
9835 "%s (%s%d) %s is enabled via %s.conf.",
9836 pathname,
9837 ddi_driver_name(pptr->port_dip),
9838 ddi_get_instance(pptr->port_dip),
9839 MANUAL_CFG_ONLY,
9840 ddi_driver_name(pptr->port_dip));
9841 fcp_enable_auto_configuration = 0;
9842 kmem_free(pathname, MAXPATHLEN);
9843 }
9844 }
9845 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9846 pptr->port_link_cnt = 1;
9847 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9848 pptr->port_id = s_id;
9849 pptr->port_instance = instance;
9850 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9851 pptr->port_state = FCP_STATE_INIT;
9852 if (pinfo->port_acc_attr == NULL) {
9853 /*
9854 * The corresponding FCA doesn't support DMA at all
9855 */
9856 pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9857 }
9858
9859 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9860
9861 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9862 /*
9863 * If FCA supports DMA in SCSI data phase, we need preallocate
9864 * dma cookie, so stash the cookie size
9865 */
9866 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9867 pptr->port_data_dma_attr.dma_attr_sgllen;
9868 }
9869
9870 /*
9871 * The two mutexes of fcp_port are initialized. The variable
9872 * mutex_initted is incremented to remember that fact. That variable
9873 * is checked when the routine fails and the mutexes have to be
9874 * destroyed.
9875 */
9876 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9877 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9878 mutex_initted++;
9879
9880 /*
9881 * The SCSI tran structure is allocate and initialized now.
9882 */
9883 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9884 fcp_log(CE_WARN, pptr->port_dip,
9885 "!fcp%d: scsi_hba_tran_alloc failed", instance);
9886 goto fail;
9887 }
9888
9889 /* link in the transport structure then fill it in */
9890 pptr->port_tran = tran;
9891 tran->tran_hba_private = pptr;
9892 tran->tran_tgt_init = fcp_scsi_tgt_init;
9893 tran->tran_tgt_probe = NULL;
9894 tran->tran_tgt_free = fcp_scsi_tgt_free;
9895 tran->tran_start = fcp_scsi_start;
9896 tran->tran_reset = fcp_scsi_reset;
9897 tran->tran_abort = fcp_scsi_abort;
9898 tran->tran_getcap = fcp_scsi_getcap;
9899 tran->tran_setcap = fcp_scsi_setcap;
9900 tran->tran_init_pkt = NULL;
9901 tran->tran_destroy_pkt = NULL;
9902 tran->tran_dmafree = NULL;
9903 tran->tran_sync_pkt = NULL;
9904 tran->tran_reset_notify = fcp_scsi_reset_notify;
9905 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr;
9906 tran->tran_get_name = fcp_scsi_get_name;
9907 tran->tran_clear_aca = NULL;
9908 tran->tran_clear_task_set = NULL;
9909 tran->tran_terminate_task = NULL;
9910 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie;
9911 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall;
9912 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall;
9913 tran->tran_post_event = fcp_scsi_bus_post_event;
9914 tran->tran_quiesce = NULL;
9915 tran->tran_unquiesce = NULL;
9916 tran->tran_bus_reset = NULL;
9917 tran->tran_bus_config = fcp_scsi_bus_config;
9918 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig;
9919 tran->tran_bus_power = NULL;
9920 tran->tran_interconnect_type = INTERCONNECT_FABRIC;
9921
9922 tran->tran_pkt_constructor = fcp_kmem_cache_constructor;
9923 tran->tran_pkt_destructor = fcp_kmem_cache_destructor;
9924 tran->tran_setup_pkt = fcp_pkt_setup;
9925 tran->tran_teardown_pkt = fcp_pkt_teardown;
9926 tran->tran_hba_len = pptr->port_priv_pkt_len +
9927 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9928 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9929 /*
9930 * If FCA don't support DMA, then we use different vectors to
9931 * minimize the effects on DMA code flow path
9932 */
9933 tran->tran_start = fcp_pseudo_start;
9934 tran->tran_init_pkt = fcp_pseudo_init_pkt;
9935 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt;
9936 tran->tran_sync_pkt = fcp_pseudo_sync_pkt;
9937 tran->tran_dmafree = fcp_pseudo_dmafree;
9938 tran->tran_setup_pkt = NULL;
9939 tran->tran_teardown_pkt = NULL;
9940 tran->tran_pkt_constructor = NULL;
9941 tran->tran_pkt_destructor = NULL;
9942 pptr->port_data_dma_attr = pseudo_fca_dma_attr;
9943 }
9944
9945 /*
9946 * Allocate an ndi event handle
9947 */
9948 pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9949 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9950
9951 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9952 sizeof (fcp_ndi_event_defs));
9953
9954 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9955 &pptr->port_ndi_event_hdl, NDI_SLEEP);
9956
9957 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9958 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9959 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9960
9961 if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9962 (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9963 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9964 goto fail;
9965 }
9966 event_bind++; /* Checked in fail case */
9967
9968 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9969 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9970 != DDI_SUCCESS) {
9971 fcp_log(CE_WARN, pptr->port_dip,
9972 "!fcp%d: scsi_hba_attach_setup failed", instance);
9973 goto fail;
9974 }
9975 hba_attached++; /* Checked in fail case */
9976
9977 pptr->port_mpxio = 0;
9978 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9979 MDI_SUCCESS) {
9980 pptr->port_mpxio++;
9981 }
9982
9983 /*
9984 * The following code is putting the new port structure in the global
9985 * list of ports and, if it is the first port to attach, it start the
9986 * fcp_watchdog_tick.
9987 *
9988 * Why put this new port in the global before we are done attaching it?
9989 * We are actually making the structure globally known before we are
9990 * done attaching it. The reason for that is: because of the code that
9991 * follows. At this point the resources to handle the port are
9992 * allocated. This function is now going to do the following:
9993 *
9994 * 1) It is going to try to register with the name server advertizing
9995 * the new FCP capability of the port.
9996 * 2) It is going to play the role of the fp/fctl layer by building
9997 * a list of worlwide names reachable through this port and call
9998 * itself on fcp_statec_callback(). That requires the port to
9999 * be part of the global list.
10000 */
10001 mutex_enter(&fcp_global_mutex);
10002 if (fcp_port_head == NULL) {
10003 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
10004 }
10005 pptr->port_next = fcp_port_head;
10006 fcp_port_head = pptr;
10007 soft_state_linked++;
10008
10009 if (fcp_watchdog_init++ == 0) {
10010 fcp_watchdog_tick = fcp_watchdog_timeout *
10011 drv_usectohz(1000000);
10012 fcp_watchdog_id = timeout(fcp_watch, NULL,
10013 fcp_watchdog_tick);
10014 }
10015 mutex_exit(&fcp_global_mutex);
10016
10017 /*
10018 * Here an attempt is made to register with the name server, the new
10019 * FCP capability. That is done using an RTF_ID to the name server.
10020 * It is done synchronously. The function fcp_do_ns_registry()
10021 * doesn't return till the name server responded.
10022 * On failures, just ignore it for now and it will get retried during
10023 * state change callbacks. We'll set a flag to show this failure
10024 */
10025 if (fcp_do_ns_registry(pptr, s_id)) {
10026 mutex_enter(&pptr->port_mutex);
10027 pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10028 mutex_exit(&pptr->port_mutex);
10029 } else {
10030 mutex_enter(&pptr->port_mutex);
10031 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10032 mutex_exit(&pptr->port_mutex);
10033 }
10034
10035 /*
10036 * Lookup for boot WWN property
10037 */
10038 if (modrootloaded != 1) {
10039 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10040 ddi_get_parent(pinfo->port_dip),
10041 DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10042 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10043 (nbytes == FC_WWN_SIZE)) {
10044 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10045 }
10046 if (boot_wwn) {
10047 ddi_prop_free(boot_wwn);
10048 }
10049 }
10050
10051 /*
10052 * Handle various topologies and link states.
10053 */
10054 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10055 case FC_STATE_OFFLINE:
10056
10057 /*
10058 * we're attaching a port where the link is offline
10059 *
10060 * Wait for ONLINE, at which time a state
10061 * change will cause a statec_callback
10062 *
10063 * in the mean time, do not do anything
10064 */
10065 res = DDI_SUCCESS;
10066 pptr->port_state |= FCP_STATE_OFFLINE;
10067 break;
10068
10069 case FC_STATE_ONLINE: {
10070 if (pptr->port_topology == FC_TOP_UNKNOWN) {
10071 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10072 res = DDI_SUCCESS;
10073 break;
10074 }
10075 /*
10076 * discover devices and create nodes (a private
10077 * loop or point-to-point)
10078 */
10079 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10080
10081 /*
10082 * At this point we are going to build a list of all the ports
10083 * that can be reached through this local port. It looks like
10084 * we cannot handle more than FCP_MAX_DEVICES per local port
10085 * (128).
10086 */
10087 if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10088 sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10089 KM_NOSLEEP)) == NULL) {
10090 fcp_log(CE_WARN, pptr->port_dip,
10091 "!fcp%d: failed to allocate portmap",
10092 instance);
10093 goto fail;
10094 }
10095
10096 /*
10097 * fc_ulp_getportmap() is going to provide us with the list of
10098 * remote ports in the buffer we just allocated. The way the
10099 * list is going to be retrieved depends on the topology.
10100 * However, if we are connected to a Fabric, a name server
10101 * request may be sent to get the list of FCP capable ports.
10102 * It should be noted that is the case the request is
10103 * synchronous. This means we are stuck here till the name
10104 * server replies. A lot of things can change during that time
10105 * and including, may be, being called on
10106 * fcp_statec_callback() for different reasons. I'm not sure
10107 * the code can handle that.
10108 */
10109 max_cnt = FCP_MAX_DEVICES;
10110 alloc_cnt = FCP_MAX_DEVICES;
10111 if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10112 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10113 FC_SUCCESS) {
10114 caddr_t msg;
10115
10116 (void) fc_ulp_error(res, &msg);
10117
10118 /*
10119 * this just means the transport is
10120 * busy perhaps building a portmap so,
10121 * for now, succeed this port attach
10122 * when the transport has a new map,
10123 * it'll send us a state change then
10124 */
10125 fcp_log(CE_WARN, pptr->port_dip,
10126 "!failed to get port map : %s", msg);
10127
10128 res = DDI_SUCCESS;
10129 break; /* go return result */
10130 }
10131 if (max_cnt > alloc_cnt) {
10132 alloc_cnt = max_cnt;
10133 }
10134
10135 /*
10136 * We are now going to call fcp_statec_callback() ourselves.
10137 * By issuing this call we are trying to kick off the enumera-
10138 * tion process.
10139 */
10140 /*
10141 * let the state change callback do the SCSI device
10142 * discovery and create the devinfos
10143 */
10144 fcp_statec_callback(ulph, pptr->port_fp_handle,
10145 pptr->port_phys_state, pptr->port_topology, tmp_list,
10146 max_cnt, pptr->port_id);
10147
10148 res = DDI_SUCCESS;
10149 break;
10150 }
10151
10152 default:
10153 /* unknown port state */
10154 fcp_log(CE_WARN, pptr->port_dip,
10155 "!fcp%d: invalid port state at attach=0x%x",
10156 instance, pptr->port_phys_state);
10157
10158 mutex_enter(&pptr->port_mutex);
10159 pptr->port_phys_state = FCP_STATE_OFFLINE;
10160 mutex_exit(&pptr->port_mutex);
10161
10162 res = DDI_SUCCESS;
10163 break;
10164 }
10165
10166 /* free temp list if used */
10167 if (tmp_list != NULL) {
10168 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10169 }
10170
10171 /* note the attach time */
10172 pptr->port_attach_time = ddi_get_lbolt64();
10173
10174 /* all done */
10175 return (res);
10176
10177 /* a failure we have to clean up after */
10178 fail:
10179 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10180
10181 if (soft_state_linked) {
10182 /* remove this fcp_port from the linked list */
10183 (void) fcp_soft_state_unlink(pptr);
10184 }
10185
10186 /* unbind and free event set */
10187 if (pptr->port_ndi_event_hdl) {
10188 if (event_bind) {
10189 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10190 &pptr->port_ndi_events, NDI_SLEEP);
10191 }
10192 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10193 }
10194
10195 if (pptr->port_ndi_event_defs) {
10196 (void) kmem_free(pptr->port_ndi_event_defs,
10197 sizeof (fcp_ndi_event_defs));
10198 }
10199
10200 /*
10201 * Clean up mpxio stuff
10202 */
10203 if (pptr->port_mpxio) {
10204 (void) mdi_phci_unregister(pptr->port_dip, 0);
10205 pptr->port_mpxio--;
10206 }
10207
10208 /* undo SCSI HBA setup */
10209 if (hba_attached) {
10210 (void) scsi_hba_detach(pptr->port_dip);
10211 }
10212 if (pptr->port_tran != NULL) {
10213 scsi_hba_tran_free(pptr->port_tran);
10214 }
10215
10216 mutex_enter(&fcp_global_mutex);
10217
10218 /*
10219 * We check soft_state_linked, because it is incremented right before
10220 * we call increment fcp_watchdog_init. Therefore, we know if
10221 * soft_state_linked is still FALSE, we do not want to decrement
10222 * fcp_watchdog_init or possibly call untimeout.
10223 */
10224
10225 if (soft_state_linked) {
10226 if (--fcp_watchdog_init == 0) {
10227 timeout_id_t tid = fcp_watchdog_id;
10228
10229 mutex_exit(&fcp_global_mutex);
10230 (void) untimeout(tid);
10231 } else {
10232 mutex_exit(&fcp_global_mutex);
10233 }
10234 } else {
10235 mutex_exit(&fcp_global_mutex);
10236 }
10237
10238 if (mutex_initted) {
10239 mutex_destroy(&pptr->port_mutex);
10240 mutex_destroy(&pptr->port_pkt_mutex);
10241 }
10242
10243 if (tmp_list != NULL) {
10244 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10245 }
10246
10247 /* this makes pptr invalid */
10248 ddi_soft_state_free(fcp_softstate, instance);
10249
10250 return (DDI_FAILURE);
10251 }
10252
10253
10254 static int
fcp_handle_port_detach(struct fcp_port * pptr,int flag,int instance)10255 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10256 {
10257 int count = 0;
10258
10259 mutex_enter(&pptr->port_mutex);
10260
10261 /*
10262 * if the port is powered down or suspended, nothing else
10263 * to do; just return.
10264 */
10265 if (flag != FCP_STATE_DETACHING) {
10266 if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10267 FCP_STATE_SUSPENDED)) {
10268 pptr->port_state |= flag;
10269 mutex_exit(&pptr->port_mutex);
10270 return (FC_SUCCESS);
10271 }
10272 }
10273
10274 if (pptr->port_state & FCP_STATE_IN_MDI) {
10275 mutex_exit(&pptr->port_mutex);
10276 return (FC_FAILURE);
10277 }
10278
10279 FCP_TRACE(fcp_logq, pptr->port_instbuf,
10280 fcp_trace, FCP_BUF_LEVEL_2, 0,
10281 "fcp_handle_port_detach: port is detaching");
10282
10283 pptr->port_state |= flag;
10284
10285 /*
10286 * Wait for any ongoing reconfig/ipkt to complete, that
10287 * ensures the freeing to targets/luns is safe.
10288 * No more ref to this port should happen from statec/ioctl
10289 * after that as it was removed from the global port list.
10290 */
10291 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10292 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10293 /*
10294 * Let's give sufficient time for reconfig/ipkt
10295 * to complete.
10296 */
10297 if (count++ >= FCP_ICMD_DEADLINE) {
10298 break;
10299 }
10300 mutex_exit(&pptr->port_mutex);
10301 delay(drv_usectohz(1000000));
10302 mutex_enter(&pptr->port_mutex);
10303 }
10304
10305 /*
10306 * if the driver is still busy then fail to
10307 * suspend/power down.
10308 */
10309 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10310 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10311 pptr->port_state &= ~flag;
10312 mutex_exit(&pptr->port_mutex);
10313 return (FC_FAILURE);
10314 }
10315
10316 if (flag == FCP_STATE_DETACHING) {
10317 pptr = fcp_soft_state_unlink(pptr);
10318 ASSERT(pptr != NULL);
10319 }
10320
10321 pptr->port_link_cnt++;
10322 pptr->port_state |= FCP_STATE_OFFLINE;
10323 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10324
10325 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10326 FCP_CAUSE_LINK_DOWN);
10327 mutex_exit(&pptr->port_mutex);
10328
10329 /* kill watch dog timer if we're the last */
10330 mutex_enter(&fcp_global_mutex);
10331 if (--fcp_watchdog_init == 0) {
10332 timeout_id_t tid = fcp_watchdog_id;
10333 mutex_exit(&fcp_global_mutex);
10334 (void) untimeout(tid);
10335 } else {
10336 mutex_exit(&fcp_global_mutex);
10337 }
10338
10339 /* clean up the port structures */
10340 if (flag == FCP_STATE_DETACHING) {
10341 fcp_cleanup_port(pptr, instance);
10342 }
10343
10344 return (FC_SUCCESS);
10345 }
10346
10347
10348 static void
fcp_cleanup_port(struct fcp_port * pptr,int instance)10349 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10350 {
10351 ASSERT(pptr != NULL);
10352
10353 /* unbind and free event set */
10354 if (pptr->port_ndi_event_hdl) {
10355 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10356 &pptr->port_ndi_events, NDI_SLEEP);
10357 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10358 }
10359
10360 if (pptr->port_ndi_event_defs) {
10361 (void) kmem_free(pptr->port_ndi_event_defs,
10362 sizeof (fcp_ndi_event_defs));
10363 }
10364
10365 /* free the lun/target structures and devinfos */
10366 fcp_free_targets(pptr);
10367
10368 /*
10369 * Clean up mpxio stuff
10370 */
10371 if (pptr->port_mpxio) {
10372 (void) mdi_phci_unregister(pptr->port_dip, 0);
10373 pptr->port_mpxio--;
10374 }
10375
10376 /* clean up SCSA stuff */
10377 (void) scsi_hba_detach(pptr->port_dip);
10378 if (pptr->port_tran != NULL) {
10379 scsi_hba_tran_free(pptr->port_tran);
10380 }
10381
10382 #ifdef KSTATS_CODE
10383 /* clean up kstats */
10384 if (pptr->fcp_ksp != NULL) {
10385 kstat_delete(pptr->fcp_ksp);
10386 }
10387 #endif
10388
10389 /* clean up soft state mutexes/condition variables */
10390 mutex_destroy(&pptr->port_mutex);
10391 mutex_destroy(&pptr->port_pkt_mutex);
10392
10393 /* all done with soft state */
10394 ddi_soft_state_free(fcp_softstate, instance);
10395 }
10396
10397 /*
10398 * Function: fcp_kmem_cache_constructor
10399 *
10400 * Description: This function allocates and initializes the resources required
10401 * to build a scsi_pkt structure the target driver. The result
10402 * of the allocation and initialization will be cached in the
10403 * memory cache. As DMA resources may be allocated here, that
10404 * means DMA resources will be tied up in the cache manager.
10405 * This is a tradeoff that has been made for performance reasons.
10406 *
10407 * Argument: *buf Memory to preinitialize.
10408 * *arg FCP port structure (fcp_port).
10409 * kmflags Value passed to kmem_cache_alloc() and
10410 * propagated to the constructor.
10411 *
10412 * Return Value: 0 Allocation/Initialization was successful.
10413 * -1 Allocation or Initialization failed.
10414 *
10415 *
10416 * If the returned value is 0, the buffer is initialized like this:
10417 *
10418 * +================================+
10419 * +----> | struct scsi_pkt |
10420 * | | |
10421 * | +--- | pkt_ha_private |
10422 * | | | |
10423 * | | +================================+
10424 * | |
10425 * | | +================================+
10426 * | +--> | struct fcp_pkt | <---------+
10427 * | | | |
10428 * +----- | cmd_pkt | |
10429 * | cmd_fp_pkt | ---+ |
10430 * +-------->| cmd_fcp_rsp[] | | |
10431 * | +--->| cmd_fcp_cmd[] | | |
10432 * | | |--------------------------------| | |
10433 * | | | struct fc_packet | <--+ |
10434 * | | | | |
10435 * | | | pkt_ulp_private | ----------+
10436 * | | | pkt_fca_private | -----+
10437 * | | | pkt_data_cookie | ---+ |
10438 * | | | pkt_cmdlen | | |
10439 * | |(a) | pkt_rsplen | | |
10440 * | +----| .......... pkt_cmd ........... | ---|-|---------------+
10441 * | (b) | pkt_cmd_cookie | ---|-|----------+ |
10442 * +---------| .......... pkt_resp .......... | ---|-|------+ | |
10443 * | pkt_resp_cookie | ---|-|--+ | | |
10444 * | pkt_cmd_dma | | | | | | |
10445 * | pkt_cmd_acc | | | | | | |
10446 * +================================+ | | | | | |
10447 * | dma_cookies | <--+ | | | | |
10448 * | | | | | | |
10449 * +================================+ | | | | |
10450 * | fca_private | <----+ | | | |
10451 * | | | | | |
10452 * +================================+ | | | |
10453 * | | | |
10454 * | | | |
10455 * +================================+ (d) | | | |
10456 * | fcp_resp cookies | <-------+ | | |
10457 * | | | | |
10458 * +================================+ | | |
10459 * | | |
10460 * +================================+ (d) | | |
10461 * | fcp_resp | <-----------+ | |
10462 * | (DMA resources associated) | | |
10463 * +================================+ | |
10464 * | |
10465 * | |
10466 * | |
10467 * +================================+ (c) | |
10468 * | fcp_cmd cookies | <---------------+ |
10469 * | | |
10470 * +================================+ |
10471 * |
10472 * +================================+ (c) |
10473 * | fcp_cmd | <--------------------+
10474 * | (DMA resources associated) |
10475 * +================================+
10476 *
10477 * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10478 * (b) Only if DMA is NOT used for the FCP_RESP buffer
10479 * (c) Only if DMA is used for the FCP_CMD buffer.
10480 * (d) Only if DMA is used for the FCP_RESP buffer
10481 */
10482 static int
fcp_kmem_cache_constructor(struct scsi_pkt * pkt,scsi_hba_tran_t * tran,int kmflags)10483 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10484 int kmflags)
10485 {
10486 struct fcp_pkt *cmd;
10487 struct fcp_port *pptr;
10488 fc_packet_t *fpkt;
10489
10490 pptr = (struct fcp_port *)tran->tran_hba_private;
10491 cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10492 bzero(cmd, tran->tran_hba_len);
10493
10494 cmd->cmd_pkt = pkt;
10495 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10496 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10497 cmd->cmd_fp_pkt = fpkt;
10498
10499 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10500 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10501 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10502 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10503
10504 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10505 sizeof (struct fcp_pkt));
10506
10507 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10508 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10509
10510 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10511 /*
10512 * The underlying HBA doesn't want to DMA the fcp_cmd or
10513 * fcp_resp. The transfer of information will be done by
10514 * bcopy.
10515 * The naming of the flags (that is actually a value) is
10516 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10517 * DMA" but instead "NO DMA".
10518 */
10519 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10520 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10521 fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10522 } else {
10523 /*
10524 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10525 * buffer. A buffer is allocated for each one the ddi_dma_*
10526 * interfaces.
10527 */
10528 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10529 return (-1);
10530 }
10531 }
10532
10533 return (0);
10534 }
10535
10536 /*
10537 * Function: fcp_kmem_cache_destructor
10538 *
10539 * Description: Called by the destructor of the cache managed by SCSA.
10540 * All the resources pre-allocated in fcp_pkt_constructor
10541 * and the data also pre-initialized in fcp_pkt_constructor
10542 * are freed and uninitialized here.
10543 *
10544 * Argument: *buf Memory to uninitialize.
10545 * *arg FCP port structure (fcp_port).
10546 *
10547 * Return Value: None
10548 *
10549 * Context: kernel
10550 */
10551 static void
fcp_kmem_cache_destructor(struct scsi_pkt * pkt,scsi_hba_tran_t * tran)10552 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10553 {
10554 struct fcp_pkt *cmd;
10555 struct fcp_port *pptr;
10556
10557 pptr = (struct fcp_port *)(tran->tran_hba_private);
10558 cmd = pkt->pkt_ha_private;
10559
10560 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10561 /*
10562 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10563 * buffer and DMA resources allocated to do so are released.
10564 */
10565 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10566 }
10567 }
10568
10569 /*
10570 * Function: fcp_alloc_cmd_resp
10571 *
10572 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10573 * will be DMAed by the HBA. The buffer is allocated applying
10574 * the DMA requirements for the HBA. The buffers allocated will
10575 * also be bound. DMA resources are allocated in the process.
10576 * They will be released by fcp_free_cmd_resp().
10577 *
10578 * Argument: *pptr FCP port.
10579 * *fpkt fc packet for which the cmd and resp packet should be
10580 * allocated.
10581 * flags Allocation flags.
10582 *
10583 * Return Value: FC_FAILURE
10584 * FC_SUCCESS
10585 *
10586 * Context: User or Kernel context only if flags == KM_SLEEP.
10587 * Interrupt context if the KM_SLEEP is not specified.
10588 */
10589 static int
fcp_alloc_cmd_resp(struct fcp_port * pptr,fc_packet_t * fpkt,int flags)10590 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10591 {
10592 int rval;
10593 int cmd_len;
10594 int resp_len;
10595 ulong_t real_len;
10596 int (*cb) (caddr_t);
10597 ddi_dma_cookie_t pkt_cookie;
10598 ddi_dma_cookie_t *cp;
10599 uint32_t cnt;
10600
10601 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10602
10603 cmd_len = fpkt->pkt_cmdlen;
10604 resp_len = fpkt->pkt_rsplen;
10605
10606 ASSERT(fpkt->pkt_cmd_dma == NULL);
10607
10608 /* Allocation of a DMA handle used in subsequent calls. */
10609 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10610 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10611 return (FC_FAILURE);
10612 }
10613
10614 /* A buffer is allocated that satisfies the DMA requirements. */
10615 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10616 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10617 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10618
10619 if (rval != DDI_SUCCESS) {
10620 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10621 return (FC_FAILURE);
10622 }
10623
10624 if (real_len < cmd_len) {
10625 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10626 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10627 return (FC_FAILURE);
10628 }
10629
10630 /* The buffer allocated is DMA bound. */
10631 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10632 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10633 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10634
10635 if (rval != DDI_DMA_MAPPED) {
10636 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10637 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10638 return (FC_FAILURE);
10639 }
10640
10641 if (fpkt->pkt_cmd_cookie_cnt >
10642 pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10643 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10644 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10645 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10646 return (FC_FAILURE);
10647 }
10648
10649 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10650
10651 /*
10652 * The buffer where the scatter/gather list is going to be built is
10653 * allocated.
10654 */
10655 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10656 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10657 KM_NOSLEEP);
10658
10659 if (cp == NULL) {
10660 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10661 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10662 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10663 return (FC_FAILURE);
10664 }
10665
10666 /*
10667 * The scatter/gather list for the buffer we just allocated is built
10668 * here.
10669 */
10670 *cp = pkt_cookie;
10671 cp++;
10672
10673 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10674 ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10675 &pkt_cookie);
10676 *cp = pkt_cookie;
10677 }
10678
10679 ASSERT(fpkt->pkt_resp_dma == NULL);
10680 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10681 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10682 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10683 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10684 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10685 return (FC_FAILURE);
10686 }
10687
10688 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10689 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10690 (caddr_t *)&fpkt->pkt_resp, &real_len,
10691 &fpkt->pkt_resp_acc);
10692
10693 if (rval != DDI_SUCCESS) {
10694 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10695 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10696 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10697 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10698 kmem_free(fpkt->pkt_cmd_cookie,
10699 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10700 return (FC_FAILURE);
10701 }
10702
10703 if (real_len < resp_len) {
10704 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10705 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10706 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10707 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10708 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10709 kmem_free(fpkt->pkt_cmd_cookie,
10710 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10711 return (FC_FAILURE);
10712 }
10713
10714 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10715 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10716 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10717
10718 if (rval != DDI_DMA_MAPPED) {
10719 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10720 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10721 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10722 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10723 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10724 kmem_free(fpkt->pkt_cmd_cookie,
10725 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10726 return (FC_FAILURE);
10727 }
10728
10729 if (fpkt->pkt_resp_cookie_cnt >
10730 pptr->port_resp_dma_attr.dma_attr_sgllen) {
10731 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10732 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10733 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10734 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10735 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10736 kmem_free(fpkt->pkt_cmd_cookie,
10737 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10738 return (FC_FAILURE);
10739 }
10740
10741 ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10742
10743 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10744 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10745 KM_NOSLEEP);
10746
10747 if (cp == NULL) {
10748 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10749 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10750 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10751 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10752 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10753 kmem_free(fpkt->pkt_cmd_cookie,
10754 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10755 return (FC_FAILURE);
10756 }
10757
10758 *cp = pkt_cookie;
10759 cp++;
10760
10761 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10762 ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10763 &pkt_cookie);
10764 *cp = pkt_cookie;
10765 }
10766
10767 return (FC_SUCCESS);
10768 }
10769
10770 /*
10771 * Function: fcp_free_cmd_resp
10772 *
10773 * Description: This function releases the FCP_CMD and FCP_RESP buffer
10774 * allocated by fcp_alloc_cmd_resp() and all the resources
10775 * associated with them. That includes the DMA resources and the
10776 * buffer allocated for the cookies of each one of them.
10777 *
10778 * Argument: *pptr FCP port context.
10779 * *fpkt fc packet containing the cmd and resp packet
10780 * to be released.
10781 *
10782 * Return Value: None
10783 *
10784 * Context: Interrupt, User and Kernel context.
10785 */
10786 /* ARGSUSED */
10787 static void
fcp_free_cmd_resp(struct fcp_port * pptr,fc_packet_t * fpkt)10788 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10789 {
10790 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10791
10792 if (fpkt->pkt_resp_dma) {
10793 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10794 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10795 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10796 }
10797
10798 if (fpkt->pkt_resp_cookie) {
10799 kmem_free(fpkt->pkt_resp_cookie,
10800 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10801 fpkt->pkt_resp_cookie = NULL;
10802 }
10803
10804 if (fpkt->pkt_cmd_dma) {
10805 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10806 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10807 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10808 }
10809
10810 if (fpkt->pkt_cmd_cookie) {
10811 kmem_free(fpkt->pkt_cmd_cookie,
10812 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10813 fpkt->pkt_cmd_cookie = NULL;
10814 }
10815 }
10816
10817
10818 /*
10819 * called by the transport to do our own target initialization
10820 *
10821 * can acquire and release the global mutex
10822 */
10823 /* ARGSUSED */
10824 static int
fcp_phys_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)10825 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10826 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10827 {
10828 uchar_t *bytes;
10829 uint_t nbytes;
10830 uint16_t lun_num;
10831 struct fcp_tgt *ptgt;
10832 struct fcp_lun *plun;
10833 struct fcp_port *pptr = (struct fcp_port *)
10834 hba_tran->tran_hba_private;
10835
10836 ASSERT(pptr != NULL);
10837
10838 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10839 FCP_BUF_LEVEL_8, 0,
10840 "fcp_phys_tgt_init: called for %s (instance %d)",
10841 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10842
10843 /* get our port WWN property */
10844 bytes = NULL;
10845 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10846 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10847 (nbytes != FC_WWN_SIZE)) {
10848 /* no port WWN property */
10849 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10850 FCP_BUF_LEVEL_8, 0,
10851 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10852 " for %s (instance %d): bytes=%p nbytes=%x",
10853 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10854 nbytes);
10855
10856 if (bytes != NULL) {
10857 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10858 }
10859
10860 return (DDI_NOT_WELL_FORMED);
10861 }
10862 ASSERT(bytes != NULL);
10863
10864 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10865 LUN_PROP, 0xFFFF);
10866 if (lun_num == 0xFFFF) {
10867 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10868 FCP_BUF_LEVEL_8, 0,
10869 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10870 " for %s (instance %d)", ddi_get_name(tgt_dip),
10871 ddi_get_instance(tgt_dip));
10872
10873 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10874 return (DDI_NOT_WELL_FORMED);
10875 }
10876
10877 mutex_enter(&pptr->port_mutex);
10878 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10879 mutex_exit(&pptr->port_mutex);
10880 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10881 FCP_BUF_LEVEL_8, 0,
10882 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10883 " for %s (instance %d)", ddi_get_name(tgt_dip),
10884 ddi_get_instance(tgt_dip));
10885
10886 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10887 return (DDI_FAILURE);
10888 }
10889
10890 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10891 FC_WWN_SIZE) == 0);
10892 ASSERT(plun->lun_num == lun_num);
10893
10894 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10895
10896 ptgt = plun->lun_tgt;
10897
10898 mutex_enter(&ptgt->tgt_mutex);
10899 plun->lun_tgt_count++;
10900 scsi_device_hba_private_set(sd, plun);
10901 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10902 plun->lun_sd = sd;
10903 mutex_exit(&ptgt->tgt_mutex);
10904 mutex_exit(&pptr->port_mutex);
10905
10906 return (DDI_SUCCESS);
10907 }
10908
10909 /*ARGSUSED*/
10910 static int
fcp_virt_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)10911 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10912 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10913 {
10914 uchar_t *bytes;
10915 uint_t nbytes;
10916 uint16_t lun_num;
10917 struct fcp_tgt *ptgt;
10918 struct fcp_lun *plun;
10919 struct fcp_port *pptr = (struct fcp_port *)
10920 hba_tran->tran_hba_private;
10921 child_info_t *cip;
10922
10923 ASSERT(pptr != NULL);
10924
10925 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10926 fcp_trace, FCP_BUF_LEVEL_8, 0,
10927 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10928 " (tgt_dip %p)", ddi_get_name(tgt_dip),
10929 ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10930
10931 cip = (child_info_t *)sd->sd_pathinfo;
10932 if (cip == NULL) {
10933 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10934 fcp_trace, FCP_BUF_LEVEL_8, 0,
10935 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10936 " for %s (instance %d)", ddi_get_name(tgt_dip),
10937 ddi_get_instance(tgt_dip));
10938
10939 return (DDI_NOT_WELL_FORMED);
10940 }
10941
10942 /* get our port WWN property */
10943 bytes = NULL;
10944 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10945 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10946 (nbytes != FC_WWN_SIZE)) {
10947 if (bytes) {
10948 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10949 }
10950 return (DDI_NOT_WELL_FORMED);
10951 }
10952
10953 ASSERT(bytes != NULL);
10954
10955 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10956 LUN_PROP, 0xFFFF);
10957 if (lun_num == 0xFFFF) {
10958 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10959 fcp_trace, FCP_BUF_LEVEL_8, 0,
10960 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10961 " for %s (instance %d)", ddi_get_name(tgt_dip),
10962 ddi_get_instance(tgt_dip));
10963
10964 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10965 return (DDI_NOT_WELL_FORMED);
10966 }
10967
10968 mutex_enter(&pptr->port_mutex);
10969 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10970 mutex_exit(&pptr->port_mutex);
10971 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10972 fcp_trace, FCP_BUF_LEVEL_8, 0,
10973 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10974 " for %s (instance %d)", ddi_get_name(tgt_dip),
10975 ddi_get_instance(tgt_dip));
10976
10977 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10978 return (DDI_FAILURE);
10979 }
10980
10981 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10982 FC_WWN_SIZE) == 0);
10983 ASSERT(plun->lun_num == lun_num);
10984
10985 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10986
10987 ptgt = plun->lun_tgt;
10988
10989 mutex_enter(&ptgt->tgt_mutex);
10990 plun->lun_tgt_count++;
10991 scsi_device_hba_private_set(sd, plun);
10992 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10993 plun->lun_sd = sd;
10994 mutex_exit(&ptgt->tgt_mutex);
10995 mutex_exit(&pptr->port_mutex);
10996
10997 return (DDI_SUCCESS);
10998 }
10999
11000
11001 /*
11002 * called by the transport to do our own target initialization
11003 *
11004 * can acquire and release the global mutex
11005 */
11006 /* ARGSUSED */
11007 static int
fcp_scsi_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)11008 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11009 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11010 {
11011 struct fcp_port *pptr = (struct fcp_port *)
11012 hba_tran->tran_hba_private;
11013 int rval;
11014
11015 ASSERT(pptr != NULL);
11016
11017 /*
11018 * Child node is getting initialized. Look at the mpxio component
11019 * type on the child device to see if this device is mpxio managed
11020 * or not.
11021 */
11022 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11023 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11024 } else {
11025 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11026 }
11027
11028 return (rval);
11029 }
11030
11031
11032 /* ARGSUSED */
11033 static void
fcp_scsi_tgt_free(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)11034 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11035 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11036 {
11037 struct fcp_lun *plun = scsi_device_hba_private_get(sd);
11038 struct fcp_tgt *ptgt;
11039
11040 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11041 fcp_trace, FCP_BUF_LEVEL_8, 0,
11042 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11043 ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11044 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11045
11046 if (plun == NULL) {
11047 return;
11048 }
11049 ptgt = plun->lun_tgt;
11050
11051 ASSERT(ptgt != NULL);
11052
11053 mutex_enter(&ptgt->tgt_mutex);
11054 ASSERT(plun->lun_tgt_count > 0);
11055
11056 if (--plun->lun_tgt_count == 0) {
11057 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11058 }
11059 plun->lun_sd = NULL;
11060 mutex_exit(&ptgt->tgt_mutex);
11061 }
11062
11063 /*
11064 * Function: fcp_scsi_start
11065 *
11066 * Description: This function is called by the target driver to request a
11067 * command to be sent.
11068 *
11069 * Argument: *ap SCSI address of the device.
11070 * *pkt SCSI packet containing the cmd to send.
11071 *
11072 * Return Value: TRAN_ACCEPT
11073 * TRAN_BUSY
11074 * TRAN_BADPKT
11075 * TRAN_FATAL_ERROR
11076 */
11077 static int
fcp_scsi_start(struct scsi_address * ap,struct scsi_pkt * pkt)11078 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11079 {
11080 struct fcp_port *pptr = ADDR2FCP(ap);
11081 struct fcp_lun *plun = ADDR2LUN(ap);
11082 struct fcp_pkt *cmd = PKT2CMD(pkt);
11083 struct fcp_tgt *ptgt = plun->lun_tgt;
11084 int rval;
11085
11086 /* ensure command isn't already issued */
11087 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11088
11089 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11090 fcp_trace, FCP_BUF_LEVEL_9, 0,
11091 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11092
11093 /*
11094 * It is strange that we enter the fcp_port mutex and the target
11095 * mutex to check the lun state (which has a mutex of its own).
11096 */
11097 mutex_enter(&pptr->port_mutex);
11098 mutex_enter(&ptgt->tgt_mutex);
11099
11100 /*
11101 * If the device is offline and is not in the process of coming
11102 * online, fail the request.
11103 */
11104
11105 if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11106 !(plun->lun_state & FCP_LUN_ONLINING)) {
11107 mutex_exit(&ptgt->tgt_mutex);
11108 mutex_exit(&pptr->port_mutex);
11109
11110 if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11111 pkt->pkt_reason = CMD_DEV_GONE;
11112 }
11113
11114 return (TRAN_FATAL_ERROR);
11115 }
11116 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11117
11118 /*
11119 * If we are suspended, kernel is trying to dump, so don't
11120 * block, fail or defer requests - send them down right away.
11121 * NOTE: If we are in panic (i.e. trying to dump), we can't
11122 * assume we have been suspended. There is hardware such as
11123 * the v880 that doesn't do PM. Thus, the check for
11124 * ddi_in_panic.
11125 *
11126 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11127 * of changing. So, if we can queue the packet, do it. Eventually,
11128 * either the device will have gone away or changed and we can fail
11129 * the request, or we can proceed if the device didn't change.
11130 *
11131 * If the pd in the target or the packet is NULL it's probably
11132 * because the device has gone away, we allow the request to be
11133 * put on the internal queue here in case the device comes back within
11134 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11135 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11136 * could be NULL because the device was disappearing during or since
11137 * packet initialization.
11138 */
11139
11140 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11141 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11142 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11143 (ptgt->tgt_pd_handle == NULL) ||
11144 (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11145 /*
11146 * If ((LUN is busy AND
11147 * LUN not suspended AND
11148 * The system is not in panic state) OR
11149 * (The port is coming up))
11150 *
11151 * We check to see if the any of the flags FLAG_NOINTR or
11152 * FLAG_NOQUEUE is set. If one of them is set the value
11153 * returned will be TRAN_BUSY. If not, the request is queued.
11154 */
11155 mutex_exit(&ptgt->tgt_mutex);
11156 mutex_exit(&pptr->port_mutex);
11157
11158 /* see if using interrupts is allowed (so queueing'll work) */
11159 if (pkt->pkt_flags & FLAG_NOINTR) {
11160 pkt->pkt_resid = 0;
11161 return (TRAN_BUSY);
11162 }
11163 if (pkt->pkt_flags & FLAG_NOQUEUE) {
11164 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11165 fcp_trace, FCP_BUF_LEVEL_9, 0,
11166 "fcp_scsi_start: lun busy for pkt %p", pkt);
11167 return (TRAN_BUSY);
11168 }
11169 #ifdef DEBUG
11170 mutex_enter(&pptr->port_pkt_mutex);
11171 pptr->port_npkts++;
11172 mutex_exit(&pptr->port_pkt_mutex);
11173 #endif /* DEBUG */
11174
11175 /* got queue up the pkt for later */
11176 fcp_queue_pkt(pptr, cmd);
11177 return (TRAN_ACCEPT);
11178 }
11179 cmd->cmd_state = FCP_PKT_ISSUED;
11180
11181 mutex_exit(&ptgt->tgt_mutex);
11182 mutex_exit(&pptr->port_mutex);
11183
11184 /*
11185 * Now that we released the mutexes, what was protected by them can
11186 * change.
11187 */
11188
11189 /*
11190 * If there is a reconfiguration in progress, wait for it to complete.
11191 */
11192 fcp_reconfig_wait(pptr);
11193
11194 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11195 pkt->pkt_time : 0;
11196
11197 /* prepare the packet */
11198
11199 fcp_prepare_pkt(pptr, cmd, plun);
11200
11201 if (cmd->cmd_pkt->pkt_time) {
11202 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11203 } else {
11204 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11205 }
11206
11207 /*
11208 * if interrupts aren't allowed (e.g. at dump time) then we'll
11209 * have to do polled I/O
11210 */
11211 if (pkt->pkt_flags & FLAG_NOINTR) {
11212 cmd->cmd_state &= ~FCP_PKT_ISSUED;
11213 return (fcp_dopoll(pptr, cmd));
11214 }
11215
11216 #ifdef DEBUG
11217 mutex_enter(&pptr->port_pkt_mutex);
11218 pptr->port_npkts++;
11219 mutex_exit(&pptr->port_pkt_mutex);
11220 #endif /* DEBUG */
11221
11222 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11223 if (rval == FC_SUCCESS) {
11224 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11225 fcp_trace, FCP_BUF_LEVEL_9, 0,
11226 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11227 return (TRAN_ACCEPT);
11228 }
11229
11230 cmd->cmd_state = FCP_PKT_IDLE;
11231
11232 #ifdef DEBUG
11233 mutex_enter(&pptr->port_pkt_mutex);
11234 pptr->port_npkts--;
11235 mutex_exit(&pptr->port_pkt_mutex);
11236 #endif /* DEBUG */
11237
11238 /*
11239 * For lack of clearer definitions, choose
11240 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11241 */
11242
11243 if (rval == FC_TRAN_BUSY) {
11244 pkt->pkt_resid = 0;
11245 rval = TRAN_BUSY;
11246 } else {
11247 mutex_enter(&ptgt->tgt_mutex);
11248 if (plun->lun_state & FCP_LUN_OFFLINE) {
11249 child_info_t *cip;
11250
11251 mutex_enter(&plun->lun_mutex);
11252 cip = plun->lun_cip;
11253 mutex_exit(&plun->lun_mutex);
11254
11255 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11256 fcp_trace, FCP_BUF_LEVEL_6, 0,
11257 "fcp_transport failed 2 for %x: %x; dip=%p",
11258 plun->lun_tgt->tgt_d_id, rval, cip);
11259
11260 rval = TRAN_FATAL_ERROR;
11261 } else {
11262 if (pkt->pkt_flags & FLAG_NOQUEUE) {
11263 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11264 fcp_trace, FCP_BUF_LEVEL_9, 0,
11265 "fcp_scsi_start: FC_BUSY for pkt %p",
11266 pkt);
11267 rval = TRAN_BUSY;
11268 } else {
11269 rval = TRAN_ACCEPT;
11270 fcp_queue_pkt(pptr, cmd);
11271 }
11272 }
11273 mutex_exit(&ptgt->tgt_mutex);
11274 }
11275
11276 return (rval);
11277 }
11278
11279 /*
11280 * called by the transport to abort a packet
11281 */
11282 /*ARGSUSED*/
11283 static int
fcp_scsi_abort(struct scsi_address * ap,struct scsi_pkt * pkt)11284 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11285 {
11286 int tgt_cnt;
11287 struct fcp_port *pptr = ADDR2FCP(ap);
11288 struct fcp_lun *plun = ADDR2LUN(ap);
11289 struct fcp_tgt *ptgt = plun->lun_tgt;
11290
11291 if (pkt == NULL) {
11292 if (ptgt) {
11293 mutex_enter(&ptgt->tgt_mutex);
11294 tgt_cnt = ptgt->tgt_change_cnt;
11295 mutex_exit(&ptgt->tgt_mutex);
11296 fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11297 return (TRUE);
11298 }
11299 }
11300 return (FALSE);
11301 }
11302
11303
11304 /*
11305 * Perform reset
11306 */
11307 int
fcp_scsi_reset(struct scsi_address * ap,int level)11308 fcp_scsi_reset(struct scsi_address *ap, int level)
11309 {
11310 int rval = 0;
11311 struct fcp_port *pptr = ADDR2FCP(ap);
11312 struct fcp_lun *plun = ADDR2LUN(ap);
11313 struct fcp_tgt *ptgt = plun->lun_tgt;
11314
11315 if (level == RESET_ALL) {
11316 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11317 rval = 1;
11318 }
11319 } else if (level == RESET_TARGET || level == RESET_LUN) {
11320 /*
11321 * If we are in the middle of discovery, return
11322 * SUCCESS as this target will be rediscovered
11323 * anyway
11324 */
11325 mutex_enter(&ptgt->tgt_mutex);
11326 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11327 mutex_exit(&ptgt->tgt_mutex);
11328 return (1);
11329 }
11330 mutex_exit(&ptgt->tgt_mutex);
11331
11332 if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11333 rval = 1;
11334 }
11335 }
11336 return (rval);
11337 }
11338
11339
11340 /*
11341 * called by the framework to get a SCSI capability
11342 */
11343 static int
fcp_scsi_getcap(struct scsi_address * ap,char * cap,int whom)11344 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11345 {
11346 return (fcp_commoncap(ap, cap, 0, whom, 0));
11347 }
11348
11349
11350 /*
11351 * called by the framework to set a SCSI capability
11352 */
11353 static int
fcp_scsi_setcap(struct scsi_address * ap,char * cap,int value,int whom)11354 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11355 {
11356 return (fcp_commoncap(ap, cap, value, whom, 1));
11357 }
11358
11359 /*
11360 * Function: fcp_pkt_setup
11361 *
11362 * Description: This function sets up the scsi_pkt structure passed by the
11363 * caller. This function assumes fcp_pkt_constructor has been
11364 * called previously for the packet passed by the caller. If
11365 * successful this call will have the following results:
11366 *
11367 * - The resources needed that will be constant through out
11368 * the whole transaction are allocated.
11369 * - The fields that will be constant through out the whole
11370 * transaction are initialized.
11371 * - The scsi packet will be linked to the LUN structure
11372 * addressed by the transaction.
11373 *
11374 * Argument:
11375 * *pkt Pointer to a scsi_pkt structure.
11376 * callback
11377 * arg
11378 *
11379 * Return Value: 0 Success
11380 * !0 Failure
11381 *
11382 * Context: Kernel context or interrupt context
11383 */
11384 /* ARGSUSED */
11385 static int
fcp_pkt_setup(struct scsi_pkt * pkt,int (* callback)(caddr_t arg),caddr_t arg)11386 fcp_pkt_setup(struct scsi_pkt *pkt,
11387 int (*callback)(caddr_t arg),
11388 caddr_t arg)
11389 {
11390 struct fcp_pkt *cmd;
11391 struct fcp_port *pptr;
11392 struct fcp_lun *plun;
11393 struct fcp_tgt *ptgt;
11394 int kf;
11395 fc_packet_t *fpkt;
11396 fc_frame_hdr_t *hp;
11397
11398 pptr = ADDR2FCP(&pkt->pkt_address);
11399 plun = ADDR2LUN(&pkt->pkt_address);
11400 ptgt = plun->lun_tgt;
11401
11402 cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11403 fpkt = cmd->cmd_fp_pkt;
11404
11405 /*
11406 * this request is for dma allocation only
11407 */
11408 /*
11409 * First step of fcp_scsi_init_pkt: pkt allocation
11410 * We determine if the caller is willing to wait for the
11411 * resources.
11412 */
11413 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11414
11415 /*
11416 * Selective zeroing of the pkt.
11417 */
11418 cmd->cmd_back = NULL;
11419 cmd->cmd_next = NULL;
11420
11421 /*
11422 * Zero out fcp command
11423 */
11424 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11425
11426 cmd->cmd_state = FCP_PKT_IDLE;
11427
11428 fpkt = cmd->cmd_fp_pkt;
11429 fpkt->pkt_data_acc = NULL;
11430
11431 /*
11432 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11433 * could be destroyed. We need fail pkt_setup.
11434 */
11435 if (pptr->port_state & FCP_STATE_OFFLINE) {
11436 return (-1);
11437 }
11438
11439 mutex_enter(&ptgt->tgt_mutex);
11440 fpkt->pkt_pd = ptgt->tgt_pd_handle;
11441
11442 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11443 != FC_SUCCESS) {
11444 mutex_exit(&ptgt->tgt_mutex);
11445 return (-1);
11446 }
11447
11448 mutex_exit(&ptgt->tgt_mutex);
11449
11450 /* Fill in the Fabric Channel Header */
11451 hp = &fpkt->pkt_cmd_fhdr;
11452 hp->r_ctl = R_CTL_COMMAND;
11453 hp->rsvd = 0;
11454 hp->type = FC_TYPE_SCSI_FCP;
11455 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11456 hp->seq_id = 0;
11457 hp->df_ctl = 0;
11458 hp->seq_cnt = 0;
11459 hp->ox_id = 0xffff;
11460 hp->rx_id = 0xffff;
11461 hp->ro = 0;
11462
11463 /*
11464 * A doubly linked list (cmd_forw, cmd_back) is built
11465 * out of every allocated packet on a per-lun basis
11466 *
11467 * The packets are maintained in the list so as to satisfy
11468 * scsi_abort() requests. At present (which is unlikely to
11469 * change in the future) nobody performs a real scsi_abort
11470 * in the SCSI target drivers (as they don't keep the packets
11471 * after doing scsi_transport - so they don't know how to
11472 * abort a packet other than sending a NULL to abort all
11473 * outstanding packets)
11474 */
11475 mutex_enter(&plun->lun_mutex);
11476 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11477 plun->lun_pkt_head->cmd_back = cmd;
11478 } else {
11479 plun->lun_pkt_tail = cmd;
11480 }
11481 plun->lun_pkt_head = cmd;
11482 mutex_exit(&plun->lun_mutex);
11483 return (0);
11484 }
11485
11486 /*
11487 * Function: fcp_pkt_teardown
11488 *
11489 * Description: This function releases a scsi_pkt structure and all the
11490 * resources attached to it.
11491 *
11492 * Argument: *pkt Pointer to a scsi_pkt structure.
11493 *
11494 * Return Value: None
11495 *
11496 * Context: User, Kernel or Interrupt context.
11497 */
11498 static void
fcp_pkt_teardown(struct scsi_pkt * pkt)11499 fcp_pkt_teardown(struct scsi_pkt *pkt)
11500 {
11501 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
11502 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address);
11503 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11504
11505 /*
11506 * Remove the packet from the per-lun list
11507 */
11508 mutex_enter(&plun->lun_mutex);
11509 if (cmd->cmd_back) {
11510 ASSERT(cmd != plun->lun_pkt_head);
11511 cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11512 } else {
11513 ASSERT(cmd == plun->lun_pkt_head);
11514 plun->lun_pkt_head = cmd->cmd_forw;
11515 }
11516
11517 if (cmd->cmd_forw) {
11518 cmd->cmd_forw->cmd_back = cmd->cmd_back;
11519 } else {
11520 ASSERT(cmd == plun->lun_pkt_tail);
11521 plun->lun_pkt_tail = cmd->cmd_back;
11522 }
11523
11524 mutex_exit(&plun->lun_mutex);
11525
11526 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11527 }
11528
11529 /*
11530 * Routine for reset notification setup, to register or cancel.
11531 * This function is called by SCSA
11532 */
11533 /*ARGSUSED*/
11534 static int
fcp_scsi_reset_notify(struct scsi_address * ap,int flag,void (* callback)(caddr_t),caddr_t arg)11535 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11536 void (*callback)(caddr_t), caddr_t arg)
11537 {
11538 struct fcp_port *pptr = ADDR2FCP(ap);
11539
11540 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11541 &pptr->port_mutex, &pptr->port_reset_notify_listf));
11542 }
11543
11544
11545 static int
fcp_scsi_bus_get_eventcookie(dev_info_t * dip,dev_info_t * rdip,char * name,ddi_eventcookie_t * event_cookiep)11546 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11547 ddi_eventcookie_t *event_cookiep)
11548 {
11549 struct fcp_port *pptr = fcp_dip2port(dip);
11550
11551 if (pptr == NULL) {
11552 return (DDI_FAILURE);
11553 }
11554
11555 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11556 event_cookiep, NDI_EVENT_NOPASS));
11557 }
11558
11559
11560 static int
fcp_scsi_bus_add_eventcall(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t eventid,void (* callback)(),void * arg,ddi_callback_id_t * cb_id)11561 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11562 ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11563 ddi_callback_id_t *cb_id)
11564 {
11565 struct fcp_port *pptr = fcp_dip2port(dip);
11566
11567 if (pptr == NULL) {
11568 return (DDI_FAILURE);
11569 }
11570
11571 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11572 eventid, callback, arg, NDI_SLEEP, cb_id));
11573 }
11574
11575
11576 static int
fcp_scsi_bus_remove_eventcall(dev_info_t * dip,ddi_callback_id_t cb_id)11577 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11578 {
11579
11580 struct fcp_port *pptr = fcp_dip2port(dip);
11581
11582 if (pptr == NULL) {
11583 return (DDI_FAILURE);
11584 }
11585 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11586 }
11587
11588
11589 /*
11590 * called by the transport to post an event
11591 */
11592 static int
fcp_scsi_bus_post_event(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t eventid,void * impldata)11593 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11594 ddi_eventcookie_t eventid, void *impldata)
11595 {
11596 struct fcp_port *pptr = fcp_dip2port(dip);
11597
11598 if (pptr == NULL) {
11599 return (DDI_FAILURE);
11600 }
11601
11602 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11603 eventid, impldata));
11604 }
11605
11606
11607 /*
11608 * A target in in many cases in Fibre Channel has a one to one relation
11609 * with a port identifier (which is also known as D_ID and also as AL_PA
11610 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11611 * will most likely result in resetting all LUNs (which means a reset will
11612 * occur on all the SCSI devices connected at the other end of the bridge)
11613 * That is the latest favorite topic for discussion, for, one can debate as
11614 * hot as one likes and come up with arguably a best solution to one's
11615 * satisfaction
11616 *
11617 * To stay on track and not digress much, here are the problems stated
11618 * briefly:
11619 *
11620 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11621 * target drivers use RESET_TARGET even if their instance is on a
11622 * LUN. Doesn't that sound a bit broken ?
11623 *
11624 * FCP SCSI (the current spec) only defines RESET TARGET in the
11625 * control fields of an FCP_CMND structure. It should have been
11626 * fixed right there, giving flexibility to the initiators to
11627 * minimize havoc that could be caused by resetting a target.
11628 */
11629 static int
fcp_reset_target(struct scsi_address * ap,int level)11630 fcp_reset_target(struct scsi_address *ap, int level)
11631 {
11632 int rval = FC_FAILURE;
11633 char lun_id[25];
11634 struct fcp_port *pptr = ADDR2FCP(ap);
11635 struct fcp_lun *plun = ADDR2LUN(ap);
11636 struct fcp_tgt *ptgt = plun->lun_tgt;
11637 struct scsi_pkt *pkt;
11638 struct fcp_pkt *cmd;
11639 struct fcp_rsp *rsp;
11640 uint32_t tgt_cnt;
11641 struct fcp_rsp_info *rsp_info;
11642 struct fcp_reset_elem *p;
11643 int bval;
11644
11645 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11646 KM_NOSLEEP)) == NULL) {
11647 return (rval);
11648 }
11649
11650 mutex_enter(&ptgt->tgt_mutex);
11651 if (level == RESET_TARGET) {
11652 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11653 mutex_exit(&ptgt->tgt_mutex);
11654 kmem_free(p, sizeof (struct fcp_reset_elem));
11655 return (rval);
11656 }
11657 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11658 (void) strcpy(lun_id, " ");
11659 } else {
11660 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11661 mutex_exit(&ptgt->tgt_mutex);
11662 kmem_free(p, sizeof (struct fcp_reset_elem));
11663 return (rval);
11664 }
11665 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11666
11667 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11668 }
11669 tgt_cnt = ptgt->tgt_change_cnt;
11670
11671 mutex_exit(&ptgt->tgt_mutex);
11672
11673 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11674 0, 0, NULL, 0)) == NULL) {
11675 kmem_free(p, sizeof (struct fcp_reset_elem));
11676 mutex_enter(&ptgt->tgt_mutex);
11677 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11678 mutex_exit(&ptgt->tgt_mutex);
11679 return (rval);
11680 }
11681 pkt->pkt_time = FCP_POLL_TIMEOUT;
11682
11683 /* fill in cmd part of packet */
11684 cmd = PKT2CMD(pkt);
11685 if (level == RESET_TARGET) {
11686 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11687 } else {
11688 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11689 }
11690 cmd->cmd_fp_pkt->pkt_comp = NULL;
11691 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11692
11693 /* prepare a packet for transport */
11694 fcp_prepare_pkt(pptr, cmd, plun);
11695
11696 if (cmd->cmd_pkt->pkt_time) {
11697 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11698 } else {
11699 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11700 }
11701
11702 (void) fc_ulp_busy_port(pptr->port_fp_handle);
11703 bval = fcp_dopoll(pptr, cmd);
11704 fc_ulp_idle_port(pptr->port_fp_handle);
11705
11706 /* submit the packet */
11707 if (bval == TRAN_ACCEPT) {
11708 int error = 3;
11709
11710 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11711 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11712 sizeof (struct fcp_rsp));
11713
11714 if (rsp->fcp_u.fcp_status.rsp_len_set) {
11715 if (fcp_validate_fcp_response(rsp, pptr) ==
11716 FC_SUCCESS) {
11717 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11718 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11719 sizeof (struct fcp_rsp), rsp_info,
11720 cmd->cmd_fp_pkt->pkt_resp_acc,
11721 sizeof (struct fcp_rsp_info));
11722 }
11723 if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11724 rval = FC_SUCCESS;
11725 error = 0;
11726 } else {
11727 error = 1;
11728 }
11729 } else {
11730 error = 2;
11731 }
11732 }
11733
11734 switch (error) {
11735 case 0:
11736 fcp_log(CE_WARN, pptr->port_dip,
11737 "!FCP: WWN 0x%08x%08x %s reset successfully",
11738 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11739 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11740 break;
11741
11742 case 1:
11743 fcp_log(CE_WARN, pptr->port_dip,
11744 "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11745 " response code=%x",
11746 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11747 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11748 rsp_info->rsp_code);
11749 break;
11750
11751 case 2:
11752 fcp_log(CE_WARN, pptr->port_dip,
11753 "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11754 " Bad FCP response values: rsvd1=%x,"
11755 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11756 " rsplen=%x, senselen=%x",
11757 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11758 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11759 rsp->reserved_0, rsp->reserved_1,
11760 rsp->fcp_u.fcp_status.reserved_0,
11761 rsp->fcp_u.fcp_status.reserved_1,
11762 rsp->fcp_response_len, rsp->fcp_sense_len);
11763 break;
11764
11765 default:
11766 fcp_log(CE_WARN, pptr->port_dip,
11767 "!FCP: Reset to WWN 0x%08x%08x %s failed",
11768 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11769 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11770 break;
11771 }
11772 }
11773 scsi_destroy_pkt(pkt);
11774
11775 if (rval == FC_FAILURE) {
11776 mutex_enter(&ptgt->tgt_mutex);
11777 if (level == RESET_TARGET) {
11778 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11779 } else {
11780 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11781 }
11782 mutex_exit(&ptgt->tgt_mutex);
11783 kmem_free(p, sizeof (struct fcp_reset_elem));
11784 return (rval);
11785 }
11786
11787 mutex_enter(&pptr->port_mutex);
11788 if (level == RESET_TARGET) {
11789 p->tgt = ptgt;
11790 p->lun = NULL;
11791 } else {
11792 p->tgt = NULL;
11793 p->lun = plun;
11794 }
11795 p->tgt = ptgt;
11796 p->tgt_cnt = tgt_cnt;
11797 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11798 p->next = pptr->port_reset_list;
11799 pptr->port_reset_list = p;
11800
11801 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11802 fcp_trace, FCP_BUF_LEVEL_3, 0,
11803 "Notify ssd of the reset to reinstate the reservations");
11804
11805 scsi_hba_reset_notify_callback(&pptr->port_mutex,
11806 &pptr->port_reset_notify_listf);
11807
11808 mutex_exit(&pptr->port_mutex);
11809
11810 return (rval);
11811 }
11812
11813
11814 /*
11815 * called by fcp_getcap and fcp_setcap to get and set (respectively)
11816 * SCSI capabilities
11817 */
11818 /* ARGSUSED */
11819 static int
fcp_commoncap(struct scsi_address * ap,char * cap,int val,int tgtonly,int doset)11820 fcp_commoncap(struct scsi_address *ap, char *cap,
11821 int val, int tgtonly, int doset)
11822 {
11823 struct fcp_port *pptr = ADDR2FCP(ap);
11824 struct fcp_lun *plun = ADDR2LUN(ap);
11825 struct fcp_tgt *ptgt = plun->lun_tgt;
11826 int cidx;
11827 int rval = FALSE;
11828
11829 if (cap == (char *)0) {
11830 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11831 fcp_trace, FCP_BUF_LEVEL_3, 0,
11832 "fcp_commoncap: invalid arg");
11833 return (rval);
11834 }
11835
11836 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11837 return (UNDEFINED);
11838 }
11839
11840 /*
11841 * Process setcap request.
11842 */
11843 if (doset) {
11844 /*
11845 * At present, we can only set binary (0/1) values
11846 */
11847 switch (cidx) {
11848 case SCSI_CAP_ARQ:
11849 if (val == 0) {
11850 rval = FALSE;
11851 } else {
11852 rval = TRUE;
11853 }
11854 break;
11855
11856 case SCSI_CAP_LUN_RESET:
11857 if (val) {
11858 plun->lun_cap |= FCP_LUN_CAP_RESET;
11859 } else {
11860 plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11861 }
11862 rval = TRUE;
11863 break;
11864
11865 case SCSI_CAP_SECTOR_SIZE:
11866 rval = TRUE;
11867 break;
11868 default:
11869 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11870 fcp_trace, FCP_BUF_LEVEL_4, 0,
11871 "fcp_setcap: unsupported %d", cidx);
11872 rval = UNDEFINED;
11873 break;
11874 }
11875
11876 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11877 fcp_trace, FCP_BUF_LEVEL_5, 0,
11878 "set cap: cap=%s, val/tgtonly/doset/rval = "
11879 "0x%x/0x%x/0x%x/%d",
11880 cap, val, tgtonly, doset, rval);
11881
11882 } else {
11883 /*
11884 * Process getcap request.
11885 */
11886 switch (cidx) {
11887 case SCSI_CAP_DMA_MAX:
11888 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11889
11890 /*
11891 * Need to make an adjustment qlc is uint_t 64
11892 * st is int, so we will make the adjustment here
11893 * being as nobody wants to touch this.
11894 * It still leaves the max single block length
11895 * of 2 gig. This should last .
11896 */
11897
11898 if (rval == -1) {
11899 rval = MAX_INT_DMA;
11900 }
11901
11902 break;
11903
11904 case SCSI_CAP_INITIATOR_ID:
11905 rval = pptr->port_id;
11906 break;
11907
11908 case SCSI_CAP_ARQ:
11909 case SCSI_CAP_RESET_NOTIFICATION:
11910 case SCSI_CAP_TAGGED_QING:
11911 rval = TRUE;
11912 break;
11913
11914 case SCSI_CAP_SCSI_VERSION:
11915 rval = 3;
11916 break;
11917
11918 case SCSI_CAP_INTERCONNECT_TYPE:
11919 if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11920 (ptgt->tgt_hard_addr == 0)) {
11921 rval = INTERCONNECT_FABRIC;
11922 } else {
11923 rval = INTERCONNECT_FIBRE;
11924 }
11925 break;
11926
11927 case SCSI_CAP_LUN_RESET:
11928 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11929 TRUE : FALSE;
11930 break;
11931
11932 default:
11933 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11934 fcp_trace, FCP_BUF_LEVEL_4, 0,
11935 "fcp_getcap: unsupported %d", cidx);
11936 rval = UNDEFINED;
11937 break;
11938 }
11939
11940 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11941 fcp_trace, FCP_BUF_LEVEL_8, 0,
11942 "get cap: cap=%s, val/tgtonly/doset/rval = "
11943 "0x%x/0x%x/0x%x/%d",
11944 cap, val, tgtonly, doset, rval);
11945 }
11946
11947 return (rval);
11948 }
11949
11950 /*
11951 * called by the transport to get the port-wwn and lun
11952 * properties of this device, and to create a "name" based on them
11953 *
11954 * these properties don't exist on sun4m
11955 *
11956 * return 1 for success else return 0
11957 */
11958 /* ARGSUSED */
11959 static int
fcp_scsi_get_name(struct scsi_device * sd,char * name,int len)11960 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11961 {
11962 int i;
11963 int *lun;
11964 int numChars;
11965 uint_t nlun;
11966 uint_t count;
11967 uint_t nbytes;
11968 uchar_t *bytes;
11969 uint16_t lun_num;
11970 uint32_t tgt_id;
11971 char **conf_wwn;
11972 char tbuf[(FC_WWN_SIZE << 1) + 1];
11973 uchar_t barray[FC_WWN_SIZE];
11974 dev_info_t *tgt_dip;
11975 struct fcp_tgt *ptgt;
11976 struct fcp_port *pptr;
11977 struct fcp_lun *plun;
11978
11979 ASSERT(sd != NULL);
11980 ASSERT(name != NULL);
11981
11982 tgt_dip = sd->sd_dev;
11983 pptr = ddi_get_soft_state(fcp_softstate,
11984 ddi_get_instance(ddi_get_parent(tgt_dip)));
11985 if (pptr == NULL) {
11986 return (0);
11987 }
11988
11989 ASSERT(tgt_dip != NULL);
11990
11991 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11992 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11993 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11994 name[0] = '\0';
11995 return (0);
11996 }
11997
11998 if (nlun == 0) {
11999 ddi_prop_free(lun);
12000 return (0);
12001 }
12002
12003 lun_num = lun[0];
12004 ddi_prop_free(lun);
12005
12006 /*
12007 * Lookup for .conf WWN property
12008 */
12009 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12010 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12011 &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12012 ASSERT(count >= 1);
12013
12014 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12015 ddi_prop_free(conf_wwn);
12016 mutex_enter(&pptr->port_mutex);
12017 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12018 mutex_exit(&pptr->port_mutex);
12019 return (0);
12020 }
12021 ptgt = plun->lun_tgt;
12022 mutex_exit(&pptr->port_mutex);
12023
12024 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12025 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12026
12027 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12028 ptgt->tgt_hard_addr != 0) {
12029 tgt_id = (uint32_t)fcp_alpa_to_switch[
12030 ptgt->tgt_hard_addr];
12031 } else {
12032 tgt_id = ptgt->tgt_d_id;
12033 }
12034
12035 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12036 TARGET_PROP, tgt_id);
12037 }
12038
12039 /* get the our port-wwn property */
12040 bytes = NULL;
12041 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12042 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12043 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12044 if (bytes != NULL) {
12045 ddi_prop_free(bytes);
12046 }
12047 return (0);
12048 }
12049
12050 for (i = 0; i < FC_WWN_SIZE; i++) {
12051 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12052 }
12053
12054 /* Stick in the address of the form "wWWN,LUN" */
12055 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12056
12057 ASSERT(numChars < len);
12058 if (numChars >= len) {
12059 fcp_log(CE_WARN, pptr->port_dip,
12060 "!fcp_scsi_get_name: "
12061 "name parameter length too small, it needs to be %d",
12062 numChars+1);
12063 }
12064
12065 ddi_prop_free(bytes);
12066
12067 return (1);
12068 }
12069
12070
12071 /*
12072 * called by the transport to get the SCSI target id value, returning
12073 * it in "name"
12074 *
12075 * this isn't needed/used on sun4m
12076 *
12077 * return 1 for success else return 0
12078 */
12079 /* ARGSUSED */
12080 static int
fcp_scsi_get_bus_addr(struct scsi_device * sd,char * name,int len)12081 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12082 {
12083 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address);
12084 struct fcp_tgt *ptgt;
12085 int numChars;
12086
12087 if (plun == NULL) {
12088 return (0);
12089 }
12090
12091 if ((ptgt = plun->lun_tgt) == NULL) {
12092 return (0);
12093 }
12094
12095 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12096
12097 ASSERT(numChars < len);
12098 if (numChars >= len) {
12099 fcp_log(CE_WARN, NULL,
12100 "!fcp_scsi_get_bus_addr: "
12101 "name parameter length too small, it needs to be %d",
12102 numChars+1);
12103 }
12104
12105 return (1);
12106 }
12107
12108
12109 /*
12110 * called internally to reset the link where the specified port lives
12111 */
12112 static int
fcp_linkreset(struct fcp_port * pptr,struct scsi_address * ap,int sleep)12113 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12114 {
12115 la_wwn_t wwn;
12116 struct fcp_lun *plun;
12117 struct fcp_tgt *ptgt;
12118
12119 /* disable restart of lip if we're suspended */
12120 mutex_enter(&pptr->port_mutex);
12121
12122 if (pptr->port_state & (FCP_STATE_SUSPENDED |
12123 FCP_STATE_POWER_DOWN)) {
12124 mutex_exit(&pptr->port_mutex);
12125 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12126 fcp_trace, FCP_BUF_LEVEL_2, 0,
12127 "fcp_linkreset, fcp%d: link reset "
12128 "disabled due to DDI_SUSPEND",
12129 ddi_get_instance(pptr->port_dip));
12130 return (FC_FAILURE);
12131 }
12132
12133 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12134 mutex_exit(&pptr->port_mutex);
12135 return (FC_SUCCESS);
12136 }
12137
12138 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12139 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12140
12141 /*
12142 * If ap == NULL assume local link reset.
12143 */
12144 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12145 plun = ADDR2LUN(ap);
12146 ptgt = plun->lun_tgt;
12147 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12148 } else {
12149 bzero((caddr_t)&wwn, sizeof (wwn));
12150 }
12151 mutex_exit(&pptr->port_mutex);
12152
12153 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12154 }
12155
12156
12157 /*
12158 * called from fcp_port_attach() to resume a port
12159 * return DDI_* success/failure status
12160 * acquires and releases the global mutex
12161 * acquires and releases the port mutex
12162 */
12163 /*ARGSUSED*/
12164
12165 static int
fcp_handle_port_resume(opaque_t ulph,fc_ulp_port_info_t * pinfo,uint32_t s_id,fc_attach_cmd_t cmd,int instance)12166 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12167 uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12168 {
12169 int res = DDI_FAILURE; /* default result */
12170 struct fcp_port *pptr; /* port state ptr */
12171 uint32_t alloc_cnt;
12172 uint32_t max_cnt;
12173 fc_portmap_t *tmp_list = NULL;
12174
12175 FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12176 FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12177 instance);
12178
12179 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12180 cmn_err(CE_WARN, "fcp: bad soft state");
12181 return (res);
12182 }
12183
12184 mutex_enter(&pptr->port_mutex);
12185 switch (cmd) {
12186 case FC_CMD_RESUME:
12187 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12188 pptr->port_state &= ~FCP_STATE_SUSPENDED;
12189 break;
12190
12191 case FC_CMD_POWER_UP:
12192 /*
12193 * If the port is DDI_SUSPENded, defer rediscovery
12194 * until DDI_RESUME occurs
12195 */
12196 if (pptr->port_state & FCP_STATE_SUSPENDED) {
12197 pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12198 mutex_exit(&pptr->port_mutex);
12199 return (DDI_SUCCESS);
12200 }
12201 pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12202 }
12203 pptr->port_id = s_id;
12204 pptr->port_state = FCP_STATE_INIT;
12205 mutex_exit(&pptr->port_mutex);
12206
12207 /*
12208 * Make a copy of ulp_port_info as fctl allocates
12209 * a temp struct.
12210 */
12211 (void) fcp_cp_pinfo(pptr, pinfo);
12212
12213 mutex_enter(&fcp_global_mutex);
12214 if (fcp_watchdog_init++ == 0) {
12215 fcp_watchdog_tick = fcp_watchdog_timeout *
12216 drv_usectohz(1000000);
12217 fcp_watchdog_id = timeout(fcp_watch,
12218 NULL, fcp_watchdog_tick);
12219 }
12220 mutex_exit(&fcp_global_mutex);
12221
12222 /*
12223 * Handle various topologies and link states.
12224 */
12225 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12226 case FC_STATE_OFFLINE:
12227 /*
12228 * Wait for ONLINE, at which time a state
12229 * change will cause a statec_callback
12230 */
12231 res = DDI_SUCCESS;
12232 break;
12233
12234 case FC_STATE_ONLINE:
12235
12236 if (pptr->port_topology == FC_TOP_UNKNOWN) {
12237 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12238 res = DDI_SUCCESS;
12239 break;
12240 }
12241
12242 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12243 !fcp_enable_auto_configuration) {
12244 tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12245 if (tmp_list == NULL) {
12246 if (!alloc_cnt) {
12247 res = DDI_SUCCESS;
12248 }
12249 break;
12250 }
12251 max_cnt = alloc_cnt;
12252 } else {
12253 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12254
12255 alloc_cnt = FCP_MAX_DEVICES;
12256
12257 if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12258 (sizeof (fc_portmap_t)) * alloc_cnt,
12259 KM_NOSLEEP)) == NULL) {
12260 fcp_log(CE_WARN, pptr->port_dip,
12261 "!fcp%d: failed to allocate portmap",
12262 instance);
12263 break;
12264 }
12265
12266 max_cnt = alloc_cnt;
12267 if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12268 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12269 FC_SUCCESS) {
12270 caddr_t msg;
12271
12272 (void) fc_ulp_error(res, &msg);
12273
12274 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12275 fcp_trace, FCP_BUF_LEVEL_2, 0,
12276 "resume failed getportmap: reason=0x%x",
12277 res);
12278
12279 fcp_log(CE_WARN, pptr->port_dip,
12280 "!failed to get port map : %s", msg);
12281 break;
12282 }
12283 if (max_cnt > alloc_cnt) {
12284 alloc_cnt = max_cnt;
12285 }
12286 }
12287
12288 /*
12289 * do the SCSI device discovery and create
12290 * the devinfos
12291 */
12292 fcp_statec_callback(ulph, pptr->port_fp_handle,
12293 pptr->port_phys_state, pptr->port_topology, tmp_list,
12294 max_cnt, pptr->port_id);
12295
12296 res = DDI_SUCCESS;
12297 break;
12298
12299 default:
12300 fcp_log(CE_WARN, pptr->port_dip,
12301 "!fcp%d: invalid port state at attach=0x%x",
12302 instance, pptr->port_phys_state);
12303
12304 mutex_enter(&pptr->port_mutex);
12305 pptr->port_phys_state = FCP_STATE_OFFLINE;
12306 mutex_exit(&pptr->port_mutex);
12307 res = DDI_SUCCESS;
12308
12309 break;
12310 }
12311
12312 if (tmp_list != NULL) {
12313 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12314 }
12315
12316 return (res);
12317 }
12318
12319
12320 static void
fcp_cp_pinfo(struct fcp_port * pptr,fc_ulp_port_info_t * pinfo)12321 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12322 {
12323 pptr->port_fp_modlinkage = *pinfo->port_linkage;
12324 pptr->port_dip = pinfo->port_dip;
12325 pptr->port_fp_handle = pinfo->port_handle;
12326 if (pinfo->port_acc_attr != NULL) {
12327 /*
12328 * FCA supports DMA
12329 */
12330 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12331 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12332 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12333 pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12334 }
12335 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12336 pptr->port_max_exch = pinfo->port_fca_max_exch;
12337 pptr->port_phys_state = pinfo->port_state;
12338 pptr->port_topology = pinfo->port_flags;
12339 pptr->port_reset_action = pinfo->port_reset_action;
12340 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12341 pptr->port_fcp_dma = pinfo->port_fcp_dma;
12342 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12343 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12344
12345 /* Clear FMA caps to avoid fm-capability ereport */
12346 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12347 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12348 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12349 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12350 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12351 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12352 }
12353
12354 /*
12355 * If the elements wait field is set to 1 then
12356 * another thread is waiting for the operation to complete. Once
12357 * it is complete, the waiting thread is signaled and the element is
12358 * freed by the waiting thread. If the elements wait field is set to 0
12359 * the element is freed.
12360 */
12361 static void
fcp_process_elem(struct fcp_hp_elem * elem,int result)12362 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12363 {
12364 ASSERT(elem != NULL);
12365 mutex_enter(&elem->mutex);
12366 elem->result = result;
12367 if (elem->wait) {
12368 elem->wait = 0;
12369 cv_signal(&elem->cv);
12370 mutex_exit(&elem->mutex);
12371 } else {
12372 mutex_exit(&elem->mutex);
12373 cv_destroy(&elem->cv);
12374 mutex_destroy(&elem->mutex);
12375 kmem_free(elem, sizeof (struct fcp_hp_elem));
12376 }
12377 }
12378
12379 /*
12380 * This function is invoked from the taskq thread to allocate
12381 * devinfo nodes and to online/offline them.
12382 */
12383 static void
fcp_hp_task(void * arg)12384 fcp_hp_task(void *arg)
12385 {
12386 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg;
12387 struct fcp_lun *plun = elem->lun;
12388 struct fcp_port *pptr = elem->port;
12389 int result;
12390
12391 ASSERT(elem->what == FCP_ONLINE ||
12392 elem->what == FCP_OFFLINE ||
12393 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12394 elem->what == FCP_MPXIO_PATH_SET_BUSY);
12395
12396 mutex_enter(&pptr->port_mutex);
12397 mutex_enter(&plun->lun_mutex);
12398 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12399 plun->lun_event_count != elem->event_cnt) ||
12400 pptr->port_state & (FCP_STATE_SUSPENDED |
12401 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12402 mutex_exit(&plun->lun_mutex);
12403 mutex_exit(&pptr->port_mutex);
12404 fcp_process_elem(elem, NDI_FAILURE);
12405 return;
12406 }
12407 mutex_exit(&plun->lun_mutex);
12408 mutex_exit(&pptr->port_mutex);
12409
12410 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12411 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12412 fcp_process_elem(elem, result);
12413 }
12414
12415
12416 static child_info_t *
fcp_get_cip(struct fcp_lun * plun,child_info_t * cip,int lcount,int tcount)12417 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12418 int tcount)
12419 {
12420 ASSERT(MUTEX_HELD(&plun->lun_mutex));
12421
12422 if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12423 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12424
12425 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12426 /*
12427 * Child has not been created yet. Create the child device
12428 * based on the per-Lun flags.
12429 */
12430 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12431 plun->lun_cip =
12432 CIP(fcp_create_dip(plun, lcount, tcount));
12433 plun->lun_mpxio = 0;
12434 } else {
12435 plun->lun_cip =
12436 CIP(fcp_create_pip(plun, lcount, tcount));
12437 plun->lun_mpxio = 1;
12438 }
12439 } else {
12440 plun->lun_cip = cip;
12441 }
12442
12443 return (plun->lun_cip);
12444 }
12445
12446
12447 static int
fcp_is_dip_present(struct fcp_lun * plun,dev_info_t * cdip)12448 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12449 {
12450 int rval = FC_FAILURE;
12451 dev_info_t *pdip;
12452 struct dev_info *dip;
12453 int circular;
12454
12455 ASSERT(MUTEX_HELD(&plun->lun_mutex));
12456
12457 pdip = plun->lun_tgt->tgt_port->port_dip;
12458
12459 if (plun->lun_cip == NULL) {
12460 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12461 fcp_trace, FCP_BUF_LEVEL_3, 0,
12462 "fcp_is_dip_present: plun->lun_cip is NULL: "
12463 "plun: %p lun state: %x num: %d target state: %x",
12464 plun, plun->lun_state, plun->lun_num,
12465 plun->lun_tgt->tgt_port->port_state);
12466 return (rval);
12467 }
12468 ndi_devi_enter(pdip, &circular);
12469 dip = DEVI(pdip)->devi_child;
12470 while (dip) {
12471 if (dip == DEVI(cdip)) {
12472 rval = FC_SUCCESS;
12473 break;
12474 }
12475 dip = dip->devi_sibling;
12476 }
12477 ndi_devi_exit(pdip, circular);
12478 return (rval);
12479 }
12480
12481 static int
fcp_is_child_present(struct fcp_lun * plun,child_info_t * cip)12482 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12483 {
12484 int rval = FC_FAILURE;
12485
12486 ASSERT(plun != NULL);
12487 ASSERT(MUTEX_HELD(&plun->lun_mutex));
12488
12489 if (plun->lun_mpxio == 0) {
12490 rval = fcp_is_dip_present(plun, DIP(cip));
12491 } else {
12492 rval = fcp_is_pip_present(plun, PIP(cip));
12493 }
12494
12495 return (rval);
12496 }
12497
12498 /*
12499 * Function: fcp_create_dip
12500 *
12501 * Description: Creates a dev_info_t structure for the LUN specified by the
12502 * caller.
12503 *
12504 * Argument: plun Lun structure
12505 * link_cnt Link state count.
12506 * tgt_cnt Target state change count.
12507 *
12508 * Return Value: NULL if it failed
12509 * dev_info_t structure address if it succeeded
12510 *
12511 * Context: Kernel context
12512 */
12513 static dev_info_t *
fcp_create_dip(struct fcp_lun * plun,int link_cnt,int tgt_cnt)12514 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12515 {
12516 int failure = 0;
12517 uint32_t tgt_id;
12518 uint64_t sam_lun;
12519 struct fcp_tgt *ptgt = plun->lun_tgt;
12520 struct fcp_port *pptr = ptgt->tgt_port;
12521 dev_info_t *pdip = pptr->port_dip;
12522 dev_info_t *cdip = NULL;
12523 dev_info_t *old_dip = DIP(plun->lun_cip);
12524 char *nname = NULL;
12525 char **compatible = NULL;
12526 int ncompatible;
12527 char *scsi_binding_set;
12528 char t_pwwn[17];
12529
12530 ASSERT(MUTEX_HELD(&plun->lun_mutex));
12531 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12532
12533 /* get the 'scsi-binding-set' property */
12534 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12535 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12536 &scsi_binding_set) != DDI_PROP_SUCCESS) {
12537 scsi_binding_set = NULL;
12538 }
12539
12540 /* determine the node name and compatible */
12541 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12542 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12543 if (scsi_binding_set) {
12544 ddi_prop_free(scsi_binding_set);
12545 }
12546
12547 if (nname == NULL) {
12548 #ifdef DEBUG
12549 cmn_err(CE_WARN, "%s%d: no driver for "
12550 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12551 " compatible: %s",
12552 ddi_driver_name(pdip), ddi_get_instance(pdip),
12553 ptgt->tgt_port_wwn.raw_wwn[0],
12554 ptgt->tgt_port_wwn.raw_wwn[1],
12555 ptgt->tgt_port_wwn.raw_wwn[2],
12556 ptgt->tgt_port_wwn.raw_wwn[3],
12557 ptgt->tgt_port_wwn.raw_wwn[4],
12558 ptgt->tgt_port_wwn.raw_wwn[5],
12559 ptgt->tgt_port_wwn.raw_wwn[6],
12560 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12561 *compatible);
12562 #endif /* DEBUG */
12563 failure++;
12564 goto end_of_fcp_create_dip;
12565 }
12566
12567 cdip = fcp_find_existing_dip(plun, pdip, nname);
12568
12569 /*
12570 * if the old_dip does not match the cdip, that means there is
12571 * some property change. since we'll be using the cdip, we need
12572 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12573 * then the dtype for the device has been updated. Offline the
12574 * the old device and create a new device with the new device type
12575 * Refer to bug: 4764752
12576 */
12577 if (old_dip && (cdip != old_dip ||
12578 plun->lun_state & FCP_LUN_CHANGED)) {
12579 plun->lun_state &= ~(FCP_LUN_INIT);
12580 mutex_exit(&plun->lun_mutex);
12581 mutex_exit(&pptr->port_mutex);
12582
12583 mutex_enter(&ptgt->tgt_mutex);
12584 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12585 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12586 mutex_exit(&ptgt->tgt_mutex);
12587
12588 #ifdef DEBUG
12589 if (cdip != NULL) {
12590 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12591 fcp_trace, FCP_BUF_LEVEL_2, 0,
12592 "Old dip=%p; New dip=%p don't match", old_dip,
12593 cdip);
12594 } else {
12595 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12596 fcp_trace, FCP_BUF_LEVEL_2, 0,
12597 "Old dip=%p; New dip=NULL don't match", old_dip);
12598 }
12599 #endif
12600
12601 mutex_enter(&pptr->port_mutex);
12602 mutex_enter(&plun->lun_mutex);
12603 }
12604
12605 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12606 plun->lun_state &= ~(FCP_LUN_CHANGED);
12607 if (ndi_devi_alloc(pptr->port_dip, nname,
12608 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12609 failure++;
12610 goto end_of_fcp_create_dip;
12611 }
12612 }
12613
12614 /*
12615 * Previously all the properties for the devinfo were destroyed here
12616 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12617 * the devid property (and other properties established by the target
12618 * driver or framework) which the code does not always recreate, this
12619 * call was removed.
12620 * This opens a theoretical possibility that we may return with a
12621 * stale devid on the node if the scsi entity behind the fibre channel
12622 * lun has changed.
12623 */
12624
12625 /* decorate the node with compatible */
12626 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12627 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12628 failure++;
12629 goto end_of_fcp_create_dip;
12630 }
12631
12632 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12633 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12634 failure++;
12635 goto end_of_fcp_create_dip;
12636 }
12637
12638 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12639 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12640 failure++;
12641 goto end_of_fcp_create_dip;
12642 }
12643
12644 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12645 t_pwwn[16] = '\0';
12646 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12647 != DDI_PROP_SUCCESS) {
12648 failure++;
12649 goto end_of_fcp_create_dip;
12650 }
12651
12652 /*
12653 * If there is no hard address - We might have to deal with
12654 * that by using WWN - Having said that it is important to
12655 * recognize this problem early so ssd can be informed of
12656 * the right interconnect type.
12657 */
12658 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12659 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12660 } else {
12661 tgt_id = ptgt->tgt_d_id;
12662 }
12663
12664 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12665 tgt_id) != DDI_PROP_SUCCESS) {
12666 failure++;
12667 goto end_of_fcp_create_dip;
12668 }
12669
12670 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12671 (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12672 failure++;
12673 goto end_of_fcp_create_dip;
12674 }
12675 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12676 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12677 sam_lun) != DDI_PROP_SUCCESS) {
12678 failure++;
12679 goto end_of_fcp_create_dip;
12680 }
12681
12682 end_of_fcp_create_dip:
12683 scsi_hba_nodename_compatible_free(nname, compatible);
12684
12685 if (cdip != NULL && failure) {
12686 (void) ndi_prop_remove_all(cdip);
12687 (void) ndi_devi_free(cdip);
12688 cdip = NULL;
12689 }
12690
12691 return (cdip);
12692 }
12693
12694 /*
12695 * Function: fcp_create_pip
12696 *
12697 * Description: Creates a Path Id for the LUN specified by the caller.
12698 *
12699 * Argument: plun Lun structure
12700 * link_cnt Link state count.
12701 * tgt_cnt Target state count.
12702 *
12703 * Return Value: NULL if it failed
12704 * mdi_pathinfo_t structure address if it succeeded
12705 *
12706 * Context: Kernel context
12707 */
12708 static mdi_pathinfo_t *
fcp_create_pip(struct fcp_lun * plun,int lcount,int tcount)12709 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12710 {
12711 int i;
12712 char buf[MAXNAMELEN];
12713 char uaddr[MAXNAMELEN];
12714 int failure = 0;
12715 uint32_t tgt_id;
12716 uint64_t sam_lun;
12717 struct fcp_tgt *ptgt = plun->lun_tgt;
12718 struct fcp_port *pptr = ptgt->tgt_port;
12719 dev_info_t *pdip = pptr->port_dip;
12720 mdi_pathinfo_t *pip = NULL;
12721 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip);
12722 char *nname = NULL;
12723 char **compatible = NULL;
12724 int ncompatible;
12725 char *scsi_binding_set;
12726 char t_pwwn[17];
12727
12728 ASSERT(MUTEX_HELD(&plun->lun_mutex));
12729 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12730
12731 scsi_binding_set = "vhci";
12732
12733 /* determine the node name and compatible */
12734 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12735 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12736
12737 if (nname == NULL) {
12738 #ifdef DEBUG
12739 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12740 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12741 " compatible: %s",
12742 ddi_driver_name(pdip), ddi_get_instance(pdip),
12743 ptgt->tgt_port_wwn.raw_wwn[0],
12744 ptgt->tgt_port_wwn.raw_wwn[1],
12745 ptgt->tgt_port_wwn.raw_wwn[2],
12746 ptgt->tgt_port_wwn.raw_wwn[3],
12747 ptgt->tgt_port_wwn.raw_wwn[4],
12748 ptgt->tgt_port_wwn.raw_wwn[5],
12749 ptgt->tgt_port_wwn.raw_wwn[6],
12750 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12751 *compatible);
12752 #endif /* DEBUG */
12753 failure++;
12754 goto end_of_fcp_create_pip;
12755 }
12756
12757 pip = fcp_find_existing_pip(plun, pdip);
12758
12759 /*
12760 * if the old_dip does not match the cdip, that means there is
12761 * some property change. since we'll be using the cdip, we need
12762 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12763 * then the dtype for the device has been updated. Offline the
12764 * the old device and create a new device with the new device type
12765 * Refer to bug: 4764752
12766 */
12767 if (old_pip && (pip != old_pip ||
12768 plun->lun_state & FCP_LUN_CHANGED)) {
12769 plun->lun_state &= ~(FCP_LUN_INIT);
12770 mutex_exit(&plun->lun_mutex);
12771 mutex_exit(&pptr->port_mutex);
12772
12773 mutex_enter(&ptgt->tgt_mutex);
12774 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12775 FCP_OFFLINE, lcount, tcount,
12776 NDI_DEVI_REMOVE, 0);
12777 mutex_exit(&ptgt->tgt_mutex);
12778
12779 if (pip != NULL) {
12780 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12781 fcp_trace, FCP_BUF_LEVEL_2, 0,
12782 "Old pip=%p; New pip=%p don't match",
12783 old_pip, pip);
12784 } else {
12785 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12786 fcp_trace, FCP_BUF_LEVEL_2, 0,
12787 "Old pip=%p; New pip=NULL don't match",
12788 old_pip);
12789 }
12790
12791 mutex_enter(&pptr->port_mutex);
12792 mutex_enter(&plun->lun_mutex);
12793 }
12794
12795 /*
12796 * Since FC_WWN_SIZE is 8 bytes and its not like the
12797 * lun_guid_size which is dependent on the target, I don't
12798 * believe the same trancation happens here UNLESS the standards
12799 * change the FC_WWN_SIZE value to something larger than
12800 * MAXNAMELEN(currently 255 bytes).
12801 */
12802
12803 for (i = 0; i < FC_WWN_SIZE; i++) {
12804 (void) sprintf(&buf[i << 1], "%02x",
12805 ptgt->tgt_port_wwn.raw_wwn[i]);
12806 }
12807
12808 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12809 buf, plun->lun_num);
12810
12811 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12812 /*
12813 * Release the locks before calling into
12814 * mdi_pi_alloc_compatible() since this can result in a
12815 * callback into fcp which can result in a deadlock
12816 * (see bug # 4870272).
12817 *
12818 * Basically, what we are trying to avoid is the scenario where
12819 * one thread does ndi_devi_enter() and tries to grab
12820 * fcp_mutex and another does it the other way round.
12821 *
12822 * But before we do that, make sure that nobody releases the
12823 * port in the meantime. We can do this by setting a flag.
12824 */
12825 plun->lun_state &= ~(FCP_LUN_CHANGED);
12826 pptr->port_state |= FCP_STATE_IN_MDI;
12827 mutex_exit(&plun->lun_mutex);
12828 mutex_exit(&pptr->port_mutex);
12829 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12830 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12831 fcp_log(CE_WARN, pptr->port_dip,
12832 "!path alloc failed:0x%x", plun);
12833 mutex_enter(&pptr->port_mutex);
12834 mutex_enter(&plun->lun_mutex);
12835 pptr->port_state &= ~FCP_STATE_IN_MDI;
12836 failure++;
12837 goto end_of_fcp_create_pip;
12838 }
12839 mutex_enter(&pptr->port_mutex);
12840 mutex_enter(&plun->lun_mutex);
12841 pptr->port_state &= ~FCP_STATE_IN_MDI;
12842 } else {
12843 (void) mdi_prop_remove(pip, NULL);
12844 }
12845
12846 mdi_pi_set_phci_private(pip, (caddr_t)plun);
12847
12848 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12849 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12850 != DDI_PROP_SUCCESS) {
12851 failure++;
12852 goto end_of_fcp_create_pip;
12853 }
12854
12855 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12856 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12857 != DDI_PROP_SUCCESS) {
12858 failure++;
12859 goto end_of_fcp_create_pip;
12860 }
12861
12862 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12863 t_pwwn[16] = '\0';
12864 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12865 != DDI_PROP_SUCCESS) {
12866 failure++;
12867 goto end_of_fcp_create_pip;
12868 }
12869
12870 /*
12871 * If there is no hard address - We might have to deal with
12872 * that by using WWN - Having said that it is important to
12873 * recognize this problem early so ssd can be informed of
12874 * the right interconnect type.
12875 */
12876 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12877 ptgt->tgt_hard_addr != 0) {
12878 tgt_id = (uint32_t)
12879 fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12880 } else {
12881 tgt_id = ptgt->tgt_d_id;
12882 }
12883
12884 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12885 != DDI_PROP_SUCCESS) {
12886 failure++;
12887 goto end_of_fcp_create_pip;
12888 }
12889
12890 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12891 != DDI_PROP_SUCCESS) {
12892 failure++;
12893 goto end_of_fcp_create_pip;
12894 }
12895 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12896 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12897 != DDI_PROP_SUCCESS) {
12898 failure++;
12899 goto end_of_fcp_create_pip;
12900 }
12901
12902 end_of_fcp_create_pip:
12903 scsi_hba_nodename_compatible_free(nname, compatible);
12904
12905 if (pip != NULL && failure) {
12906 (void) mdi_prop_remove(pip, NULL);
12907 mutex_exit(&plun->lun_mutex);
12908 mutex_exit(&pptr->port_mutex);
12909 (void) mdi_pi_free(pip, 0);
12910 mutex_enter(&pptr->port_mutex);
12911 mutex_enter(&plun->lun_mutex);
12912 pip = NULL;
12913 }
12914
12915 return (pip);
12916 }
12917
12918 static dev_info_t *
fcp_find_existing_dip(struct fcp_lun * plun,dev_info_t * pdip,caddr_t name)12919 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12920 {
12921 uint_t nbytes;
12922 uchar_t *bytes;
12923 uint_t nwords;
12924 uint32_t tgt_id;
12925 int *words;
12926 dev_info_t *cdip;
12927 dev_info_t *ndip;
12928 struct fcp_tgt *ptgt = plun->lun_tgt;
12929 struct fcp_port *pptr = ptgt->tgt_port;
12930 int circular;
12931
12932 ndi_devi_enter(pdip, &circular);
12933
12934 ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12935 while ((cdip = ndip) != NULL) {
12936 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12937
12938 if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12939 continue;
12940 }
12941
12942 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12943 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12944 &nbytes) != DDI_PROP_SUCCESS) {
12945 continue;
12946 }
12947
12948 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12949 if (bytes != NULL) {
12950 ddi_prop_free(bytes);
12951 }
12952 continue;
12953 }
12954 ASSERT(bytes != NULL);
12955
12956 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12957 ddi_prop_free(bytes);
12958 continue;
12959 }
12960
12961 ddi_prop_free(bytes);
12962
12963 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12964 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12965 &nbytes) != DDI_PROP_SUCCESS) {
12966 continue;
12967 }
12968
12969 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12970 if (bytes != NULL) {
12971 ddi_prop_free(bytes);
12972 }
12973 continue;
12974 }
12975 ASSERT(bytes != NULL);
12976
12977 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12978 ddi_prop_free(bytes);
12979 continue;
12980 }
12981
12982 ddi_prop_free(bytes);
12983
12984 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12985 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12986 &nwords) != DDI_PROP_SUCCESS) {
12987 continue;
12988 }
12989
12990 if (nwords != 1 || words == NULL) {
12991 if (words != NULL) {
12992 ddi_prop_free(words);
12993 }
12994 continue;
12995 }
12996 ASSERT(words != NULL);
12997
12998 /*
12999 * If there is no hard address - We might have to deal with
13000 * that by using WWN - Having said that it is important to
13001 * recognize this problem early so ssd can be informed of
13002 * the right interconnect type.
13003 */
13004 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13005 ptgt->tgt_hard_addr != 0) {
13006 tgt_id =
13007 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13008 } else {
13009 tgt_id = ptgt->tgt_d_id;
13010 }
13011
13012 if (tgt_id != (uint32_t)*words) {
13013 ddi_prop_free(words);
13014 continue;
13015 }
13016 ddi_prop_free(words);
13017
13018 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13019 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13020 &nwords) != DDI_PROP_SUCCESS) {
13021 continue;
13022 }
13023
13024 if (nwords != 1 || words == NULL) {
13025 if (words != NULL) {
13026 ddi_prop_free(words);
13027 }
13028 continue;
13029 }
13030 ASSERT(words != NULL);
13031
13032 if (plun->lun_num == (uint16_t)*words) {
13033 ddi_prop_free(words);
13034 break;
13035 }
13036 ddi_prop_free(words);
13037 }
13038 ndi_devi_exit(pdip, circular);
13039
13040 return (cdip);
13041 }
13042
13043
13044 static int
fcp_is_pip_present(struct fcp_lun * plun,mdi_pathinfo_t * pip)13045 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13046 {
13047 dev_info_t *pdip;
13048 char buf[MAXNAMELEN];
13049 char uaddr[MAXNAMELEN];
13050 int rval = FC_FAILURE;
13051
13052 ASSERT(MUTEX_HELD(&plun->lun_mutex));
13053
13054 pdip = plun->lun_tgt->tgt_port->port_dip;
13055
13056 /*
13057 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13058 * non-NULL even when the LUN is not there as in the case when a LUN is
13059 * configured and then deleted on the device end (for T3/T4 case). In
13060 * such cases, pip will be NULL.
13061 *
13062 * If the device generates an RSCN, it will end up getting offlined when
13063 * it disappeared and a new LUN will get created when it is rediscovered
13064 * on the device. If we check for lun_cip here, the LUN will not end
13065 * up getting onlined since this function will end up returning a
13066 * FC_SUCCESS.
13067 *
13068 * The behavior is different on other devices. For instance, on a HDS,
13069 * there was no RSCN generated by the device but the next I/O generated
13070 * a check condition and rediscovery got triggered that way. So, in
13071 * such cases, this path will not be exercised
13072 */
13073 if (pip == NULL) {
13074 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13075 fcp_trace, FCP_BUF_LEVEL_4, 0,
13076 "fcp_is_pip_present: plun->lun_cip is NULL: "
13077 "plun: %p lun state: %x num: %d target state: %x",
13078 plun, plun->lun_state, plun->lun_num,
13079 plun->lun_tgt->tgt_port->port_state);
13080 return (rval);
13081 }
13082
13083 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13084
13085 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13086
13087 if (plun->lun_old_guid) {
13088 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13089 rval = FC_SUCCESS;
13090 }
13091 } else {
13092 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13093 rval = FC_SUCCESS;
13094 }
13095 }
13096 return (rval);
13097 }
13098
13099 static mdi_pathinfo_t *
fcp_find_existing_pip(struct fcp_lun * plun,dev_info_t * pdip)13100 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13101 {
13102 char buf[MAXNAMELEN];
13103 char uaddr[MAXNAMELEN];
13104 mdi_pathinfo_t *pip;
13105 struct fcp_tgt *ptgt = plun->lun_tgt;
13106 struct fcp_port *pptr = ptgt->tgt_port;
13107
13108 ASSERT(MUTEX_HELD(&pptr->port_mutex));
13109
13110 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13111 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13112
13113 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13114
13115 return (pip);
13116 }
13117
13118
13119 static int
fcp_online_child(struct fcp_lun * plun,child_info_t * cip,int lcount,int tcount,int flags,int * circ)13120 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13121 int tcount, int flags, int *circ)
13122 {
13123 int rval;
13124 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
13125 struct fcp_tgt *ptgt = plun->lun_tgt;
13126 dev_info_t *cdip = NULL;
13127
13128 ASSERT(MUTEX_HELD(&pptr->port_mutex));
13129 ASSERT(MUTEX_HELD(&plun->lun_mutex));
13130
13131 if (plun->lun_cip == NULL) {
13132 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13133 fcp_trace, FCP_BUF_LEVEL_3, 0,
13134 "fcp_online_child: plun->lun_cip is NULL: "
13135 "plun: %p state: %x num: %d target state: %x",
13136 plun, plun->lun_state, plun->lun_num,
13137 plun->lun_tgt->tgt_port->port_state);
13138 return (NDI_FAILURE);
13139 }
13140 again:
13141 if (plun->lun_mpxio == 0) {
13142 cdip = DIP(cip);
13143 mutex_exit(&plun->lun_mutex);
13144 mutex_exit(&pptr->port_mutex);
13145
13146 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13147 fcp_trace, FCP_BUF_LEVEL_3, 0,
13148 "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13149 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13150
13151 /*
13152 * We could check for FCP_LUN_INIT here but chances
13153 * of getting here when it's already in FCP_LUN_INIT
13154 * is rare and a duplicate ndi_devi_online wouldn't
13155 * hurt either (as the node would already have been
13156 * in CF2)
13157 */
13158 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13159 rval = ndi_devi_bind_driver(cdip, flags);
13160 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13161 fcp_trace, FCP_BUF_LEVEL_3, 0,
13162 "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13163 } else {
13164 rval = ndi_devi_online(cdip, flags);
13165 }
13166
13167 /*
13168 * We log the message into trace buffer if the device
13169 * is "ses" and into syslog for any other device
13170 * type. This is to prevent the ndi_devi_online failure
13171 * message that appears for V880/A5K ses devices.
13172 */
13173 if (rval == NDI_SUCCESS) {
13174 mutex_enter(&ptgt->tgt_mutex);
13175 plun->lun_state |= FCP_LUN_INIT;
13176 mutex_exit(&ptgt->tgt_mutex);
13177 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13178 fcp_log(CE_NOTE, pptr->port_dip,
13179 "!ndi_devi_online:"
13180 " failed for %s: target=%x lun=%x %x",
13181 ddi_get_name(cdip), ptgt->tgt_d_id,
13182 plun->lun_num, rval);
13183 } else {
13184 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13185 fcp_trace, FCP_BUF_LEVEL_3, 0,
13186 " !ndi_devi_online:"
13187 " failed for %s: target=%x lun=%x %x",
13188 ddi_get_name(cdip), ptgt->tgt_d_id,
13189 plun->lun_num, rval);
13190 }
13191 } else {
13192 cdip = mdi_pi_get_client(PIP(cip));
13193 mutex_exit(&plun->lun_mutex);
13194 mutex_exit(&pptr->port_mutex);
13195
13196 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13197 fcp_trace, FCP_BUF_LEVEL_3, 0,
13198 "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13199 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13200
13201 /*
13202 * Hold path and exit phci to avoid deadlock with power
13203 * management code during mdi_pi_online.
13204 */
13205 mdi_hold_path(PIP(cip));
13206 mdi_devi_exit_phci(pptr->port_dip, *circ);
13207
13208 rval = mdi_pi_online(PIP(cip), flags);
13209
13210 mdi_devi_enter_phci(pptr->port_dip, circ);
13211 mdi_rele_path(PIP(cip));
13212
13213 if (rval == MDI_SUCCESS) {
13214 mutex_enter(&ptgt->tgt_mutex);
13215 plun->lun_state |= FCP_LUN_INIT;
13216 mutex_exit(&ptgt->tgt_mutex);
13217
13218 /*
13219 * Clear MPxIO path permanent disable in case
13220 * fcp hotplug dropped the offline event.
13221 */
13222 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13223
13224 } else if (rval == MDI_NOT_SUPPORTED) {
13225 child_info_t *old_cip = cip;
13226
13227 /*
13228 * MPxIO does not support this device yet.
13229 * Enumerate in legacy mode.
13230 */
13231 mutex_enter(&pptr->port_mutex);
13232 mutex_enter(&plun->lun_mutex);
13233 plun->lun_mpxio = 0;
13234 plun->lun_cip = NULL;
13235 cdip = fcp_create_dip(plun, lcount, tcount);
13236 plun->lun_cip = cip = CIP(cdip);
13237 if (cip == NULL) {
13238 fcp_log(CE_WARN, pptr->port_dip,
13239 "!fcp_online_child: "
13240 "Create devinfo failed for LU=%p", plun);
13241 mutex_exit(&plun->lun_mutex);
13242
13243 mutex_enter(&ptgt->tgt_mutex);
13244 plun->lun_state |= FCP_LUN_OFFLINE;
13245 mutex_exit(&ptgt->tgt_mutex);
13246
13247 mutex_exit(&pptr->port_mutex);
13248
13249 /*
13250 * free the mdi_pathinfo node
13251 */
13252 (void) mdi_pi_free(PIP(old_cip), 0);
13253 } else {
13254 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13255 fcp_trace, FCP_BUF_LEVEL_3, 0,
13256 "fcp_online_child: creating devinfo "
13257 "node 0x%p for plun 0x%p",
13258 cip, plun);
13259 mutex_exit(&plun->lun_mutex);
13260 mutex_exit(&pptr->port_mutex);
13261 /*
13262 * free the mdi_pathinfo node
13263 */
13264 (void) mdi_pi_free(PIP(old_cip), 0);
13265 mutex_enter(&pptr->port_mutex);
13266 mutex_enter(&plun->lun_mutex);
13267 goto again;
13268 }
13269 } else {
13270 if (cdip) {
13271 fcp_log(CE_NOTE, pptr->port_dip,
13272 "!fcp_online_child: mdi_pi_online:"
13273 " failed for %s: target=%x lun=%x %x",
13274 ddi_get_name(cdip), ptgt->tgt_d_id,
13275 plun->lun_num, rval);
13276 }
13277 }
13278 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13279 }
13280
13281 if (rval == NDI_SUCCESS) {
13282 if (cdip) {
13283 (void) ndi_event_retrieve_cookie(
13284 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13285 &fcp_insert_eid, NDI_EVENT_NOPASS);
13286 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13287 cdip, fcp_insert_eid, NULL);
13288 }
13289 }
13290 mutex_enter(&pptr->port_mutex);
13291 mutex_enter(&plun->lun_mutex);
13292 return (rval);
13293 }
13294
13295 /* ARGSUSED */
13296 static int
fcp_offline_child(struct fcp_lun * plun,child_info_t * cip,int lcount,int tcount,int flags,int * circ)13297 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13298 int tcount, int flags, int *circ)
13299 {
13300 int rval;
13301 int lun_mpxio;
13302 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
13303 struct fcp_tgt *ptgt = plun->lun_tgt;
13304 dev_info_t *cdip;
13305
13306 ASSERT(MUTEX_HELD(&plun->lun_mutex));
13307 ASSERT(MUTEX_HELD(&pptr->port_mutex));
13308
13309 if (plun->lun_cip == NULL) {
13310 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13311 fcp_trace, FCP_BUF_LEVEL_3, 0,
13312 "fcp_offline_child: plun->lun_cip is NULL: "
13313 "plun: %p lun state: %x num: %d target state: %x",
13314 plun, plun->lun_state, plun->lun_num,
13315 plun->lun_tgt->tgt_port->port_state);
13316 return (NDI_FAILURE);
13317 }
13318
13319 /*
13320 * We will use this value twice. Make a copy to be sure we use
13321 * the same value in both places.
13322 */
13323 lun_mpxio = plun->lun_mpxio;
13324
13325 if (lun_mpxio == 0) {
13326 cdip = DIP(cip);
13327 mutex_exit(&plun->lun_mutex);
13328 mutex_exit(&pptr->port_mutex);
13329 rval = ndi_devi_offline(DIP(cip), flags);
13330 if (rval != NDI_SUCCESS) {
13331 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13332 fcp_trace, FCP_BUF_LEVEL_3, 0,
13333 "fcp_offline_child: ndi_devi_offline failed "
13334 "rval=%x cip=%p", rval, cip);
13335 }
13336 } else {
13337 cdip = mdi_pi_get_client(PIP(cip));
13338 mutex_exit(&plun->lun_mutex);
13339 mutex_exit(&pptr->port_mutex);
13340
13341 /*
13342 * Exit phci to avoid deadlock with power management code
13343 * during mdi_pi_offline
13344 */
13345 mdi_hold_path(PIP(cip));
13346 mdi_devi_exit_phci(pptr->port_dip, *circ);
13347
13348 rval = mdi_pi_offline(PIP(cip), flags);
13349
13350 mdi_devi_enter_phci(pptr->port_dip, circ);
13351 mdi_rele_path(PIP(cip));
13352
13353 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13354 }
13355
13356 mutex_enter(&ptgt->tgt_mutex);
13357 plun->lun_state &= ~FCP_LUN_INIT;
13358 mutex_exit(&ptgt->tgt_mutex);
13359
13360 if (rval == NDI_SUCCESS) {
13361 cdip = NULL;
13362 if (flags & NDI_DEVI_REMOVE) {
13363 mutex_enter(&plun->lun_mutex);
13364 /*
13365 * If the guid of the LUN changes, lun_cip will not
13366 * equal to cip, and after offlining the LUN with the
13367 * old guid, we should keep lun_cip since it's the cip
13368 * of the LUN with the new guid.
13369 * Otherwise remove our reference to child node.
13370 *
13371 * This must be done before the child node is freed,
13372 * otherwise other threads could see a stale lun_cip
13373 * pointer.
13374 */
13375 if (plun->lun_cip == cip) {
13376 plun->lun_cip = NULL;
13377 }
13378 if (plun->lun_old_guid) {
13379 kmem_free(plun->lun_old_guid,
13380 plun->lun_old_guid_size);
13381 plun->lun_old_guid = NULL;
13382 plun->lun_old_guid_size = 0;
13383 }
13384 mutex_exit(&plun->lun_mutex);
13385 }
13386 }
13387
13388 if (lun_mpxio != 0) {
13389 if (rval == NDI_SUCCESS) {
13390 /*
13391 * Clear MPxIO path permanent disable as the path is
13392 * already offlined.
13393 */
13394 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13395
13396 if (flags & NDI_DEVI_REMOVE) {
13397 (void) mdi_pi_free(PIP(cip), 0);
13398 }
13399 } else {
13400 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13401 fcp_trace, FCP_BUF_LEVEL_3, 0,
13402 "fcp_offline_child: mdi_pi_offline failed "
13403 "rval=%x cip=%p", rval, cip);
13404 }
13405 }
13406
13407 mutex_enter(&pptr->port_mutex);
13408 mutex_enter(&plun->lun_mutex);
13409
13410 if (cdip) {
13411 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13412 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13413 " target=%x lun=%x", "ndi_offline",
13414 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13415 }
13416
13417 return (rval);
13418 }
13419
13420 static void
fcp_remove_child(struct fcp_lun * plun)13421 fcp_remove_child(struct fcp_lun *plun)
13422 {
13423 child_info_t *cip;
13424 int circ;
13425
13426 ASSERT(MUTEX_HELD(&plun->lun_mutex));
13427
13428 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13429 if (plun->lun_mpxio == 0) {
13430 (void) ndi_prop_remove_all(DIP(plun->lun_cip));
13431 (void) ndi_devi_free(DIP(plun->lun_cip));
13432 plun->lun_cip = NULL;
13433 } else {
13434 /*
13435 * Clear reference to the child node in the lun.
13436 * This must be done before freeing it with mdi_pi_free
13437 * and with lun_mutex held so that other threads always
13438 * see either valid lun_cip or NULL when holding
13439 * lun_mutex. We keep a copy in cip.
13440 */
13441 cip = plun->lun_cip;
13442 plun->lun_cip = NULL;
13443
13444 mutex_exit(&plun->lun_mutex);
13445 mutex_exit(&plun->lun_tgt->tgt_mutex);
13446 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13447
13448 mdi_devi_enter(
13449 plun->lun_tgt->tgt_port->port_dip, &circ);
13450
13451 /*
13452 * Exit phci to avoid deadlock with power management
13453 * code during mdi_pi_offline
13454 */
13455 mdi_hold_path(PIP(cip));
13456 mdi_devi_exit_phci(
13457 plun->lun_tgt->tgt_port->port_dip, circ);
13458 (void) mdi_pi_offline(PIP(cip),
13459 NDI_DEVI_REMOVE);
13460 mdi_devi_enter_phci(
13461 plun->lun_tgt->tgt_port->port_dip, &circ);
13462 mdi_rele_path(PIP(cip));
13463
13464 mdi_devi_exit(
13465 plun->lun_tgt->tgt_port->port_dip, circ);
13466
13467 FCP_TRACE(fcp_logq,
13468 plun->lun_tgt->tgt_port->port_instbuf,
13469 fcp_trace, FCP_BUF_LEVEL_3, 0,
13470 "lun=%p pip freed %p", plun, cip);
13471
13472 (void) mdi_prop_remove(PIP(cip), NULL);
13473 (void) mdi_pi_free(PIP(cip), 0);
13474
13475 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13476 mutex_enter(&plun->lun_tgt->tgt_mutex);
13477 mutex_enter(&plun->lun_mutex);
13478 }
13479 } else {
13480 plun->lun_cip = NULL;
13481 }
13482 }
13483
13484 /*
13485 * called when a timeout occurs
13486 *
13487 * can be scheduled during an attach or resume (if not already running)
13488 *
13489 * one timeout is set up for all ports
13490 *
13491 * acquires and releases the global mutex
13492 */
13493 /*ARGSUSED*/
13494 static void
fcp_watch(void * arg)13495 fcp_watch(void *arg)
13496 {
13497 struct fcp_port *pptr;
13498 struct fcp_ipkt *icmd;
13499 struct fcp_ipkt *nicmd;
13500 struct fcp_pkt *cmd;
13501 struct fcp_pkt *ncmd;
13502 struct fcp_pkt *tail;
13503 struct fcp_pkt *pcmd;
13504 struct fcp_pkt *save_head;
13505 struct fcp_port *save_port;
13506
13507 /* increment global watchdog time */
13508 fcp_watchdog_time += fcp_watchdog_timeout;
13509
13510 mutex_enter(&fcp_global_mutex);
13511
13512 /* scan each port in our list */
13513 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13514 save_port = fcp_port_head;
13515 pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13516 mutex_exit(&fcp_global_mutex);
13517
13518 mutex_enter(&pptr->port_mutex);
13519 if (pptr->port_ipkt_list == NULL &&
13520 (pptr->port_state & (FCP_STATE_SUSPENDED |
13521 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13522 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13523 mutex_exit(&pptr->port_mutex);
13524 mutex_enter(&fcp_global_mutex);
13525 goto end_of_watchdog;
13526 }
13527
13528 /*
13529 * We check if a list of targets need to be offlined.
13530 */
13531 if (pptr->port_offline_tgts) {
13532 fcp_scan_offline_tgts(pptr);
13533 }
13534
13535 /*
13536 * We check if a list of luns need to be offlined.
13537 */
13538 if (pptr->port_offline_luns) {
13539 fcp_scan_offline_luns(pptr);
13540 }
13541
13542 /*
13543 * We check if a list of targets or luns need to be reset.
13544 */
13545 if (pptr->port_reset_list) {
13546 fcp_check_reset_delay(pptr);
13547 }
13548
13549 mutex_exit(&pptr->port_mutex);
13550
13551 /*
13552 * This is where the pending commands (pkt) are checked for
13553 * timeout.
13554 */
13555 mutex_enter(&pptr->port_pkt_mutex);
13556 tail = pptr->port_pkt_tail;
13557
13558 for (pcmd = NULL, cmd = pptr->port_pkt_head;
13559 cmd != NULL; cmd = ncmd) {
13560 ncmd = cmd->cmd_next;
13561 /*
13562 * If a command is in this queue the bit CFLAG_IN_QUEUE
13563 * must be set.
13564 */
13565 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13566 /*
13567 * FCP_INVALID_TIMEOUT will be set for those
13568 * command that need to be failed. Mostly those
13569 * cmds that could not be queued down for the
13570 * "timeout" value. cmd->cmd_timeout is used
13571 * to try and requeue the command regularly.
13572 */
13573 if (cmd->cmd_timeout >= fcp_watchdog_time) {
13574 /*
13575 * This command hasn't timed out yet. Let's
13576 * go to the next one.
13577 */
13578 pcmd = cmd;
13579 goto end_of_loop;
13580 }
13581
13582 if (cmd == pptr->port_pkt_head) {
13583 ASSERT(pcmd == NULL);
13584 pptr->port_pkt_head = cmd->cmd_next;
13585 } else {
13586 ASSERT(pcmd != NULL);
13587 pcmd->cmd_next = cmd->cmd_next;
13588 }
13589
13590 if (cmd == pptr->port_pkt_tail) {
13591 ASSERT(cmd->cmd_next == NULL);
13592 pptr->port_pkt_tail = pcmd;
13593 if (pcmd) {
13594 pcmd->cmd_next = NULL;
13595 }
13596 }
13597 cmd->cmd_next = NULL;
13598
13599 /*
13600 * save the current head before dropping the
13601 * mutex - If the head doesn't remain the
13602 * same after re acquiring the mutex, just
13603 * bail out and revisit on next tick.
13604 *
13605 * PS: The tail pointer can change as the commands
13606 * get requeued after failure to retransport
13607 */
13608 save_head = pptr->port_pkt_head;
13609 mutex_exit(&pptr->port_pkt_mutex);
13610
13611 if (cmd->cmd_fp_pkt->pkt_timeout ==
13612 FCP_INVALID_TIMEOUT) {
13613 struct scsi_pkt *pkt = cmd->cmd_pkt;
13614 struct fcp_lun *plun;
13615 struct fcp_tgt *ptgt;
13616
13617 plun = ADDR2LUN(&pkt->pkt_address);
13618 ptgt = plun->lun_tgt;
13619
13620 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13621 fcp_trace, FCP_BUF_LEVEL_2, 0,
13622 "SCSI cmd 0x%x to D_ID=%x timed out",
13623 pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13624
13625 cmd->cmd_state == FCP_PKT_ABORTING ?
13626 fcp_fail_cmd(cmd, CMD_RESET,
13627 STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13628 CMD_TIMEOUT, STAT_ABORTED);
13629 } else {
13630 fcp_retransport_cmd(pptr, cmd);
13631 }
13632 mutex_enter(&pptr->port_pkt_mutex);
13633 if (save_head && save_head != pptr->port_pkt_head) {
13634 /*
13635 * Looks like linked list got changed (mostly
13636 * happens when an an OFFLINE LUN code starts
13637 * returning overflow queue commands in
13638 * parallel. So bail out and revisit during
13639 * next tick
13640 */
13641 break;
13642 }
13643 end_of_loop:
13644 /*
13645 * Scan only upto the previously known tail pointer
13646 * to avoid excessive processing - lots of new packets
13647 * could have been added to the tail or the old ones
13648 * re-queued.
13649 */
13650 if (cmd == tail) {
13651 break;
13652 }
13653 }
13654 mutex_exit(&pptr->port_pkt_mutex);
13655
13656 mutex_enter(&pptr->port_mutex);
13657 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13658 struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13659
13660 nicmd = icmd->ipkt_next;
13661 if ((icmd->ipkt_restart != 0) &&
13662 (icmd->ipkt_restart >= fcp_watchdog_time)) {
13663 /* packet has not timed out */
13664 continue;
13665 }
13666
13667 /* time for packet re-transport */
13668 if (icmd == pptr->port_ipkt_list) {
13669 pptr->port_ipkt_list = icmd->ipkt_next;
13670 if (pptr->port_ipkt_list) {
13671 pptr->port_ipkt_list->ipkt_prev =
13672 NULL;
13673 }
13674 } else {
13675 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13676 if (icmd->ipkt_next) {
13677 icmd->ipkt_next->ipkt_prev =
13678 icmd->ipkt_prev;
13679 }
13680 }
13681 icmd->ipkt_next = NULL;
13682 icmd->ipkt_prev = NULL;
13683 mutex_exit(&pptr->port_mutex);
13684
13685 if (fcp_is_retryable(icmd)) {
13686 fc_ulp_rscn_info_t *rscnp =
13687 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13688 pkt_ulp_rscn_infop;
13689
13690 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13691 fcp_trace, FCP_BUF_LEVEL_2, 0,
13692 "%x to D_ID=%x Retrying..",
13693 icmd->ipkt_opcode,
13694 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13695
13696 /*
13697 * Update the RSCN count in the packet
13698 * before resending.
13699 */
13700
13701 if (rscnp != NULL) {
13702 rscnp->ulp_rscn_count =
13703 fc_ulp_get_rscn_count(pptr->
13704 port_fp_handle);
13705 }
13706
13707 mutex_enter(&pptr->port_mutex);
13708 mutex_enter(&ptgt->tgt_mutex);
13709 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13710 mutex_exit(&ptgt->tgt_mutex);
13711 mutex_exit(&pptr->port_mutex);
13712 switch (icmd->ipkt_opcode) {
13713 int rval;
13714 case LA_ELS_PLOGI:
13715 if ((rval = fc_ulp_login(
13716 pptr->port_fp_handle,
13717 &icmd->ipkt_fpkt, 1)) ==
13718 FC_SUCCESS) {
13719 mutex_enter(
13720 &pptr->port_mutex);
13721 continue;
13722 }
13723 if (fcp_handle_ipkt_errors(
13724 pptr, ptgt, icmd, rval,
13725 "PLOGI") == DDI_SUCCESS) {
13726 mutex_enter(
13727 &pptr->port_mutex);
13728 continue;
13729 }
13730 break;
13731
13732 case LA_ELS_PRLI:
13733 if ((rval = fc_ulp_issue_els(
13734 pptr->port_fp_handle,
13735 icmd->ipkt_fpkt)) ==
13736 FC_SUCCESS) {
13737 mutex_enter(
13738 &pptr->port_mutex);
13739 continue;
13740 }
13741 if (fcp_handle_ipkt_errors(
13742 pptr, ptgt, icmd, rval,
13743 "PRLI") == DDI_SUCCESS) {
13744 mutex_enter(
13745 &pptr->port_mutex);
13746 continue;
13747 }
13748 break;
13749
13750 default:
13751 if ((rval = fcp_transport(
13752 pptr->port_fp_handle,
13753 icmd->ipkt_fpkt, 1)) ==
13754 FC_SUCCESS) {
13755 mutex_enter(
13756 &pptr->port_mutex);
13757 continue;
13758 }
13759 if (fcp_handle_ipkt_errors(
13760 pptr, ptgt, icmd, rval,
13761 "PRLI") == DDI_SUCCESS) {
13762 mutex_enter(
13763 &pptr->port_mutex);
13764 continue;
13765 }
13766 break;
13767 }
13768 } else {
13769 mutex_exit(&ptgt->tgt_mutex);
13770 mutex_exit(&pptr->port_mutex);
13771 }
13772 } else {
13773 fcp_print_error(icmd->ipkt_fpkt);
13774 }
13775
13776 (void) fcp_call_finish_init(pptr, ptgt,
13777 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13778 icmd->ipkt_cause);
13779 fcp_icmd_free(pptr, icmd);
13780 mutex_enter(&pptr->port_mutex);
13781 }
13782
13783 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13784 mutex_exit(&pptr->port_mutex);
13785 mutex_enter(&fcp_global_mutex);
13786
13787 end_of_watchdog:
13788 /*
13789 * Bail out early before getting into trouble
13790 */
13791 if (save_port != fcp_port_head) {
13792 break;
13793 }
13794 }
13795
13796 if (fcp_watchdog_init > 0) {
13797 /* reschedule timeout to go again */
13798 fcp_watchdog_id =
13799 timeout(fcp_watch, NULL, fcp_watchdog_tick);
13800 }
13801 mutex_exit(&fcp_global_mutex);
13802 }
13803
13804
13805 static void
fcp_check_reset_delay(struct fcp_port * pptr)13806 fcp_check_reset_delay(struct fcp_port *pptr)
13807 {
13808 uint32_t tgt_cnt;
13809 int level;
13810 struct fcp_tgt *ptgt;
13811 struct fcp_lun *plun;
13812 struct fcp_reset_elem *cur = NULL;
13813 struct fcp_reset_elem *next = NULL;
13814 struct fcp_reset_elem *prev = NULL;
13815
13816 ASSERT(mutex_owned(&pptr->port_mutex));
13817
13818 next = pptr->port_reset_list;
13819 while ((cur = next) != NULL) {
13820 next = cur->next;
13821
13822 if (cur->timeout < fcp_watchdog_time) {
13823 prev = cur;
13824 continue;
13825 }
13826
13827 ptgt = cur->tgt;
13828 plun = cur->lun;
13829 tgt_cnt = cur->tgt_cnt;
13830
13831 if (ptgt) {
13832 level = RESET_TARGET;
13833 } else {
13834 ASSERT(plun != NULL);
13835 level = RESET_LUN;
13836 ptgt = plun->lun_tgt;
13837 }
13838 if (prev) {
13839 prev->next = next;
13840 } else {
13841 /*
13842 * Because we drop port mutex while doing aborts for
13843 * packets, we can't rely on reset_list pointing to
13844 * our head
13845 */
13846 if (cur == pptr->port_reset_list) {
13847 pptr->port_reset_list = next;
13848 } else {
13849 struct fcp_reset_elem *which;
13850
13851 which = pptr->port_reset_list;
13852 while (which && which->next != cur) {
13853 which = which->next;
13854 }
13855 ASSERT(which != NULL);
13856
13857 which->next = next;
13858 prev = which;
13859 }
13860 }
13861
13862 kmem_free(cur, sizeof (*cur));
13863
13864 if (tgt_cnt == ptgt->tgt_change_cnt) {
13865 mutex_enter(&ptgt->tgt_mutex);
13866 if (level == RESET_TARGET) {
13867 fcp_update_tgt_state(ptgt,
13868 FCP_RESET, FCP_LUN_BUSY);
13869 } else {
13870 fcp_update_lun_state(plun,
13871 FCP_RESET, FCP_LUN_BUSY);
13872 }
13873 mutex_exit(&ptgt->tgt_mutex);
13874
13875 mutex_exit(&pptr->port_mutex);
13876 fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13877 mutex_enter(&pptr->port_mutex);
13878 }
13879 }
13880 }
13881
13882
13883 static void
fcp_abort_all(struct fcp_port * pptr,struct fcp_tgt * ttgt,struct fcp_lun * rlun,int tgt_cnt)13884 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13885 struct fcp_lun *rlun, int tgt_cnt)
13886 {
13887 int rval;
13888 struct fcp_lun *tlun, *nlun;
13889 struct fcp_pkt *pcmd = NULL, *ncmd = NULL,
13890 *cmd = NULL, *head = NULL,
13891 *tail = NULL;
13892
13893 mutex_enter(&pptr->port_pkt_mutex);
13894 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13895 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13896 struct fcp_tgt *ptgt = plun->lun_tgt;
13897
13898 ncmd = cmd->cmd_next;
13899
13900 if (ptgt != ttgt && plun != rlun) {
13901 pcmd = cmd;
13902 continue;
13903 }
13904
13905 if (pcmd != NULL) {
13906 ASSERT(pptr->port_pkt_head != cmd);
13907 pcmd->cmd_next = ncmd;
13908 } else {
13909 ASSERT(cmd == pptr->port_pkt_head);
13910 pptr->port_pkt_head = ncmd;
13911 }
13912 if (pptr->port_pkt_tail == cmd) {
13913 ASSERT(cmd->cmd_next == NULL);
13914 pptr->port_pkt_tail = pcmd;
13915 if (pcmd != NULL) {
13916 pcmd->cmd_next = NULL;
13917 }
13918 }
13919
13920 if (head == NULL) {
13921 head = tail = cmd;
13922 } else {
13923 ASSERT(tail != NULL);
13924 tail->cmd_next = cmd;
13925 tail = cmd;
13926 }
13927 cmd->cmd_next = NULL;
13928 }
13929 mutex_exit(&pptr->port_pkt_mutex);
13930
13931 for (cmd = head; cmd != NULL; cmd = ncmd) {
13932 struct scsi_pkt *pkt = cmd->cmd_pkt;
13933
13934 ncmd = cmd->cmd_next;
13935 ASSERT(pkt != NULL);
13936
13937 mutex_enter(&pptr->port_mutex);
13938 if (ttgt->tgt_change_cnt == tgt_cnt) {
13939 mutex_exit(&pptr->port_mutex);
13940 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13941 pkt->pkt_reason = CMD_RESET;
13942 pkt->pkt_statistics |= STAT_DEV_RESET;
13943 cmd->cmd_state = FCP_PKT_IDLE;
13944 fcp_post_callback(cmd);
13945 } else {
13946 mutex_exit(&pptr->port_mutex);
13947 }
13948 }
13949
13950 /*
13951 * If the FCA will return all the commands in its queue then our
13952 * work is easy, just return.
13953 */
13954
13955 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13956 return;
13957 }
13958
13959 /*
13960 * For RESET_LUN get hold of target pointer
13961 */
13962 if (ttgt == NULL) {
13963 ASSERT(rlun != NULL);
13964
13965 ttgt = rlun->lun_tgt;
13966
13967 ASSERT(ttgt != NULL);
13968 }
13969
13970 /*
13971 * There are some severe race conditions here.
13972 * While we are trying to abort the pkt, it might be completing
13973 * so mark it aborted and if the abort does not succeed then
13974 * handle it in the watch thread.
13975 */
13976 mutex_enter(&ttgt->tgt_mutex);
13977 nlun = ttgt->tgt_lun;
13978 mutex_exit(&ttgt->tgt_mutex);
13979 while ((tlun = nlun) != NULL) {
13980 int restart = 0;
13981 if (rlun && rlun != tlun) {
13982 mutex_enter(&ttgt->tgt_mutex);
13983 nlun = tlun->lun_next;
13984 mutex_exit(&ttgt->tgt_mutex);
13985 continue;
13986 }
13987 mutex_enter(&tlun->lun_mutex);
13988 cmd = tlun->lun_pkt_head;
13989 while (cmd != NULL) {
13990 if (cmd->cmd_state == FCP_PKT_ISSUED) {
13991 struct scsi_pkt *pkt;
13992
13993 restart = 1;
13994 cmd->cmd_state = FCP_PKT_ABORTING;
13995 mutex_exit(&tlun->lun_mutex);
13996 rval = fc_ulp_abort(pptr->port_fp_handle,
13997 cmd->cmd_fp_pkt, KM_SLEEP);
13998 if (rval == FC_SUCCESS) {
13999 pkt = cmd->cmd_pkt;
14000 pkt->pkt_reason = CMD_RESET;
14001 pkt->pkt_statistics |= STAT_DEV_RESET;
14002 cmd->cmd_state = FCP_PKT_IDLE;
14003 fcp_post_callback(cmd);
14004 } else {
14005 caddr_t msg;
14006
14007 (void) fc_ulp_error(rval, &msg);
14008
14009 /*
14010 * This part is tricky. The abort
14011 * failed and now the command could
14012 * be completing. The cmd_state ==
14013 * FCP_PKT_ABORTING should save
14014 * us in fcp_cmd_callback. If we
14015 * are already aborting ignore the
14016 * command in fcp_cmd_callback.
14017 * Here we leave this packet for 20
14018 * sec to be aborted in the
14019 * fcp_watch thread.
14020 */
14021 fcp_log(CE_WARN, pptr->port_dip,
14022 "!Abort failed after reset %s",
14023 msg);
14024
14025 cmd->cmd_timeout =
14026 fcp_watchdog_time +
14027 cmd->cmd_pkt->pkt_time +
14028 FCP_FAILED_DELAY;
14029
14030 cmd->cmd_fp_pkt->pkt_timeout =
14031 FCP_INVALID_TIMEOUT;
14032 /*
14033 * This is a hack, cmd is put in the
14034 * overflow queue so that it can be
14035 * timed out finally
14036 */
14037 cmd->cmd_flags |= CFLAG_IN_QUEUE;
14038
14039 mutex_enter(&pptr->port_pkt_mutex);
14040 if (pptr->port_pkt_head) {
14041 ASSERT(pptr->port_pkt_tail
14042 != NULL);
14043 pptr->port_pkt_tail->cmd_next
14044 = cmd;
14045 pptr->port_pkt_tail = cmd;
14046 } else {
14047 ASSERT(pptr->port_pkt_tail
14048 == NULL);
14049 pptr->port_pkt_head =
14050 pptr->port_pkt_tail
14051 = cmd;
14052 }
14053 cmd->cmd_next = NULL;
14054 mutex_exit(&pptr->port_pkt_mutex);
14055 }
14056 mutex_enter(&tlun->lun_mutex);
14057 cmd = tlun->lun_pkt_head;
14058 } else {
14059 cmd = cmd->cmd_forw;
14060 }
14061 }
14062 mutex_exit(&tlun->lun_mutex);
14063
14064 mutex_enter(&ttgt->tgt_mutex);
14065 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14066 mutex_exit(&ttgt->tgt_mutex);
14067
14068 mutex_enter(&pptr->port_mutex);
14069 if (tgt_cnt != ttgt->tgt_change_cnt) {
14070 mutex_exit(&pptr->port_mutex);
14071 return;
14072 } else {
14073 mutex_exit(&pptr->port_mutex);
14074 }
14075 }
14076 }
14077
14078
14079 /*
14080 * unlink the soft state, returning the soft state found (if any)
14081 *
14082 * acquires and releases the global mutex
14083 */
14084 struct fcp_port *
fcp_soft_state_unlink(struct fcp_port * pptr)14085 fcp_soft_state_unlink(struct fcp_port *pptr)
14086 {
14087 struct fcp_port *hptr; /* ptr index */
14088 struct fcp_port *tptr; /* prev hptr */
14089
14090 mutex_enter(&fcp_global_mutex);
14091 for (hptr = fcp_port_head, tptr = NULL;
14092 hptr != NULL;
14093 tptr = hptr, hptr = hptr->port_next) {
14094 if (hptr == pptr) {
14095 /* we found a match -- remove this item */
14096 if (tptr == NULL) {
14097 /* we're at the head of the list */
14098 fcp_port_head = hptr->port_next;
14099 } else {
14100 tptr->port_next = hptr->port_next;
14101 }
14102 break; /* success */
14103 }
14104 }
14105 if (fcp_port_head == NULL) {
14106 fcp_cleanup_blacklist(&fcp_lun_blacklist);
14107 }
14108 mutex_exit(&fcp_global_mutex);
14109 return (hptr);
14110 }
14111
14112
14113 /*
14114 * called by fcp_scsi_hba_tgt_init to find a LUN given a
14115 * WWN and a LUN number
14116 */
14117 /* ARGSUSED */
14118 static struct fcp_lun *
fcp_lookup_lun(struct fcp_port * pptr,uchar_t * wwn,uint16_t lun)14119 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14120 {
14121 int hash;
14122 struct fcp_tgt *ptgt;
14123 struct fcp_lun *plun;
14124
14125 ASSERT(mutex_owned(&pptr->port_mutex));
14126
14127 hash = FCP_HASH(wwn);
14128 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14129 ptgt = ptgt->tgt_next) {
14130 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14131 sizeof (ptgt->tgt_port_wwn)) == 0) {
14132 mutex_enter(&ptgt->tgt_mutex);
14133 for (plun = ptgt->tgt_lun;
14134 plun != NULL;
14135 plun = plun->lun_next) {
14136 if (plun->lun_num == lun) {
14137 mutex_exit(&ptgt->tgt_mutex);
14138 return (plun);
14139 }
14140 }
14141 mutex_exit(&ptgt->tgt_mutex);
14142 return (NULL);
14143 }
14144 }
14145 return (NULL);
14146 }
14147
14148 /*
14149 * Function: fcp_prepare_pkt
14150 *
14151 * Description: This function prepares the SCSI cmd pkt, passed by the caller,
14152 * for fcp_start(). It binds the data or partially maps it.
14153 * Builds the FCP header and starts the initialization of the
14154 * Fibre Channel header.
14155 *
14156 * Argument: *pptr FCP port.
14157 * *cmd FCP packet.
14158 * *plun LUN the command will be sent to.
14159 *
14160 * Context: User, Kernel and Interrupt context.
14161 */
14162 static void
fcp_prepare_pkt(struct fcp_port * pptr,struct fcp_pkt * cmd,struct fcp_lun * plun)14163 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14164 struct fcp_lun *plun)
14165 {
14166 fc_packet_t *fpkt = cmd->cmd_fp_pkt;
14167 struct fcp_tgt *ptgt = plun->lun_tgt;
14168 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd;
14169
14170 ASSERT(cmd->cmd_pkt->pkt_comp ||
14171 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14172
14173 if (cmd->cmd_pkt->pkt_numcookies) {
14174 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14175 fcmd->fcp_cntl.cntl_read_data = 1;
14176 fcmd->fcp_cntl.cntl_write_data = 0;
14177 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14178 } else {
14179 fcmd->fcp_cntl.cntl_read_data = 0;
14180 fcmd->fcp_cntl.cntl_write_data = 1;
14181 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14182 }
14183
14184 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14185
14186 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14187 ASSERT(fpkt->pkt_data_cookie_cnt <=
14188 pptr->port_data_dma_attr.dma_attr_sgllen);
14189
14190 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14191
14192 /* FCA needs pkt_datalen to be set */
14193 fpkt->pkt_datalen = cmd->cmd_dmacount;
14194 fcmd->fcp_data_len = cmd->cmd_dmacount;
14195 } else {
14196 fcmd->fcp_cntl.cntl_read_data = 0;
14197 fcmd->fcp_cntl.cntl_write_data = 0;
14198 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14199 fpkt->pkt_datalen = 0;
14200 fcmd->fcp_data_len = 0;
14201 }
14202
14203 /* set up the Tagged Queuing type */
14204 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14205 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14206 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14207 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14208 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14209 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14210 } else {
14211 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14212 }
14213
14214 fcmd->fcp_ent_addr = plun->lun_addr;
14215
14216 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14217 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14218 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14219 } else {
14220 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14221 }
14222
14223 cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14224 cmd->cmd_pkt->pkt_state = 0;
14225 cmd->cmd_pkt->pkt_statistics = 0;
14226 cmd->cmd_pkt->pkt_resid = 0;
14227
14228 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14229
14230 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14231 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14232 fpkt->pkt_comp = NULL;
14233 } else {
14234 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14235 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14236 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14237 }
14238 fpkt->pkt_comp = fcp_cmd_callback;
14239 }
14240
14241 mutex_enter(&pptr->port_mutex);
14242 if (pptr->port_state & FCP_STATE_SUSPENDED) {
14243 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14244 }
14245 mutex_exit(&pptr->port_mutex);
14246
14247 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14248 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14249
14250 /*
14251 * Save a few kernel cycles here
14252 */
14253 #ifndef __lock_lint
14254 fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14255 #endif /* __lock_lint */
14256 }
14257
14258 static void
fcp_post_callback(struct fcp_pkt * cmd)14259 fcp_post_callback(struct fcp_pkt *cmd)
14260 {
14261 scsi_hba_pkt_comp(cmd->cmd_pkt);
14262 }
14263
14264
14265 /*
14266 * called to do polled I/O by fcp_start()
14267 *
14268 * return a transport status value, i.e. TRAN_ACCECPT for success
14269 */
14270 static int
fcp_dopoll(struct fcp_port * pptr,struct fcp_pkt * cmd)14271 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14272 {
14273 int rval;
14274
14275 #ifdef DEBUG
14276 mutex_enter(&pptr->port_pkt_mutex);
14277 pptr->port_npkts++;
14278 mutex_exit(&pptr->port_pkt_mutex);
14279 #endif /* DEBUG */
14280
14281 if (cmd->cmd_fp_pkt->pkt_timeout) {
14282 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14283 } else {
14284 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14285 }
14286
14287 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14288
14289 cmd->cmd_state = FCP_PKT_ISSUED;
14290
14291 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14292
14293 #ifdef DEBUG
14294 mutex_enter(&pptr->port_pkt_mutex);
14295 pptr->port_npkts--;
14296 mutex_exit(&pptr->port_pkt_mutex);
14297 #endif /* DEBUG */
14298
14299 cmd->cmd_state = FCP_PKT_IDLE;
14300
14301 switch (rval) {
14302 case FC_SUCCESS:
14303 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14304 fcp_complete_pkt(cmd->cmd_fp_pkt);
14305 rval = TRAN_ACCEPT;
14306 } else {
14307 rval = TRAN_FATAL_ERROR;
14308 }
14309 break;
14310
14311 case FC_TRAN_BUSY:
14312 rval = TRAN_BUSY;
14313 cmd->cmd_pkt->pkt_resid = 0;
14314 break;
14315
14316 case FC_BADPACKET:
14317 rval = TRAN_BADPKT;
14318 break;
14319
14320 default:
14321 rval = TRAN_FATAL_ERROR;
14322 break;
14323 }
14324
14325 return (rval);
14326 }
14327
14328
14329 /*
14330 * called by some of the following transport-called routines to convert
14331 * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14332 */
14333 static struct fcp_port *
fcp_dip2port(dev_info_t * dip)14334 fcp_dip2port(dev_info_t *dip)
14335 {
14336 int instance;
14337
14338 instance = ddi_get_instance(dip);
14339 return (ddi_get_soft_state(fcp_softstate, instance));
14340 }
14341
14342
14343 /*
14344 * called internally to return a LUN given a dip
14345 */
14346 struct fcp_lun *
fcp_get_lun_from_cip(struct fcp_port * pptr,child_info_t * cip)14347 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14348 {
14349 struct fcp_tgt *ptgt;
14350 struct fcp_lun *plun;
14351 int i;
14352
14353
14354 ASSERT(mutex_owned(&pptr->port_mutex));
14355
14356 for (i = 0; i < FCP_NUM_HASH; i++) {
14357 for (ptgt = pptr->port_tgt_hash_table[i];
14358 ptgt != NULL;
14359 ptgt = ptgt->tgt_next) {
14360 mutex_enter(&ptgt->tgt_mutex);
14361 for (plun = ptgt->tgt_lun; plun != NULL;
14362 plun = plun->lun_next) {
14363 mutex_enter(&plun->lun_mutex);
14364 if (plun->lun_cip == cip) {
14365 mutex_exit(&plun->lun_mutex);
14366 mutex_exit(&ptgt->tgt_mutex);
14367 return (plun); /* match found */
14368 }
14369 mutex_exit(&plun->lun_mutex);
14370 }
14371 mutex_exit(&ptgt->tgt_mutex);
14372 }
14373 }
14374 return (NULL); /* no LUN found */
14375 }
14376
14377 /*
14378 * pass an element to the hotplug list, kick the hotplug thread
14379 * and wait for the element to get processed by the hotplug thread.
14380 * on return the element is freed.
14381 *
14382 * return zero success and non-zero on failure
14383 *
14384 * acquires/releases the target mutex
14385 *
14386 */
14387 static int
fcp_pass_to_hp_and_wait(struct fcp_port * pptr,struct fcp_lun * plun,child_info_t * cip,int what,int link_cnt,int tgt_cnt,int flags)14388 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14389 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14390 {
14391 struct fcp_hp_elem *elem;
14392 int rval;
14393
14394 mutex_enter(&plun->lun_tgt->tgt_mutex);
14395 if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14396 what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14397 mutex_exit(&plun->lun_tgt->tgt_mutex);
14398 fcp_log(CE_CONT, pptr->port_dip,
14399 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14400 what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14401 return (NDI_FAILURE);
14402 }
14403 mutex_exit(&plun->lun_tgt->tgt_mutex);
14404 mutex_enter(&elem->mutex);
14405 if (elem->wait) {
14406 while (elem->wait) {
14407 cv_wait(&elem->cv, &elem->mutex);
14408 }
14409 }
14410 rval = (elem->result);
14411 mutex_exit(&elem->mutex);
14412 mutex_destroy(&elem->mutex);
14413 cv_destroy(&elem->cv);
14414 kmem_free(elem, sizeof (struct fcp_hp_elem));
14415 return (rval);
14416 }
14417
14418 /*
14419 * pass an element to the hotplug list, and then
14420 * kick the hotplug thread
14421 *
14422 * return Boolean success, i.e. non-zero if all goes well, else zero on error
14423 *
14424 * acquires/releases the hotplug mutex
14425 *
14426 * called with the target mutex owned
14427 *
14428 * memory acquired in NOSLEEP mode
14429 * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14430 * for the hp daemon to process the request and is responsible for
14431 * freeing the element
14432 */
14433 static struct fcp_hp_elem *
fcp_pass_to_hp(struct fcp_port * pptr,struct fcp_lun * plun,child_info_t * cip,int what,int link_cnt,int tgt_cnt,int flags,int wait)14434 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14435 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14436 {
14437 struct fcp_hp_elem *elem;
14438 dev_info_t *pdip;
14439
14440 ASSERT(pptr != NULL);
14441 ASSERT(plun != NULL);
14442 ASSERT(plun->lun_tgt != NULL);
14443 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14444
14445 /* create space for a hotplug element */
14446 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14447 == NULL) {
14448 fcp_log(CE_WARN, NULL,
14449 "!can't allocate memory for hotplug element");
14450 return (NULL);
14451 }
14452
14453 /* fill in hotplug element */
14454 elem->port = pptr;
14455 elem->lun = plun;
14456 elem->cip = cip;
14457 elem->old_lun_mpxio = plun->lun_mpxio;
14458 elem->what = what;
14459 elem->flags = flags;
14460 elem->link_cnt = link_cnt;
14461 elem->tgt_cnt = tgt_cnt;
14462 elem->wait = wait;
14463 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14464 cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14465
14466 /* schedule the hotplug task */
14467 pdip = pptr->port_dip;
14468 mutex_enter(&plun->lun_mutex);
14469 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14470 plun->lun_event_count++;
14471 elem->event_cnt = plun->lun_event_count;
14472 }
14473 mutex_exit(&plun->lun_mutex);
14474 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14475 (void *)elem, KM_NOSLEEP) == NULL) {
14476 mutex_enter(&plun->lun_mutex);
14477 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14478 plun->lun_event_count--;
14479 }
14480 mutex_exit(&plun->lun_mutex);
14481 kmem_free(elem, sizeof (*elem));
14482 return (0);
14483 }
14484
14485 return (elem);
14486 }
14487
14488
14489 static void
fcp_retransport_cmd(struct fcp_port * pptr,struct fcp_pkt * cmd)14490 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14491 {
14492 int rval;
14493 struct scsi_address *ap;
14494 struct fcp_lun *plun;
14495 struct fcp_tgt *ptgt;
14496 fc_packet_t *fpkt;
14497
14498 ap = &cmd->cmd_pkt->pkt_address;
14499 plun = ADDR2LUN(ap);
14500 ptgt = plun->lun_tgt;
14501
14502 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14503
14504 cmd->cmd_state = FCP_PKT_IDLE;
14505
14506 mutex_enter(&pptr->port_mutex);
14507 mutex_enter(&ptgt->tgt_mutex);
14508 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14509 (!(pptr->port_state & FCP_STATE_ONLINING))) {
14510 fc_ulp_rscn_info_t *rscnp;
14511
14512 cmd->cmd_state = FCP_PKT_ISSUED;
14513
14514 /*
14515 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14516 * originally NULL, hence we try to set it to the pd pointed
14517 * to by the SCSI device we're trying to get to.
14518 */
14519
14520 fpkt = cmd->cmd_fp_pkt;
14521 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14522 fpkt->pkt_pd = ptgt->tgt_pd_handle;
14523 /*
14524 * We need to notify the transport that we now have a
14525 * reference to the remote port handle.
14526 */
14527 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14528 }
14529
14530 mutex_exit(&ptgt->tgt_mutex);
14531 mutex_exit(&pptr->port_mutex);
14532
14533 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14534
14535 /* prepare the packet */
14536
14537 fcp_prepare_pkt(pptr, cmd, plun);
14538
14539 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14540 pkt_ulp_rscn_infop;
14541
14542 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14543 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14544
14545 if (rscnp != NULL) {
14546 rscnp->ulp_rscn_count =
14547 fc_ulp_get_rscn_count(pptr->
14548 port_fp_handle);
14549 }
14550
14551 rval = fcp_transport(pptr->port_fp_handle,
14552 cmd->cmd_fp_pkt, 0);
14553
14554 if (rval == FC_SUCCESS) {
14555 return;
14556 }
14557 cmd->cmd_state &= ~FCP_PKT_ISSUED;
14558 } else {
14559 mutex_exit(&ptgt->tgt_mutex);
14560 mutex_exit(&pptr->port_mutex);
14561 }
14562
14563 fcp_queue_pkt(pptr, cmd);
14564 }
14565
14566
14567 static void
fcp_fail_cmd(struct fcp_pkt * cmd,uchar_t reason,uint_t statistics)14568 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14569 {
14570 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14571
14572 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14573 cmd->cmd_state = FCP_PKT_IDLE;
14574
14575 cmd->cmd_pkt->pkt_reason = reason;
14576 cmd->cmd_pkt->pkt_state = 0;
14577 cmd->cmd_pkt->pkt_statistics = statistics;
14578
14579 fcp_post_callback(cmd);
14580 }
14581
14582 /*
14583 * Function: fcp_queue_pkt
14584 *
14585 * Description: This function queues the packet passed by the caller into
14586 * the list of packets of the FCP port.
14587 *
14588 * Argument: *pptr FCP port.
14589 * *cmd FCP packet to queue.
14590 *
14591 * Return Value: None
14592 *
14593 * Context: User, Kernel and Interrupt context.
14594 */
14595 static void
fcp_queue_pkt(struct fcp_port * pptr,struct fcp_pkt * cmd)14596 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14597 {
14598 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14599
14600 mutex_enter(&pptr->port_pkt_mutex);
14601 cmd->cmd_flags |= CFLAG_IN_QUEUE;
14602 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14603 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14604
14605 /*
14606 * zero pkt_time means hang around for ever
14607 */
14608 if (cmd->cmd_pkt->pkt_time) {
14609 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14610 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14611 } else {
14612 /*
14613 * Indicate the watch thread to fail the
14614 * command by setting it to highest value
14615 */
14616 cmd->cmd_timeout = fcp_watchdog_time;
14617 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14618 }
14619 }
14620
14621 if (pptr->port_pkt_head) {
14622 ASSERT(pptr->port_pkt_tail != NULL);
14623
14624 pptr->port_pkt_tail->cmd_next = cmd;
14625 pptr->port_pkt_tail = cmd;
14626 } else {
14627 ASSERT(pptr->port_pkt_tail == NULL);
14628
14629 pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14630 }
14631 cmd->cmd_next = NULL;
14632 mutex_exit(&pptr->port_pkt_mutex);
14633 }
14634
14635 /*
14636 * Function: fcp_update_targets
14637 *
14638 * Description: This function applies the specified change of state to all
14639 * the targets listed. The operation applied is 'set'.
14640 *
14641 * Argument: *pptr FCP port.
14642 * *dev_list Array of fc_portmap_t structures.
14643 * count Length of dev_list.
14644 * state State bits to update.
14645 * cause Reason for the update.
14646 *
14647 * Return Value: None
14648 *
14649 * Context: User, Kernel and Interrupt context.
14650 * The mutex pptr->port_mutex must be held.
14651 */
14652 static void
fcp_update_targets(struct fcp_port * pptr,fc_portmap_t * dev_list,uint32_t count,uint32_t state,int cause)14653 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14654 uint32_t count, uint32_t state, int cause)
14655 {
14656 fc_portmap_t *map_entry;
14657 struct fcp_tgt *ptgt;
14658
14659 ASSERT(MUTEX_HELD(&pptr->port_mutex));
14660
14661 while (count--) {
14662 map_entry = &(dev_list[count]);
14663 ptgt = fcp_lookup_target(pptr,
14664 (uchar_t *)&(map_entry->map_pwwn));
14665 if (ptgt == NULL) {
14666 continue;
14667 }
14668
14669 mutex_enter(&ptgt->tgt_mutex);
14670 ptgt->tgt_trace = 0;
14671 ptgt->tgt_change_cnt++;
14672 ptgt->tgt_statec_cause = cause;
14673 ptgt->tgt_tmp_cnt = 1;
14674 fcp_update_tgt_state(ptgt, FCP_SET, state);
14675 mutex_exit(&ptgt->tgt_mutex);
14676 }
14677 }
14678
14679 static int
fcp_call_finish_init(struct fcp_port * pptr,struct fcp_tgt * ptgt,int lcount,int tcount,int cause)14680 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14681 int lcount, int tcount, int cause)
14682 {
14683 int rval;
14684
14685 mutex_enter(&pptr->port_mutex);
14686 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14687 mutex_exit(&pptr->port_mutex);
14688
14689 return (rval);
14690 }
14691
14692
14693 static int
fcp_call_finish_init_held(struct fcp_port * pptr,struct fcp_tgt * ptgt,int lcount,int tcount,int cause)14694 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14695 int lcount, int tcount, int cause)
14696 {
14697 int finish_init = 0;
14698 int finish_tgt = 0;
14699 int do_finish_init = 0;
14700 int rval = FCP_NO_CHANGE;
14701
14702 if (cause == FCP_CAUSE_LINK_CHANGE ||
14703 cause == FCP_CAUSE_LINK_DOWN) {
14704 do_finish_init = 1;
14705 }
14706
14707 if (ptgt != NULL) {
14708 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14709 FCP_BUF_LEVEL_2, 0,
14710 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14711 " cause = %d, d_id = 0x%x, tgt_done = %d",
14712 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14713 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14714 ptgt->tgt_d_id, ptgt->tgt_done);
14715
14716 mutex_enter(&ptgt->tgt_mutex);
14717
14718 if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14719 rval = FCP_DEV_CHANGE;
14720 if (do_finish_init && ptgt->tgt_done == 0) {
14721 ptgt->tgt_done++;
14722 finish_init = 1;
14723 }
14724 } else {
14725 if (--ptgt->tgt_tmp_cnt <= 0) {
14726 ptgt->tgt_tmp_cnt = 0;
14727 finish_tgt = 1;
14728
14729 if (do_finish_init) {
14730 finish_init = 1;
14731 }
14732 }
14733 }
14734 mutex_exit(&ptgt->tgt_mutex);
14735 } else {
14736 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14737 FCP_BUF_LEVEL_2, 0,
14738 "Call Finish Init for NO target");
14739
14740 if (do_finish_init) {
14741 finish_init = 1;
14742 }
14743 }
14744
14745 if (finish_tgt) {
14746 ASSERT(ptgt != NULL);
14747
14748 mutex_enter(&ptgt->tgt_mutex);
14749 #ifdef DEBUG
14750 bzero(ptgt->tgt_tmp_cnt_stack,
14751 sizeof (ptgt->tgt_tmp_cnt_stack));
14752
14753 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14754 FCP_STACK_DEPTH);
14755 #endif /* DEBUG */
14756 mutex_exit(&ptgt->tgt_mutex);
14757
14758 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14759 }
14760
14761 if (finish_init && lcount == pptr->port_link_cnt) {
14762 ASSERT(pptr->port_tmp_cnt > 0);
14763 if (--pptr->port_tmp_cnt == 0) {
14764 fcp_finish_init(pptr);
14765 }
14766 } else if (lcount != pptr->port_link_cnt) {
14767 FCP_TRACE(fcp_logq, pptr->port_instbuf,
14768 fcp_trace, FCP_BUF_LEVEL_2, 0,
14769 "fcp_call_finish_init_held,1: state change occured"
14770 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14771 }
14772
14773 return (rval);
14774 }
14775
14776 static void
fcp_reconfigure_luns(void * tgt_handle)14777 fcp_reconfigure_luns(void * tgt_handle)
14778 {
14779 uint32_t dev_cnt;
14780 fc_portmap_t *devlist;
14781 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle;
14782 struct fcp_port *pptr = ptgt->tgt_port;
14783
14784 /*
14785 * If the timer that fires this off got canceled too late, the
14786 * target could have been destroyed.
14787 */
14788
14789 if (ptgt->tgt_tid == NULL) {
14790 return;
14791 }
14792
14793 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14794 if (devlist == NULL) {
14795 fcp_log(CE_WARN, pptr->port_dip,
14796 "!fcp%d: failed to allocate for portmap",
14797 pptr->port_instance);
14798 return;
14799 }
14800
14801 dev_cnt = 1;
14802 devlist->map_pd = ptgt->tgt_pd_handle;
14803 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14804 devlist->map_did.port_id = ptgt->tgt_d_id;
14805
14806 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14807 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14808
14809 devlist->map_state = PORT_DEVICE_LOGGED_IN;
14810 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14811 devlist->map_flags = 0;
14812
14813 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14814 pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14815
14816 /*
14817 * Clear the tgt_tid after no more references to
14818 * the fcp_tgt
14819 */
14820 mutex_enter(&ptgt->tgt_mutex);
14821 ptgt->tgt_tid = NULL;
14822 mutex_exit(&ptgt->tgt_mutex);
14823
14824 kmem_free(devlist, sizeof (*devlist));
14825 }
14826
14827
14828 static void
fcp_free_targets(struct fcp_port * pptr)14829 fcp_free_targets(struct fcp_port *pptr)
14830 {
14831 int i;
14832 struct fcp_tgt *ptgt;
14833
14834 mutex_enter(&pptr->port_mutex);
14835 for (i = 0; i < FCP_NUM_HASH; i++) {
14836 ptgt = pptr->port_tgt_hash_table[i];
14837 while (ptgt != NULL) {
14838 struct fcp_tgt *next_tgt = ptgt->tgt_next;
14839
14840 fcp_free_target(ptgt);
14841 ptgt = next_tgt;
14842 }
14843 }
14844 mutex_exit(&pptr->port_mutex);
14845 }
14846
14847
14848 static void
fcp_free_target(struct fcp_tgt * ptgt)14849 fcp_free_target(struct fcp_tgt *ptgt)
14850 {
14851 struct fcp_lun *plun;
14852 timeout_id_t tid;
14853
14854 mutex_enter(&ptgt->tgt_mutex);
14855 tid = ptgt->tgt_tid;
14856
14857 /*
14858 * Cancel any pending timeouts for this target.
14859 */
14860
14861 if (tid != NULL) {
14862 /*
14863 * Set tgt_tid to NULL first to avoid a race in the callback.
14864 * If tgt_tid is NULL, the callback will simply return.
14865 */
14866 ptgt->tgt_tid = NULL;
14867 mutex_exit(&ptgt->tgt_mutex);
14868 (void) untimeout(tid);
14869 mutex_enter(&ptgt->tgt_mutex);
14870 }
14871
14872 plun = ptgt->tgt_lun;
14873 while (plun != NULL) {
14874 struct fcp_lun *next_lun = plun->lun_next;
14875
14876 fcp_dealloc_lun(plun);
14877 plun = next_lun;
14878 }
14879
14880 mutex_exit(&ptgt->tgt_mutex);
14881 fcp_dealloc_tgt(ptgt);
14882 }
14883
14884 /*
14885 * Function: fcp_is_retryable
14886 *
14887 * Description: Indicates if the internal packet is retryable.
14888 *
14889 * Argument: *icmd FCP internal packet.
14890 *
14891 * Return Value: 0 Not retryable
14892 * 1 Retryable
14893 *
14894 * Context: User, Kernel and Interrupt context
14895 */
14896 static int
fcp_is_retryable(struct fcp_ipkt * icmd)14897 fcp_is_retryable(struct fcp_ipkt *icmd)
14898 {
14899 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14900 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14901 return (0);
14902 }
14903
14904 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14905 icmd->ipkt_port->port_deadline) ? 1 : 0);
14906 }
14907
14908 /*
14909 * Function: fcp_create_on_demand
14910 *
14911 * Argument: *pptr FCP port.
14912 * *pwwn Port WWN.
14913 *
14914 * Return Value: 0 Success
14915 * EIO
14916 * ENOMEM
14917 * EBUSY
14918 * EINVAL
14919 *
14920 * Context: User and Kernel context
14921 */
14922 static int
fcp_create_on_demand(struct fcp_port * pptr,uchar_t * pwwn)14923 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14924 {
14925 int wait_ms;
14926 int tcount;
14927 int lcount;
14928 int ret;
14929 int error;
14930 int rval = EIO;
14931 int ntries;
14932 fc_portmap_t *devlist;
14933 opaque_t pd;
14934 struct fcp_lun *plun;
14935 struct fcp_tgt *ptgt;
14936 int old_manual = 0;
14937
14938 /* Allocates the fc_portmap_t structure. */
14939 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14940
14941 /*
14942 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14943 * in the commented statement below:
14944 *
14945 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14946 *
14947 * Below, the deadline for the discovery process is set.
14948 */
14949 mutex_enter(&pptr->port_mutex);
14950 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14951 mutex_exit(&pptr->port_mutex);
14952
14953 /*
14954 * We try to find the remote port based on the WWN provided by the
14955 * caller. We actually ask fp/fctl if it has it.
14956 */
14957 pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14958 (la_wwn_t *)pwwn, &error, 1);
14959
14960 if (pd == NULL) {
14961 kmem_free(devlist, sizeof (*devlist));
14962 return (rval);
14963 }
14964
14965 /*
14966 * The remote port was found. We ask fp/fctl to update our
14967 * fc_portmap_t structure.
14968 */
14969 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14970 (la_wwn_t *)pwwn, devlist);
14971 if (ret != FC_SUCCESS) {
14972 kmem_free(devlist, sizeof (*devlist));
14973 return (rval);
14974 }
14975
14976 /*
14977 * The map flag field is set to indicates that the creation is being
14978 * done at the user request (Ioclt probably luxadm or cfgadm).
14979 */
14980 devlist->map_type = PORT_DEVICE_USER_CREATE;
14981
14982 mutex_enter(&pptr->port_mutex);
14983
14984 /*
14985 * We check to see if fcp already has a target that describes the
14986 * device being created. If not it is created.
14987 */
14988 ptgt = fcp_lookup_target(pptr, pwwn);
14989 if (ptgt == NULL) {
14990 lcount = pptr->port_link_cnt;
14991 mutex_exit(&pptr->port_mutex);
14992
14993 ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14994 if (ptgt == NULL) {
14995 fcp_log(CE_WARN, pptr->port_dip,
14996 "!FC target allocation failed");
14997 return (ENOMEM);
14998 }
14999
15000 mutex_enter(&pptr->port_mutex);
15001 }
15002
15003 mutex_enter(&ptgt->tgt_mutex);
15004 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
15005 ptgt->tgt_tmp_cnt = 1;
15006 ptgt->tgt_device_created = 0;
15007 /*
15008 * If fabric and auto config is set but the target was
15009 * manually unconfigured then reset to the manual_config_only to
15010 * 0 so the device will get configured.
15011 */
15012 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15013 fcp_enable_auto_configuration &&
15014 ptgt->tgt_manual_config_only == 1) {
15015 old_manual = 1;
15016 ptgt->tgt_manual_config_only = 0;
15017 }
15018 mutex_exit(&ptgt->tgt_mutex);
15019
15020 fcp_update_targets(pptr, devlist, 1,
15021 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15022
15023 lcount = pptr->port_link_cnt;
15024 tcount = ptgt->tgt_change_cnt;
15025
15026 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15027 tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15028 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15029 fcp_enable_auto_configuration && old_manual) {
15030 mutex_enter(&ptgt->tgt_mutex);
15031 ptgt->tgt_manual_config_only = 1;
15032 mutex_exit(&ptgt->tgt_mutex);
15033 }
15034
15035 if (pptr->port_link_cnt != lcount ||
15036 ptgt->tgt_change_cnt != tcount) {
15037 rval = EBUSY;
15038 }
15039 mutex_exit(&pptr->port_mutex);
15040
15041 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15042 FCP_BUF_LEVEL_3, 0,
15043 "fcp_create_on_demand: mapflags ptgt=%x, "
15044 "lcount=%x::port_link_cnt=%x, "
15045 "tcount=%x: tgt_change_cnt=%x, rval=%x",
15046 ptgt, lcount, pptr->port_link_cnt,
15047 tcount, ptgt->tgt_change_cnt, rval);
15048 return (rval);
15049 }
15050
15051 /*
15052 * Due to lack of synchronization mechanisms, we perform
15053 * periodic monitoring of our request; Because requests
15054 * get dropped when another one supercedes (either because
15055 * of a link change or a target change), it is difficult to
15056 * provide a clean synchronization mechanism (such as a
15057 * semaphore or a conditional variable) without exhaustively
15058 * rewriting the mainline discovery code of this driver.
15059 */
15060 wait_ms = 500;
15061
15062 ntries = fcp_max_target_retries;
15063
15064 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15065 FCP_BUF_LEVEL_3, 0,
15066 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15067 "lcount=%x::port_link_cnt=%x, "
15068 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15069 "tgt_tmp_cnt =%x",
15070 ntries, ptgt, lcount, pptr->port_link_cnt,
15071 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15072 ptgt->tgt_tmp_cnt);
15073
15074 mutex_enter(&ptgt->tgt_mutex);
15075 while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15076 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15077 mutex_exit(&ptgt->tgt_mutex);
15078 mutex_exit(&pptr->port_mutex);
15079
15080 delay(drv_usectohz(wait_ms * 1000));
15081
15082 mutex_enter(&pptr->port_mutex);
15083 mutex_enter(&ptgt->tgt_mutex);
15084 }
15085
15086
15087 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15088 rval = EBUSY;
15089 } else {
15090 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15091 FCP_TGT_NODE_PRESENT) {
15092 rval = 0;
15093 }
15094 }
15095
15096 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15097 FCP_BUF_LEVEL_3, 0,
15098 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15099 "lcount=%x::port_link_cnt=%x, "
15100 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15101 "tgt_tmp_cnt =%x",
15102 ntries, ptgt, lcount, pptr->port_link_cnt,
15103 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15104 ptgt->tgt_tmp_cnt);
15105
15106 if (rval) {
15107 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15108 fcp_enable_auto_configuration && old_manual) {
15109 ptgt->tgt_manual_config_only = 1;
15110 }
15111 mutex_exit(&ptgt->tgt_mutex);
15112 mutex_exit(&pptr->port_mutex);
15113 kmem_free(devlist, sizeof (*devlist));
15114
15115 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15116 FCP_BUF_LEVEL_3, 0,
15117 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15118 "lcount=%x::port_link_cnt=%x, "
15119 "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15120 "tgt_device_created=%x, tgt D_ID=%x",
15121 ntries, ptgt, lcount, pptr->port_link_cnt,
15122 tcount, ptgt->tgt_change_cnt, rval,
15123 ptgt->tgt_device_created, ptgt->tgt_d_id);
15124 return (rval);
15125 }
15126
15127 if ((plun = ptgt->tgt_lun) != NULL) {
15128 tcount = plun->lun_tgt->tgt_change_cnt;
15129 } else {
15130 rval = EINVAL;
15131 }
15132 lcount = pptr->port_link_cnt;
15133
15134 /*
15135 * Configuring the target with no LUNs will fail. We
15136 * should reset the node state so that it is not
15137 * automatically configured when the LUNs are added
15138 * to this target.
15139 */
15140 if (ptgt->tgt_lun_cnt == 0) {
15141 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15142 }
15143 mutex_exit(&ptgt->tgt_mutex);
15144 mutex_exit(&pptr->port_mutex);
15145
15146 while (plun) {
15147 child_info_t *cip;
15148
15149 mutex_enter(&plun->lun_mutex);
15150 cip = plun->lun_cip;
15151 mutex_exit(&plun->lun_mutex);
15152
15153 mutex_enter(&ptgt->tgt_mutex);
15154 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15155 mutex_exit(&ptgt->tgt_mutex);
15156
15157 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15158 FCP_ONLINE, lcount, tcount,
15159 NDI_ONLINE_ATTACH);
15160 if (rval != NDI_SUCCESS) {
15161 FCP_TRACE(fcp_logq,
15162 pptr->port_instbuf, fcp_trace,
15163 FCP_BUF_LEVEL_3, 0,
15164 "fcp_create_on_demand: "
15165 "pass_to_hp_and_wait failed "
15166 "rval=%x", rval);
15167 rval = EIO;
15168 } else {
15169 mutex_enter(&LUN_TGT->tgt_mutex);
15170 plun->lun_state &= ~(FCP_LUN_OFFLINE |
15171 FCP_LUN_BUSY);
15172 mutex_exit(&LUN_TGT->tgt_mutex);
15173 }
15174 mutex_enter(&ptgt->tgt_mutex);
15175 }
15176
15177 plun = plun->lun_next;
15178 mutex_exit(&ptgt->tgt_mutex);
15179 }
15180
15181 kmem_free(devlist, sizeof (*devlist));
15182
15183 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15184 fcp_enable_auto_configuration && old_manual) {
15185 mutex_enter(&ptgt->tgt_mutex);
15186 /* if successful then set manual to 0 */
15187 if (rval == 0) {
15188 ptgt->tgt_manual_config_only = 0;
15189 } else {
15190 /* reset to 1 so the user has to do the config */
15191 ptgt->tgt_manual_config_only = 1;
15192 }
15193 mutex_exit(&ptgt->tgt_mutex);
15194 }
15195
15196 return (rval);
15197 }
15198
15199
15200 static void
fcp_ascii_to_wwn(caddr_t string,uchar_t bytes[],unsigned int byte_len)15201 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15202 {
15203 int count;
15204 uchar_t byte;
15205
15206 count = 0;
15207 while (*string) {
15208 byte = FCP_ATOB(*string); string++;
15209 byte = byte << 4 | FCP_ATOB(*string); string++;
15210 bytes[count++] = byte;
15211
15212 if (count >= byte_len) {
15213 break;
15214 }
15215 }
15216 }
15217
15218 static void
fcp_wwn_to_ascii(uchar_t wwn[],char * string)15219 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15220 {
15221 int i;
15222
15223 for (i = 0; i < FC_WWN_SIZE; i++) {
15224 (void) sprintf(string + (i * 2),
15225 "%02x", wwn[i]);
15226 }
15227
15228 }
15229
15230 static void
fcp_print_error(fc_packet_t * fpkt)15231 fcp_print_error(fc_packet_t *fpkt)
15232 {
15233 struct fcp_ipkt *icmd = (struct fcp_ipkt *)
15234 fpkt->pkt_ulp_private;
15235 struct fcp_port *pptr;
15236 struct fcp_tgt *ptgt;
15237 struct fcp_lun *plun;
15238 caddr_t buf;
15239 int scsi_cmd = 0;
15240
15241 ptgt = icmd->ipkt_tgt;
15242 plun = icmd->ipkt_lun;
15243 pptr = ptgt->tgt_port;
15244
15245 buf = kmem_zalloc(256, KM_NOSLEEP);
15246 if (buf == NULL) {
15247 return;
15248 }
15249
15250 switch (icmd->ipkt_opcode) {
15251 case SCMD_REPORT_LUN:
15252 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15253 " lun=0x%%x failed");
15254 scsi_cmd++;
15255 break;
15256
15257 case SCMD_INQUIRY_PAGE83:
15258 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15259 " lun=0x%%x failed");
15260 scsi_cmd++;
15261 break;
15262
15263 case SCMD_INQUIRY:
15264 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15265 " lun=0x%%x failed");
15266 scsi_cmd++;
15267 break;
15268
15269 case LA_ELS_PLOGI:
15270 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15271 break;
15272
15273 case LA_ELS_PRLI:
15274 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15275 break;
15276 }
15277
15278 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15279 struct fcp_rsp response, *rsp;
15280 uchar_t asc, ascq;
15281 caddr_t sense_key = NULL;
15282 struct fcp_rsp_info fcp_rsp_err, *bep;
15283
15284 if (icmd->ipkt_nodma) {
15285 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15286 bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15287 sizeof (struct fcp_rsp));
15288 } else {
15289 rsp = &response;
15290 bep = &fcp_rsp_err;
15291
15292 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15293 sizeof (struct fcp_rsp));
15294
15295 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15296 bep, fpkt->pkt_resp_acc,
15297 sizeof (struct fcp_rsp_info));
15298 }
15299
15300
15301 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15302 (void) sprintf(buf + strlen(buf),
15303 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15304 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15305 " senselen=%%x. Giving up");
15306
15307 fcp_log(CE_WARN, pptr->port_dip, buf,
15308 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15309 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15310 rsp->fcp_u.fcp_status.reserved_1,
15311 rsp->fcp_response_len, rsp->fcp_sense_len);
15312
15313 kmem_free(buf, 256);
15314 return;
15315 }
15316
15317 if (rsp->fcp_u.fcp_status.rsp_len_set &&
15318 bep->rsp_code != FCP_NO_FAILURE) {
15319 (void) sprintf(buf + strlen(buf),
15320 " FCP Response code = 0x%x", bep->rsp_code);
15321 }
15322
15323 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15324 struct scsi_extended_sense sense_info, *sense_ptr;
15325
15326 if (icmd->ipkt_nodma) {
15327 sense_ptr = (struct scsi_extended_sense *)
15328 ((caddr_t)fpkt->pkt_resp +
15329 sizeof (struct fcp_rsp) +
15330 rsp->fcp_response_len);
15331 } else {
15332 sense_ptr = &sense_info;
15333
15334 FCP_CP_IN(fpkt->pkt_resp +
15335 sizeof (struct fcp_rsp) +
15336 rsp->fcp_response_len, &sense_info,
15337 fpkt->pkt_resp_acc,
15338 sizeof (struct scsi_extended_sense));
15339 }
15340
15341 if (sense_ptr->es_key < NUM_SENSE_KEYS +
15342 NUM_IMPL_SENSE_KEYS) {
15343 sense_key = sense_keys[sense_ptr->es_key];
15344 } else {
15345 sense_key = "Undefined";
15346 }
15347
15348 asc = sense_ptr->es_add_code;
15349 ascq = sense_ptr->es_qual_code;
15350
15351 (void) sprintf(buf + strlen(buf),
15352 ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15353 " Giving up");
15354
15355 fcp_log(CE_WARN, pptr->port_dip, buf,
15356 ptgt->tgt_d_id, plun->lun_num, sense_key,
15357 asc, ascq);
15358 } else {
15359 (void) sprintf(buf + strlen(buf),
15360 " : SCSI status=%%x. Giving up");
15361
15362 fcp_log(CE_WARN, pptr->port_dip, buf,
15363 ptgt->tgt_d_id, plun->lun_num,
15364 rsp->fcp_u.fcp_status.scsi_status);
15365 }
15366 } else {
15367 caddr_t state, reason, action, expln;
15368
15369 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
15370 &action, &expln);
15371
15372 (void) sprintf(buf + strlen(buf), ": State:%%s,"
15373 " Reason:%%s. Giving up");
15374
15375 if (scsi_cmd) {
15376 fcp_log(CE_WARN, pptr->port_dip, buf,
15377 ptgt->tgt_d_id, plun->lun_num, state, reason);
15378 } else {
15379 fcp_log(CE_WARN, pptr->port_dip, buf,
15380 ptgt->tgt_d_id, state, reason);
15381 }
15382 }
15383
15384 kmem_free(buf, 256);
15385 }
15386
15387
15388 static int
fcp_handle_ipkt_errors(struct fcp_port * pptr,struct fcp_tgt * ptgt,struct fcp_ipkt * icmd,int rval,caddr_t op)15389 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15390 struct fcp_ipkt *icmd, int rval, caddr_t op)
15391 {
15392 int ret = DDI_FAILURE;
15393 char *error;
15394
15395 switch (rval) {
15396 case FC_DEVICE_BUSY_NEW_RSCN:
15397 /*
15398 * This means that there was a new RSCN that the transport
15399 * knows about (which the ULP *may* know about too) but the
15400 * pkt that was sent down was related to an older RSCN. So, we
15401 * are just going to reset the retry count and deadline and
15402 * continue to retry. The idea is that transport is currently
15403 * working on the new RSCN and will soon let the ULPs know
15404 * about it and when it does the existing logic will kick in
15405 * where it will change the tcount to indicate that something
15406 * changed on the target. So, rediscovery will start and there
15407 * will not be an infinite retry.
15408 *
15409 * For a full flow of how the RSCN info is transferred back and
15410 * forth, see fp.c
15411 */
15412 icmd->ipkt_retries = 0;
15413 icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15414 FCP_ICMD_DEADLINE;
15415
15416 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15417 FCP_BUF_LEVEL_3, 0,
15418 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x",
15419 rval, ptgt->tgt_d_id);
15420 /* FALLTHROUGH */
15421
15422 case FC_STATEC_BUSY:
15423 case FC_DEVICE_BUSY:
15424 case FC_PBUSY:
15425 case FC_FBUSY:
15426 case FC_TRAN_BUSY:
15427 case FC_OFFLINE:
15428 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15429 FCP_BUF_LEVEL_3, 0,
15430 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x",
15431 rval, ptgt->tgt_d_id);
15432 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15433 fcp_is_retryable(icmd)) {
15434 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15435 ret = DDI_SUCCESS;
15436 }
15437 break;
15438
15439 case FC_LOGINREQ:
15440 /*
15441 * FC_LOGINREQ used to be handled just like all the cases
15442 * above. It has been changed to handled a PRLI that fails
15443 * with FC_LOGINREQ different than other ipkts that fail
15444 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15445 * a simple matter to turn it into a PLOGI instead, so that's
15446 * exactly what we do here.
15447 */
15448 if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15449 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15450 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15451 icmd->ipkt_change_cnt, icmd->ipkt_cause);
15452 } else {
15453 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15454 FCP_BUF_LEVEL_3, 0,
15455 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x",
15456 rval, ptgt->tgt_d_id);
15457 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15458 fcp_is_retryable(icmd)) {
15459 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15460 ret = DDI_SUCCESS;
15461 }
15462 }
15463 break;
15464
15465 default:
15466 mutex_enter(&pptr->port_mutex);
15467 mutex_enter(&ptgt->tgt_mutex);
15468 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15469 mutex_exit(&ptgt->tgt_mutex);
15470 mutex_exit(&pptr->port_mutex);
15471
15472 (void) fc_ulp_error(rval, &error);
15473 fcp_log(CE_WARN, pptr->port_dip,
15474 "!Failed to send %s to D_ID=%x error=%s",
15475 op, ptgt->tgt_d_id, error);
15476 } else {
15477 FCP_TRACE(fcp_logq, pptr->port_instbuf,
15478 fcp_trace, FCP_BUF_LEVEL_2, 0,
15479 "fcp_handle_ipkt_errors,1: state change occured"
15480 " for D_ID=0x%x", ptgt->tgt_d_id);
15481 mutex_exit(&ptgt->tgt_mutex);
15482 mutex_exit(&pptr->port_mutex);
15483 }
15484 break;
15485 }
15486
15487 return (ret);
15488 }
15489
15490
15491 /*
15492 * Check of outstanding commands on any LUN for this target
15493 */
15494 static int
fcp_outstanding_lun_cmds(struct fcp_tgt * ptgt)15495 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15496 {
15497 struct fcp_lun *plun;
15498 struct fcp_pkt *cmd;
15499
15500 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15501 mutex_enter(&plun->lun_mutex);
15502 for (cmd = plun->lun_pkt_head; cmd != NULL;
15503 cmd = cmd->cmd_forw) {
15504 if (cmd->cmd_state == FCP_PKT_ISSUED) {
15505 mutex_exit(&plun->lun_mutex);
15506 return (FC_SUCCESS);
15507 }
15508 }
15509 mutex_exit(&plun->lun_mutex);
15510 }
15511
15512 return (FC_FAILURE);
15513 }
15514
15515 static fc_portmap_t *
fcp_construct_map(struct fcp_port * pptr,uint32_t * dev_cnt)15516 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15517 {
15518 int i;
15519 fc_portmap_t *devlist;
15520 fc_portmap_t *devptr = NULL;
15521 struct fcp_tgt *ptgt;
15522
15523 mutex_enter(&pptr->port_mutex);
15524 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15525 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15526 ptgt = ptgt->tgt_next) {
15527 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15528 ++*dev_cnt;
15529 }
15530 }
15531 }
15532
15533 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15534 KM_NOSLEEP);
15535 if (devlist == NULL) {
15536 mutex_exit(&pptr->port_mutex);
15537 fcp_log(CE_WARN, pptr->port_dip,
15538 "!fcp%d: failed to allocate for portmap for construct map",
15539 pptr->port_instance);
15540 return (devptr);
15541 }
15542
15543 for (i = 0; i < FCP_NUM_HASH; i++) {
15544 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15545 ptgt = ptgt->tgt_next) {
15546 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15547 int ret;
15548
15549 ret = fc_ulp_pwwn_to_portmap(
15550 pptr->port_fp_handle,
15551 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15552 devlist);
15553
15554 if (ret == FC_SUCCESS) {
15555 devlist++;
15556 continue;
15557 }
15558
15559 devlist->map_pd = NULL;
15560 devlist->map_did.port_id = ptgt->tgt_d_id;
15561 devlist->map_hard_addr.hard_addr =
15562 ptgt->tgt_hard_addr;
15563
15564 devlist->map_state = PORT_DEVICE_INVALID;
15565 devlist->map_type = PORT_DEVICE_OLD;
15566
15567 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15568 &devlist->map_nwwn, FC_WWN_SIZE);
15569
15570 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15571 &devlist->map_pwwn, FC_WWN_SIZE);
15572
15573 devlist++;
15574 }
15575 }
15576 }
15577
15578 mutex_exit(&pptr->port_mutex);
15579
15580 return (devptr);
15581 }
15582 /*
15583 * Inimate MPxIO that the lun is busy and cannot accept regular IO
15584 */
15585 static void
fcp_update_mpxio_path_verifybusy(struct fcp_port * pptr)15586 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15587 {
15588 int i;
15589 struct fcp_tgt *ptgt;
15590 struct fcp_lun *plun;
15591
15592 for (i = 0; i < FCP_NUM_HASH; i++) {
15593 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15594 ptgt = ptgt->tgt_next) {
15595 mutex_enter(&ptgt->tgt_mutex);
15596 for (plun = ptgt->tgt_lun; plun != NULL;
15597 plun = plun->lun_next) {
15598 if (plun->lun_mpxio &&
15599 plun->lun_state & FCP_LUN_BUSY) {
15600 if (!fcp_pass_to_hp(pptr, plun,
15601 plun->lun_cip,
15602 FCP_MPXIO_PATH_SET_BUSY,
15603 pptr->port_link_cnt,
15604 ptgt->tgt_change_cnt, 0, 0)) {
15605 FCP_TRACE(fcp_logq,
15606 pptr->port_instbuf,
15607 fcp_trace,
15608 FCP_BUF_LEVEL_2, 0,
15609 "path_verifybusy: "
15610 "disable lun %p failed!",
15611 plun);
15612 }
15613 }
15614 }
15615 mutex_exit(&ptgt->tgt_mutex);
15616 }
15617 }
15618 }
15619
15620 static int
fcp_update_mpxio_path(struct fcp_lun * plun,child_info_t * cip,int what)15621 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15622 {
15623 dev_info_t *cdip = NULL;
15624 dev_info_t *pdip = NULL;
15625
15626 ASSERT(plun);
15627
15628 mutex_enter(&plun->lun_mutex);
15629 if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15630 mutex_exit(&plun->lun_mutex);
15631 return (NDI_FAILURE);
15632 }
15633 mutex_exit(&plun->lun_mutex);
15634 cdip = mdi_pi_get_client(PIP(cip));
15635 pdip = mdi_pi_get_phci(PIP(cip));
15636
15637 ASSERT(cdip != NULL);
15638 ASSERT(pdip != NULL);
15639
15640 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15641 /* LUN ready for IO */
15642 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15643 } else {
15644 /* LUN busy to accept IO */
15645 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15646 }
15647 return (NDI_SUCCESS);
15648 }
15649
15650 /*
15651 * Caller must free the returned string of MAXPATHLEN len
15652 * If the device is offline (-1 instance number) NULL
15653 * will be returned.
15654 */
15655 static char *
fcp_get_lun_path(struct fcp_lun * plun)15656 fcp_get_lun_path(struct fcp_lun *plun) {
15657 dev_info_t *dip = NULL;
15658 char *path = NULL;
15659 mdi_pathinfo_t *pip = NULL;
15660
15661 if (plun == NULL) {
15662 return (NULL);
15663 }
15664
15665 mutex_enter(&plun->lun_mutex);
15666 if (plun->lun_mpxio == 0) {
15667 dip = DIP(plun->lun_cip);
15668 mutex_exit(&plun->lun_mutex);
15669 } else {
15670 /*
15671 * lun_cip must be accessed with lun_mutex held. Here
15672 * plun->lun_cip either points to a valid node or it is NULL.
15673 * Make a copy so that we can release lun_mutex.
15674 */
15675 pip = PIP(plun->lun_cip);
15676
15677 /*
15678 * Increase ref count on the path so that we can release
15679 * lun_mutex and still be sure that the pathinfo node (and thus
15680 * also the client) is not deallocated. If pip is NULL, this
15681 * has no effect.
15682 */
15683 mdi_hold_path(pip);
15684
15685 mutex_exit(&plun->lun_mutex);
15686
15687 /* Get the client. If pip is NULL, we get NULL. */
15688 dip = mdi_pi_get_client(pip);
15689 }
15690
15691 if (dip == NULL)
15692 goto out;
15693 if (ddi_get_instance(dip) < 0)
15694 goto out;
15695
15696 path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15697 if (path == NULL)
15698 goto out;
15699
15700 (void) ddi_pathname(dip, path);
15701
15702 /* Clean up. */
15703 out:
15704 if (pip != NULL)
15705 mdi_rele_path(pip);
15706
15707 /*
15708 * In reality, the user wants a fully valid path (one they can open)
15709 * but this string is lacking the mount point, and the minor node.
15710 * It would be nice if we could "figure these out" somehow
15711 * and fill them in. Otherwise, the userland code has to understand
15712 * driver specific details of which minor node is the "best" or
15713 * "right" one to expose. (Ex: which slice is the whole disk, or
15714 * which tape doesn't rewind)
15715 */
15716 return (path);
15717 }
15718
15719 static int
fcp_scsi_bus_config(dev_info_t * parent,uint_t flag,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)15720 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15721 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15722 {
15723 int64_t reset_delay;
15724 int rval, retry = 0;
15725 struct fcp_port *pptr = fcp_dip2port(parent);
15726
15727 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15728 (ddi_get_lbolt64() - pptr->port_attach_time);
15729 if (reset_delay < 0) {
15730 reset_delay = 0;
15731 }
15732
15733 if (fcp_bus_config_debug) {
15734 flag |= NDI_DEVI_DEBUG;
15735 }
15736
15737 switch (op) {
15738 case BUS_CONFIG_ONE:
15739 /*
15740 * Retry the command since we need to ensure
15741 * the fabric devices are available for root
15742 */
15743 while (retry++ < fcp_max_bus_config_retries) {
15744 rval = (ndi_busop_bus_config(parent,
15745 flag | NDI_MDI_FALLBACK, op,
15746 arg, childp, (clock_t)reset_delay));
15747 if (rval == 0) {
15748 return (rval);
15749 }
15750 }
15751
15752 /*
15753 * drain taskq to make sure nodes are created and then
15754 * try again.
15755 */
15756 taskq_wait(DEVI(parent)->devi_taskq);
15757 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15758 op, arg, childp, 0));
15759
15760 case BUS_CONFIG_DRIVER:
15761 case BUS_CONFIG_ALL: {
15762 /*
15763 * delay till all devices report in (port_tmp_cnt == 0)
15764 * or FCP_INIT_WAIT_TIMEOUT
15765 */
15766 mutex_enter(&pptr->port_mutex);
15767 while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15768 (void) cv_timedwait(&pptr->port_config_cv,
15769 &pptr->port_mutex,
15770 ddi_get_lbolt() + (clock_t)reset_delay);
15771 reset_delay =
15772 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15773 (ddi_get_lbolt64() - pptr->port_attach_time);
15774 }
15775 mutex_exit(&pptr->port_mutex);
15776 /* drain taskq to make sure nodes are created */
15777 taskq_wait(DEVI(parent)->devi_taskq);
15778 return (ndi_busop_bus_config(parent, flag, op,
15779 arg, childp, 0));
15780 }
15781
15782 default:
15783 return (NDI_FAILURE);
15784 }
15785 /*NOTREACHED*/
15786 }
15787
15788 static int
fcp_scsi_bus_unconfig(dev_info_t * parent,uint_t flag,ddi_bus_config_op_t op,void * arg)15789 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15790 ddi_bus_config_op_t op, void *arg)
15791 {
15792 if (fcp_bus_config_debug) {
15793 flag |= NDI_DEVI_DEBUG;
15794 }
15795
15796 return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15797 }
15798
15799
15800 /*
15801 * Routine to copy GUID into the lun structure.
15802 * returns 0 if copy was successful and 1 if encountered a
15803 * failure and did not copy the guid.
15804 */
15805 static int
fcp_copy_guid_2_lun_block(struct fcp_lun * plun,char * guidp)15806 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15807 {
15808
15809 int retval = 0;
15810
15811 /* add one for the null terminator */
15812 const unsigned int len = strlen(guidp) + 1;
15813
15814 if ((guidp == NULL) || (plun == NULL)) {
15815 return (1);
15816 }
15817
15818 /*
15819 * if the plun->lun_guid already has been allocated,
15820 * then check the size. if the size is exact, reuse
15821 * it....if not free it an allocate the required size.
15822 * The reallocation should NOT typically happen
15823 * unless the GUIDs reported changes between passes.
15824 * We free up and alloc again even if the
15825 * size was more than required. This is due to the
15826 * fact that the field lun_guid_size - serves
15827 * dual role of indicating the size of the wwn
15828 * size and ALSO the allocation size.
15829 */
15830 if (plun->lun_guid) {
15831 if (plun->lun_guid_size != len) {
15832 /*
15833 * free the allocated memory and
15834 * initialize the field
15835 * lun_guid_size to 0.
15836 */
15837 kmem_free(plun->lun_guid, plun->lun_guid_size);
15838 plun->lun_guid = NULL;
15839 plun->lun_guid_size = 0;
15840 }
15841 }
15842 /*
15843 * alloc only if not already done.
15844 */
15845 if (plun->lun_guid == NULL) {
15846 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15847 if (plun->lun_guid == NULL) {
15848 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15849 "Unable to allocate"
15850 "Memory for GUID!!! size %d", len);
15851 retval = 1;
15852 } else {
15853 plun->lun_guid_size = len;
15854 }
15855 }
15856 if (plun->lun_guid) {
15857 /*
15858 * now copy the GUID
15859 */
15860 bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15861 }
15862 return (retval);
15863 }
15864
15865 /*
15866 * fcp_reconfig_wait
15867 *
15868 * Wait for a rediscovery/reconfiguration to complete before continuing.
15869 */
15870
15871 static void
fcp_reconfig_wait(struct fcp_port * pptr)15872 fcp_reconfig_wait(struct fcp_port *pptr)
15873 {
15874 clock_t reconfig_start, wait_timeout;
15875
15876 /*
15877 * Quick check. If pptr->port_tmp_cnt is 0, there is no
15878 * reconfiguration in progress.
15879 */
15880
15881 mutex_enter(&pptr->port_mutex);
15882 if (pptr->port_tmp_cnt == 0) {
15883 mutex_exit(&pptr->port_mutex);
15884 return;
15885 }
15886 mutex_exit(&pptr->port_mutex);
15887
15888 /*
15889 * If we cause a reconfig by raising power, delay until all devices
15890 * report in (port_tmp_cnt returns to 0)
15891 */
15892
15893 reconfig_start = ddi_get_lbolt();
15894 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15895
15896 mutex_enter(&pptr->port_mutex);
15897
15898 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15899 pptr->port_tmp_cnt) {
15900
15901 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15902 reconfig_start + wait_timeout);
15903 }
15904
15905 mutex_exit(&pptr->port_mutex);
15906
15907 /*
15908 * Even if fcp_tmp_count isn't 0, continue without error. The port
15909 * we want may still be ok. If not, it will error out later
15910 */
15911 }
15912
15913 /*
15914 * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15915 * We rely on the fcp_global_mutex to provide protection against changes to
15916 * the fcp_lun_blacklist.
15917 *
15918 * You can describe a list of target port WWNs and LUN numbers which will
15919 * not be configured. LUN numbers will be interpreted as decimal. White
15920 * spaces and ',' can be used in the list of LUN numbers.
15921 *
15922 * To prevent LUNs 1 and 2 from being configured for target
15923 * port 510000f010fd92a1 and target port 510000e012079df1, set:
15924 *
15925 * pwwn-lun-blacklist=
15926 * "510000f010fd92a1,1,2",
15927 * "510000e012079df1,1,2";
15928 */
15929 static void
fcp_read_blacklist(dev_info_t * dip,struct fcp_black_list_entry ** pplun_blacklist)15930 fcp_read_blacklist(dev_info_t *dip,
15931 struct fcp_black_list_entry **pplun_blacklist) {
15932 char **prop_array = NULL;
15933 char *curr_pwwn = NULL;
15934 char *curr_lun = NULL;
15935 uint32_t prop_item = 0;
15936 int idx = 0;
15937 int len = 0;
15938
15939 ASSERT(mutex_owned(&fcp_global_mutex));
15940 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15941 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15942 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15943 return;
15944 }
15945
15946 for (idx = 0; idx < prop_item; idx++) {
15947
15948 curr_pwwn = prop_array[idx];
15949 while (*curr_pwwn == ' ') {
15950 curr_pwwn++;
15951 }
15952 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15953 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15954 ", please check.", curr_pwwn);
15955 continue;
15956 }
15957 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15958 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15959 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15960 ", please check.", curr_pwwn);
15961 continue;
15962 }
15963 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15964 if (isxdigit(curr_pwwn[len]) != TRUE) {
15965 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15966 "blacklist, please check.", curr_pwwn);
15967 break;
15968 }
15969 }
15970 if (len != sizeof (la_wwn_t) * 2) {
15971 continue;
15972 }
15973
15974 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15975 *(curr_lun - 1) = '\0';
15976 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15977 }
15978
15979 ddi_prop_free(prop_array);
15980 }
15981
15982 /*
15983 * Get the masking info about one remote target port designated by wwn.
15984 * Lun ids could be separated by ',' or white spaces.
15985 */
15986 static void
fcp_mask_pwwn_lun(char * curr_pwwn,char * curr_lun,struct fcp_black_list_entry ** pplun_blacklist)15987 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15988 struct fcp_black_list_entry **pplun_blacklist) {
15989 int idx = 0;
15990 uint32_t offset = 0;
15991 unsigned long lun_id = 0;
15992 char lunid_buf[16];
15993 char *pend = NULL;
15994 int illegal_digit = 0;
15995
15996 while (offset < strlen(curr_lun)) {
15997 while ((curr_lun[offset + idx] != ',') &&
15998 (curr_lun[offset + idx] != '\0') &&
15999 (curr_lun[offset + idx] != ' ')) {
16000 if (isdigit(curr_lun[offset + idx]) == 0) {
16001 illegal_digit++;
16002 }
16003 idx++;
16004 }
16005 if (illegal_digit > 0) {
16006 offset += (idx+1); /* To the start of next lun */
16007 idx = 0;
16008 illegal_digit = 0;
16009 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16010 "the blacklist, please check digits.",
16011 curr_lun, curr_pwwn);
16012 continue;
16013 }
16014 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16015 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16016 "the blacklist, please check the length of LUN#.",
16017 curr_lun, curr_pwwn);
16018 break;
16019 }
16020 if (idx == 0) { /* ignore ' ' or ',' or '\0' */
16021 offset++;
16022 continue;
16023 }
16024
16025 bcopy(curr_lun + offset, lunid_buf, idx);
16026 lunid_buf[idx] = '\0';
16027 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16028 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16029 } else {
16030 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16031 "the blacklist, please check %s.",
16032 curr_lun, curr_pwwn, lunid_buf);
16033 }
16034 offset += (idx+1); /* To the start of next lun */
16035 idx = 0;
16036 }
16037 }
16038
16039 /*
16040 * Add one masking record
16041 */
16042 static void
fcp_add_one_mask(char * curr_pwwn,uint32_t lun_id,struct fcp_black_list_entry ** pplun_blacklist)16043 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16044 struct fcp_black_list_entry **pplun_blacklist) {
16045 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist;
16046 struct fcp_black_list_entry *new_entry = NULL;
16047 la_wwn_t wwn;
16048
16049 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16050 while (tmp_entry) {
16051 if ((bcmp(&tmp_entry->wwn, &wwn,
16052 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16053 return;
16054 }
16055
16056 tmp_entry = tmp_entry->next;
16057 }
16058
16059 /* add to black list */
16060 new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16061 (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16062 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16063 new_entry->lun = lun_id;
16064 new_entry->masked = 0;
16065 new_entry->next = *pplun_blacklist;
16066 *pplun_blacklist = new_entry;
16067 }
16068
16069 /*
16070 * Check if we should mask the specified lun of this fcp_tgt
16071 */
16072 static int
fcp_should_mask(la_wwn_t * wwn,uint32_t lun_id)16073 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16074 struct fcp_black_list_entry *remote_port;
16075
16076 remote_port = fcp_lun_blacklist;
16077 while (remote_port != NULL) {
16078 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16079 if (remote_port->lun == lun_id) {
16080 remote_port->masked++;
16081 if (remote_port->masked == 1) {
16082 fcp_log(CE_NOTE, NULL, "LUN %d of port "
16083 "%02x%02x%02x%02x%02x%02x%02x%02x "
16084 "is masked due to black listing.\n",
16085 lun_id, wwn->raw_wwn[0],
16086 wwn->raw_wwn[1], wwn->raw_wwn[2],
16087 wwn->raw_wwn[3], wwn->raw_wwn[4],
16088 wwn->raw_wwn[5], wwn->raw_wwn[6],
16089 wwn->raw_wwn[7]);
16090 }
16091 return (TRUE);
16092 }
16093 }
16094 remote_port = remote_port->next;
16095 }
16096 return (FALSE);
16097 }
16098
16099 /*
16100 * Release all allocated resources
16101 */
16102 static void
fcp_cleanup_blacklist(struct fcp_black_list_entry ** pplun_blacklist)16103 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16104 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist;
16105 struct fcp_black_list_entry *current_entry = NULL;
16106
16107 ASSERT(mutex_owned(&fcp_global_mutex));
16108 /*
16109 * Traverse all luns
16110 */
16111 while (tmp_entry) {
16112 current_entry = tmp_entry;
16113 tmp_entry = tmp_entry->next;
16114 kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16115 }
16116 *pplun_blacklist = NULL;
16117 }
16118
16119 /*
16120 * In fcp module,
16121 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16122 */
16123 static struct scsi_pkt *
fcp_pseudo_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)16124 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16125 struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16126 int flags, int (*callback)(), caddr_t arg)
16127 {
16128 fcp_port_t *pptr = ADDR2FCP(ap);
16129 fcp_pkt_t *cmd = NULL;
16130 fc_frame_hdr_t *hp;
16131
16132 /*
16133 * First step: get the packet
16134 */
16135 if (pkt == NULL) {
16136 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16137 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16138 callback, arg);
16139 if (pkt == NULL) {
16140 return (NULL);
16141 }
16142
16143 /*
16144 * All fields in scsi_pkt will be initialized properly or
16145 * set to zero. We need do nothing for scsi_pkt.
16146 */
16147 /*
16148 * But it's our responsibility to link other related data
16149 * structures. Their initialization will be done, just
16150 * before the scsi_pkt will be sent to FCA.
16151 */
16152 cmd = PKT2CMD(pkt);
16153 cmd->cmd_pkt = pkt;
16154 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16155 /*
16156 * fc_packet_t
16157 */
16158 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16159 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16160 sizeof (struct fcp_pkt));
16161 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16162 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16163 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16164 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16165 /*
16166 * Fill in the Fabric Channel Header
16167 */
16168 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16169 hp->r_ctl = R_CTL_COMMAND;
16170 hp->rsvd = 0;
16171 hp->type = FC_TYPE_SCSI_FCP;
16172 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16173 hp->seq_id = 0;
16174 hp->df_ctl = 0;
16175 hp->seq_cnt = 0;
16176 hp->ox_id = 0xffff;
16177 hp->rx_id = 0xffff;
16178 hp->ro = 0;
16179 } else {
16180 /*
16181 * We need think if we should reset any elements in
16182 * related data structures.
16183 */
16184 FCP_TRACE(fcp_logq, pptr->port_instbuf,
16185 fcp_trace, FCP_BUF_LEVEL_6, 0,
16186 "reusing pkt, flags %d", flags);
16187 cmd = PKT2CMD(pkt);
16188 if (cmd->cmd_fp_pkt->pkt_pd) {
16189 cmd->cmd_fp_pkt->pkt_pd = NULL;
16190 }
16191 }
16192
16193 /*
16194 * Second step: dma allocation/move
16195 */
16196 if (bp && bp->b_bcount != 0) {
16197 /*
16198 * Mark if it's read or write
16199 */
16200 if (bp->b_flags & B_READ) {
16201 cmd->cmd_flags |= CFLAG_IS_READ;
16202 } else {
16203 cmd->cmd_flags &= ~CFLAG_IS_READ;
16204 }
16205
16206 bp_mapin(bp);
16207 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16208 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16209 cmd->cmd_fp_pkt->pkt_data_resid = 0;
16210 } else {
16211 /*
16212 * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16213 * to send zero-length read/write.
16214 */
16215 cmd->cmd_fp_pkt->pkt_data = NULL;
16216 cmd->cmd_fp_pkt->pkt_datalen = 0;
16217 }
16218
16219 return (pkt);
16220 }
16221
16222 static void
fcp_pseudo_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)16223 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16224 {
16225 fcp_port_t *pptr = ADDR2FCP(ap);
16226
16227 /*
16228 * First we let FCA to uninitilize private part.
16229 */
16230 (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16231 PKT2CMD(pkt)->cmd_fp_pkt);
16232
16233 /*
16234 * Then we uninitialize fc_packet.
16235 */
16236
16237 /*
16238 * Thirdly, we uninitializae fcp_pkt.
16239 */
16240
16241 /*
16242 * In the end, we free scsi_pkt.
16243 */
16244 scsi_hba_pkt_free(ap, pkt);
16245 }
16246
16247 static int
fcp_pseudo_start(struct scsi_address * ap,struct scsi_pkt * pkt)16248 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16249 {
16250 fcp_port_t *pptr = ADDR2FCP(ap);
16251 fcp_lun_t *plun = ADDR2LUN(ap);
16252 fcp_tgt_t *ptgt = plun->lun_tgt;
16253 fcp_pkt_t *cmd = PKT2CMD(pkt);
16254 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd;
16255 fc_packet_t *fpkt = cmd->cmd_fp_pkt;
16256 int rval;
16257
16258 fpkt->pkt_pd = ptgt->tgt_pd_handle;
16259 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16260
16261 /*
16262 * Firstly, we need initialize fcp_pkt_t
16263 * Secondly, we need initialize fcp_cmd_t.
16264 */
16265 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16266 fcmd->fcp_data_len = fpkt->pkt_datalen;
16267 fcmd->fcp_ent_addr = plun->lun_addr;
16268 if (pkt->pkt_flags & FLAG_HTAG) {
16269 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16270 } else if (pkt->pkt_flags & FLAG_OTAG) {
16271 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16272 } else if (pkt->pkt_flags & FLAG_STAG) {
16273 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16274 } else {
16275 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16276 }
16277
16278 if (cmd->cmd_flags & CFLAG_IS_READ) {
16279 fcmd->fcp_cntl.cntl_read_data = 1;
16280 fcmd->fcp_cntl.cntl_write_data = 0;
16281 } else {
16282 fcmd->fcp_cntl.cntl_read_data = 0;
16283 fcmd->fcp_cntl.cntl_write_data = 1;
16284 }
16285
16286 /*
16287 * Then we need initialize fc_packet_t too.
16288 */
16289 fpkt->pkt_timeout = pkt->pkt_time + 2;
16290 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16291 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16292 if (cmd->cmd_flags & CFLAG_IS_READ) {
16293 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16294 } else {
16295 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16296 }
16297
16298 if (pkt->pkt_flags & FLAG_NOINTR) {
16299 fpkt->pkt_comp = NULL;
16300 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16301 } else {
16302 fpkt->pkt_comp = fcp_cmd_callback;
16303 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16304 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16305 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16306 }
16307 }
16308
16309 /*
16310 * Lastly, we need initialize scsi_pkt
16311 */
16312 pkt->pkt_reason = CMD_CMPLT;
16313 pkt->pkt_state = 0;
16314 pkt->pkt_statistics = 0;
16315 pkt->pkt_resid = 0;
16316
16317 /*
16318 * if interrupts aren't allowed (e.g. at dump time) then we'll
16319 * have to do polled I/O
16320 */
16321 if (pkt->pkt_flags & FLAG_NOINTR) {
16322 return (fcp_dopoll(pptr, cmd));
16323 }
16324
16325 cmd->cmd_state = FCP_PKT_ISSUED;
16326 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16327 if (rval == FC_SUCCESS) {
16328 return (TRAN_ACCEPT);
16329 }
16330
16331 /*
16332 * Need more consideration
16333 *
16334 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16335 */
16336 cmd->cmd_state = FCP_PKT_IDLE;
16337 if (rval == FC_TRAN_BUSY) {
16338 return (TRAN_BUSY);
16339 } else {
16340 return (TRAN_FATAL_ERROR);
16341 }
16342 }
16343
16344 /*
16345 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16346 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16347 */
16348 static void
fcp_pseudo_sync_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)16349 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16350 {
16351 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16352 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16353 }
16354
16355 /*
16356 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16357 */
16358 static void
fcp_pseudo_dmafree(struct scsi_address * ap,struct scsi_pkt * pkt)16359 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16360 {
16361 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16362 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16363 }
16364