xref: /openbmc/linux/drivers/scsi/bfa/bfad_im.c (revision 4800cd83)
1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17 
18 /*
19  *  bfad_im.c Linux driver IM module.
20  */
21 
22 #include "bfad_drv.h"
23 #include "bfad_im.h"
24 #include "bfa_fcs.h"
25 
26 BFA_TRC_FILE(LDRV, IM);
27 
28 DEFINE_IDR(bfad_im_port_index);
29 struct scsi_transport_template *bfad_im_scsi_transport_template;
30 struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
31 static void bfad_im_itnim_work_handler(struct work_struct *work);
32 static int bfad_im_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmnd);
33 static int bfad_im_slave_alloc(struct scsi_device *sdev);
34 static void bfad_im_fc_rport_add(struct bfad_im_port_s  *im_port,
35 				struct bfad_itnim_s *itnim);
36 
37 void
38 bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
39 			enum bfi_ioim_status io_status, u8 scsi_status,
40 			int sns_len, u8 *sns_info, s32 residue)
41 {
42 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
43 	struct bfad_s         *bfad = drv;
44 	struct bfad_itnim_data_s *itnim_data;
45 	struct bfad_itnim_s *itnim;
46 	u8         host_status = DID_OK;
47 
48 	switch (io_status) {
49 	case BFI_IOIM_STS_OK:
50 		bfa_trc(bfad, scsi_status);
51 		scsi_set_resid(cmnd, 0);
52 
53 		if (sns_len > 0) {
54 			bfa_trc(bfad, sns_len);
55 			if (sns_len > SCSI_SENSE_BUFFERSIZE)
56 				sns_len = SCSI_SENSE_BUFFERSIZE;
57 			memcpy(cmnd->sense_buffer, sns_info, sns_len);
58 		}
59 
60 		if (residue > 0) {
61 			bfa_trc(bfad, residue);
62 			scsi_set_resid(cmnd, residue);
63 			if (!sns_len && (scsi_status == SAM_STAT_GOOD) &&
64 				(scsi_bufflen(cmnd) - residue) <
65 					cmnd->underflow) {
66 				bfa_trc(bfad, 0);
67 				host_status = DID_ERROR;
68 			}
69 		}
70 		cmnd->result = ScsiResult(host_status, scsi_status);
71 
72 		break;
73 
74 	case BFI_IOIM_STS_ABORTED:
75 	case BFI_IOIM_STS_TIMEDOUT:
76 	case BFI_IOIM_STS_PATHTOV:
77 	default:
78 		host_status = DID_ERROR;
79 		cmnd->result = ScsiResult(host_status, 0);
80 	}
81 
82 	/* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
83 	if (cmnd->device->host != NULL)
84 		scsi_dma_unmap(cmnd);
85 
86 	cmnd->host_scribble = NULL;
87 	bfa_trc(bfad, cmnd->result);
88 
89 	itnim_data = cmnd->device->hostdata;
90 	if (itnim_data) {
91 		itnim = itnim_data->itnim;
92 		if (!cmnd->result && itnim &&
93 			 (bfa_lun_queue_depth > cmnd->device->queue_depth)) {
94 			/* Queue depth adjustment for good status completion */
95 			bfad_ramp_up_qdepth(itnim, cmnd->device);
96 		} else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) {
97 			/* qfull handling */
98 			bfad_handle_qfull(itnim, cmnd->device);
99 		}
100 	}
101 
102 	cmnd->scsi_done(cmnd);
103 }
104 
105 void
106 bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio)
107 {
108 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
109 	struct bfad_itnim_data_s *itnim_data;
110 	struct bfad_itnim_s *itnim;
111 
112 	cmnd->result = ScsiResult(DID_OK, SCSI_STATUS_GOOD);
113 
114 	/* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
115 	if (cmnd->device->host != NULL)
116 		scsi_dma_unmap(cmnd);
117 
118 	cmnd->host_scribble = NULL;
119 
120 	/* Queue depth adjustment */
121 	if (bfa_lun_queue_depth > cmnd->device->queue_depth) {
122 		itnim_data = cmnd->device->hostdata;
123 		if (itnim_data) {
124 			itnim = itnim_data->itnim;
125 			if (itnim)
126 				bfad_ramp_up_qdepth(itnim, cmnd->device);
127 		}
128 	}
129 
130 	cmnd->scsi_done(cmnd);
131 }
132 
133 void
134 bfa_cb_ioim_abort(void *drv, struct bfad_ioim_s *dio)
135 {
136 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
137 	struct bfad_s         *bfad = drv;
138 
139 	cmnd->result = ScsiResult(DID_ERROR, 0);
140 
141 	/* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
142 	if (cmnd->device->host != NULL)
143 		scsi_dma_unmap(cmnd);
144 
145 	bfa_trc(bfad, cmnd->result);
146 	cmnd->host_scribble = NULL;
147 }
148 
149 void
150 bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
151 		   enum bfi_tskim_status tsk_status)
152 {
153 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dtsk;
154 	wait_queue_head_t *wq;
155 
156 	cmnd->SCp.Status |= tsk_status << 1;
157 	set_bit(IO_DONE_BIT, (unsigned long *)&cmnd->SCp.Status);
158 	wq = (wait_queue_head_t *) cmnd->SCp.ptr;
159 	cmnd->SCp.ptr = NULL;
160 
161 	if (wq)
162 		wake_up(wq);
163 }
164 
165 /*
166  *  Scsi_Host_template SCSI host template
167  */
168 /*
169  * Scsi_Host template entry, returns BFAD PCI info.
170  */
171 static const char *
172 bfad_im_info(struct Scsi_Host *shost)
173 {
174 	static char     bfa_buf[256];
175 	struct bfad_im_port_s *im_port =
176 			(struct bfad_im_port_s *) shost->hostdata[0];
177 	struct bfad_s *bfad = im_port->bfad;
178 	struct bfa_s *bfa = &bfad->bfa;
179 	struct bfa_ioc_s *ioc = &bfa->ioc;
180 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
181 
182 	bfa_get_adapter_model(bfa, model);
183 
184 	memset(bfa_buf, 0, sizeof(bfa_buf));
185 	if (ioc->ctdev && !ioc->fcmode)
186 		snprintf(bfa_buf, sizeof(bfa_buf),
187 		"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
188 		 model, bfad->pci_name, BFAD_DRIVER_VERSION);
189 	else
190 		snprintf(bfa_buf, sizeof(bfa_buf),
191 		"Brocade FC Adapter, " "model: %s hwpath: %s driver: %s",
192 		model, bfad->pci_name, BFAD_DRIVER_VERSION);
193 
194 	return bfa_buf;
195 }
196 
197 /*
198  * Scsi_Host template entry, aborts the specified SCSI command.
199  *
200  * Returns: SUCCESS or FAILED.
201  */
202 static int
203 bfad_im_abort_handler(struct scsi_cmnd *cmnd)
204 {
205 	struct Scsi_Host *shost = cmnd->device->host;
206 	struct bfad_im_port_s *im_port =
207 			(struct bfad_im_port_s *) shost->hostdata[0];
208 	struct bfad_s         *bfad = im_port->bfad;
209 	struct bfa_ioim_s *hal_io;
210 	unsigned long   flags;
211 	u32        timeout;
212 	int             rc = FAILED;
213 
214 	spin_lock_irqsave(&bfad->bfad_lock, flags);
215 	hal_io = (struct bfa_ioim_s *) cmnd->host_scribble;
216 	if (!hal_io) {
217 		/* IO has been completed, retrun success */
218 		rc = SUCCESS;
219 		goto out;
220 	}
221 	if (hal_io->dio != (struct bfad_ioim_s *) cmnd) {
222 		rc = FAILED;
223 		goto out;
224 	}
225 
226 	bfa_trc(bfad, hal_io->iotag);
227 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
228 		"scsi%d: abort cmnd %p iotag %x\n",
229 		im_port->shost->host_no, cmnd, hal_io->iotag);
230 	(void) bfa_ioim_abort(hal_io);
231 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
232 
233 	/* Need to wait until the command get aborted */
234 	timeout = 10;
235 	while ((struct bfa_ioim_s *) cmnd->host_scribble == hal_io) {
236 		set_current_state(TASK_UNINTERRUPTIBLE);
237 		schedule_timeout(timeout);
238 		if (timeout < 4 * HZ)
239 			timeout *= 2;
240 	}
241 
242 	cmnd->scsi_done(cmnd);
243 	bfa_trc(bfad, hal_io->iotag);
244 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
245 		"scsi%d: complete abort 0x%p iotag 0x%x\n",
246 		im_port->shost->host_no, cmnd, hal_io->iotag);
247 	return SUCCESS;
248 out:
249 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
250 	return rc;
251 }
252 
253 static bfa_status_t
254 bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
255 		     struct bfad_itnim_s *itnim)
256 {
257 	struct bfa_tskim_s *tskim;
258 	struct bfa_itnim_s *bfa_itnim;
259 	bfa_status_t    rc = BFA_STATUS_OK;
260 	struct scsi_lun scsilun;
261 
262 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
263 	if (!tskim) {
264 		BFA_LOG(KERN_ERR, bfad, bfa_log_level,
265 			"target reset, fail to allocate tskim\n");
266 		rc = BFA_STATUS_FAILED;
267 		goto out;
268 	}
269 
270 	/*
271 	 * Set host_scribble to NULL to avoid aborting a task command if
272 	 * happens.
273 	 */
274 	cmnd->host_scribble = NULL;
275 	cmnd->SCp.Status = 0;
276 	bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
277 	memset(&scsilun, 0, sizeof(scsilun));
278 	bfa_tskim_start(tskim, bfa_itnim, scsilun,
279 			    FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO);
280 out:
281 	return rc;
282 }
283 
284 /*
285  * Scsi_Host template entry, resets a LUN and abort its all commands.
286  *
287  * Returns: SUCCESS or FAILED.
288  *
289  */
290 static int
291 bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
292 {
293 	struct Scsi_Host *shost = cmnd->device->host;
294 	struct bfad_im_port_s *im_port =
295 			(struct bfad_im_port_s *) shost->hostdata[0];
296 	struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata;
297 	struct bfad_s         *bfad = im_port->bfad;
298 	struct bfa_tskim_s *tskim;
299 	struct bfad_itnim_s   *itnim;
300 	struct bfa_itnim_s *bfa_itnim;
301 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
302 	int             rc = SUCCESS;
303 	unsigned long   flags;
304 	enum bfi_tskim_status task_status;
305 	struct scsi_lun scsilun;
306 
307 	spin_lock_irqsave(&bfad->bfad_lock, flags);
308 	itnim = itnim_data->itnim;
309 	if (!itnim) {
310 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
311 		rc = FAILED;
312 		goto out;
313 	}
314 
315 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
316 	if (!tskim) {
317 		BFA_LOG(KERN_ERR, bfad, bfa_log_level,
318 				"LUN reset, fail to allocate tskim");
319 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
320 		rc = FAILED;
321 		goto out;
322 	}
323 
324 	/*
325 	 * Set host_scribble to NULL to avoid aborting a task command
326 	 * if happens.
327 	 */
328 	cmnd->host_scribble = NULL;
329 	cmnd->SCp.ptr = (char *)&wq;
330 	cmnd->SCp.Status = 0;
331 	bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
332 	int_to_scsilun(cmnd->device->lun, &scsilun);
333 	bfa_tskim_start(tskim, bfa_itnim, scsilun,
334 			    FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO);
335 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
336 
337 	wait_event(wq, test_bit(IO_DONE_BIT,
338 			(unsigned long *)&cmnd->SCp.Status));
339 
340 	task_status = cmnd->SCp.Status >> 1;
341 	if (task_status != BFI_TSKIM_STS_OK) {
342 		BFA_LOG(KERN_ERR, bfad, bfa_log_level,
343 			"LUN reset failure, status: %d\n", task_status);
344 		rc = FAILED;
345 	}
346 
347 out:
348 	return rc;
349 }
350 
351 /*
352  * Scsi_Host template entry, resets the bus and abort all commands.
353  */
354 static int
355 bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)
356 {
357 	struct Scsi_Host *shost = cmnd->device->host;
358 	struct bfad_im_port_s *im_port =
359 				(struct bfad_im_port_s *) shost->hostdata[0];
360 	struct bfad_s         *bfad = im_port->bfad;
361 	struct bfad_itnim_s   *itnim;
362 	unsigned long   flags;
363 	u32        i, rc, err_cnt = 0;
364 	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
365 	enum bfi_tskim_status task_status;
366 
367 	spin_lock_irqsave(&bfad->bfad_lock, flags);
368 	for (i = 0; i < MAX_FCP_TARGET; i++) {
369 		itnim = bfad_get_itnim(im_port, i);
370 		if (itnim) {
371 			cmnd->SCp.ptr = (char *)&wq;
372 			rc = bfad_im_target_reset_send(bfad, cmnd, itnim);
373 			if (rc != BFA_STATUS_OK) {
374 				err_cnt++;
375 				continue;
376 			}
377 
378 			/* wait target reset to complete */
379 			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
380 			wait_event(wq, test_bit(IO_DONE_BIT,
381 					(unsigned long *)&cmnd->SCp.Status));
382 			spin_lock_irqsave(&bfad->bfad_lock, flags);
383 
384 			task_status = cmnd->SCp.Status >> 1;
385 			if (task_status != BFI_TSKIM_STS_OK) {
386 				BFA_LOG(KERN_ERR, bfad, bfa_log_level,
387 					"target reset failure,"
388 					" status: %d\n", task_status);
389 				err_cnt++;
390 			}
391 		}
392 	}
393 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
394 
395 	if (err_cnt)
396 		return FAILED;
397 
398 	return SUCCESS;
399 }
400 
401 /*
402  * Scsi_Host template entry slave_destroy.
403  */
404 static void
405 bfad_im_slave_destroy(struct scsi_device *sdev)
406 {
407 	sdev->hostdata = NULL;
408 	return;
409 }
410 
411 /*
412  *  BFA FCS itnim callbacks
413  */
414 
415 /*
416  * BFA FCS itnim alloc callback, after successful PRLI
417  * Context: Interrupt
418  */
419 void
420 bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
421 		    struct bfad_itnim_s **itnim_drv)
422 {
423 	*itnim_drv = kzalloc(sizeof(struct bfad_itnim_s), GFP_ATOMIC);
424 	if (*itnim_drv == NULL)
425 		return;
426 
427 	(*itnim_drv)->im = bfad->im;
428 	*itnim = &(*itnim_drv)->fcs_itnim;
429 	(*itnim_drv)->state = ITNIM_STATE_NONE;
430 
431 	/*
432 	 * Initiaze the itnim_work
433 	 */
434 	INIT_WORK(&(*itnim_drv)->itnim_work, bfad_im_itnim_work_handler);
435 	bfad->bfad_flags |= BFAD_RPORT_ONLINE;
436 }
437 
438 /*
439  * BFA FCS itnim free callback.
440  * Context: Interrupt. bfad_lock is held
441  */
442 void
443 bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)
444 {
445 	struct bfad_port_s    *port;
446 	wwn_t wwpn;
447 	u32 fcid;
448 	char wwpn_str[32], fcid_str[16];
449 	struct bfad_im_s	*im = itnim_drv->im;
450 
451 	/* online to free state transtion should not happen */
452 	WARN_ON(itnim_drv->state == ITNIM_STATE_ONLINE);
453 
454 	itnim_drv->queue_work = 1;
455 	/* offline request is not yet done, use the same request to free */
456 	if (itnim_drv->state == ITNIM_STATE_OFFLINE_PENDING)
457 		itnim_drv->queue_work = 0;
458 
459 	itnim_drv->state = ITNIM_STATE_FREE;
460 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
461 	itnim_drv->im_port = port->im_port;
462 	wwpn = bfa_fcs_itnim_get_pwwn(&itnim_drv->fcs_itnim);
463 	fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);
464 	wwn2str(wwpn_str, wwpn);
465 	fcid2str(fcid_str, fcid);
466 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
467 		"ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",
468 		port->im_port->shost->host_no,
469 		fcid_str, wwpn_str);
470 
471 	/* ITNIM processing */
472 	if (itnim_drv->queue_work)
473 		queue_work(im->drv_workq, &itnim_drv->itnim_work);
474 }
475 
476 /*
477  * BFA FCS itnim online callback.
478  * Context: Interrupt. bfad_lock is held
479  */
480 void
481 bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv)
482 {
483 	struct bfad_port_s    *port;
484 	struct bfad_im_s	*im = itnim_drv->im;
485 
486 	itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim);
487 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
488 	itnim_drv->state = ITNIM_STATE_ONLINE;
489 	itnim_drv->queue_work = 1;
490 	itnim_drv->im_port = port->im_port;
491 
492 	/* ITNIM processing */
493 	if (itnim_drv->queue_work)
494 		queue_work(im->drv_workq, &itnim_drv->itnim_work);
495 }
496 
497 /*
498  * BFA FCS itnim offline callback.
499  * Context: Interrupt. bfad_lock is held
500  */
501 void
502 bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv)
503 {
504 	struct bfad_port_s    *port;
505 	struct bfad_s *bfad;
506 	struct bfad_im_s	*im = itnim_drv->im;
507 
508 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
509 	bfad = port->bfad;
510 	if ((bfad->pport.flags & BFAD_PORT_DELETE) ||
511 		 (port->flags & BFAD_PORT_DELETE)) {
512 		itnim_drv->state = ITNIM_STATE_OFFLINE;
513 		return;
514 	}
515 	itnim_drv->im_port = port->im_port;
516 	itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING;
517 	itnim_drv->queue_work = 1;
518 
519 	/* ITNIM processing */
520 	if (itnim_drv->queue_work)
521 		queue_work(im->drv_workq, &itnim_drv->itnim_work);
522 }
523 
524 /*
525  * Allocate a Scsi_Host for a port.
526  */
527 int
528 bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
529 			struct device *dev)
530 {
531 	int error = 1;
532 
533 	mutex_lock(&bfad_mutex);
534 	if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) {
535 		mutex_unlock(&bfad_mutex);
536 		printk(KERN_WARNING "idr_pre_get failure\n");
537 		goto out;
538 	}
539 
540 	error = idr_get_new(&bfad_im_port_index, im_port,
541 					 &im_port->idr_id);
542 	if (error) {
543 		mutex_unlock(&bfad_mutex);
544 		printk(KERN_WARNING "idr_get_new failure\n");
545 		goto out;
546 	}
547 
548 	mutex_unlock(&bfad_mutex);
549 
550 	im_port->shost = bfad_scsi_host_alloc(im_port, bfad);
551 	if (!im_port->shost) {
552 		error = 1;
553 		goto out_free_idr;
554 	}
555 
556 	im_port->shost->hostdata[0] = (unsigned long)im_port;
557 	im_port->shost->unique_id = im_port->idr_id;
558 	im_port->shost->this_id = -1;
559 	im_port->shost->max_id = MAX_FCP_TARGET;
560 	im_port->shost->max_lun = MAX_FCP_LUN;
561 	im_port->shost->max_cmd_len = 16;
562 	im_port->shost->can_queue = bfad->cfg_data.ioc_queue_depth;
563 	if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE)
564 		im_port->shost->transportt = bfad_im_scsi_transport_template;
565 	else
566 		im_port->shost->transportt =
567 				bfad_im_scsi_vport_transport_template;
568 
569 	error = scsi_add_host_with_dma(im_port->shost, dev, &bfad->pcidev->dev);
570 	if (error) {
571 		printk(KERN_WARNING "scsi_add_host failure %d\n", error);
572 		goto out_fc_rel;
573 	}
574 
575 	/* setup host fixed attribute if the lk supports */
576 	bfad_fc_host_init(im_port);
577 
578 	return 0;
579 
580 out_fc_rel:
581 	scsi_host_put(im_port->shost);
582 	im_port->shost = NULL;
583 out_free_idr:
584 	mutex_lock(&bfad_mutex);
585 	idr_remove(&bfad_im_port_index, im_port->idr_id);
586 	mutex_unlock(&bfad_mutex);
587 out:
588 	return error;
589 }
590 
591 void
592 bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
593 {
594 	bfa_trc(bfad, bfad->inst_no);
595 	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "Free scsi%d\n",
596 			im_port->shost->host_no);
597 
598 	fc_remove_host(im_port->shost);
599 
600 	scsi_remove_host(im_port->shost);
601 	scsi_host_put(im_port->shost);
602 
603 	mutex_lock(&bfad_mutex);
604 	idr_remove(&bfad_im_port_index, im_port->idr_id);
605 	mutex_unlock(&bfad_mutex);
606 }
607 
608 static void
609 bfad_im_port_delete_handler(struct work_struct *work)
610 {
611 	struct bfad_im_port_s *im_port =
612 		container_of(work, struct bfad_im_port_s, port_delete_work);
613 
614 	if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
615 		im_port->flags |= BFAD_PORT_DELETE;
616 		fc_vport_terminate(im_port->fc_vport);
617 	}
618 }
619 
620 bfa_status_t
621 bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port)
622 {
623 	int             rc = BFA_STATUS_OK;
624 	struct bfad_im_port_s *im_port;
625 
626 	im_port = kzalloc(sizeof(struct bfad_im_port_s), GFP_ATOMIC);
627 	if (im_port == NULL) {
628 		rc = BFA_STATUS_ENOMEM;
629 		goto ext;
630 	}
631 	port->im_port = im_port;
632 	im_port->port = port;
633 	im_port->bfad = bfad;
634 
635 	INIT_WORK(&im_port->port_delete_work, bfad_im_port_delete_handler);
636 	INIT_LIST_HEAD(&im_port->itnim_mapped_list);
637 	INIT_LIST_HEAD(&im_port->binding_list);
638 
639 ext:
640 	return rc;
641 }
642 
643 void
644 bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port)
645 {
646 	struct bfad_im_port_s *im_port = port->im_port;
647 
648 	queue_work(bfad->im->drv_workq,
649 				&im_port->port_delete_work);
650 }
651 
652 void
653 bfad_im_port_clean(struct bfad_im_port_s *im_port)
654 {
655 	struct bfad_fcp_binding *bp, *bp_new;
656 	unsigned long flags;
657 	struct bfad_s *bfad =  im_port->bfad;
658 
659 	spin_lock_irqsave(&bfad->bfad_lock, flags);
660 	list_for_each_entry_safe(bp, bp_new, &im_port->binding_list,
661 					list_entry) {
662 		list_del(&bp->list_entry);
663 		kfree(bp);
664 	}
665 
666 	/* the itnim_mapped_list must be empty at this time */
667 	WARN_ON(!list_empty(&im_port->itnim_mapped_list));
668 
669 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
670 }
671 
672 bfa_status_t
673 bfad_im_probe(struct bfad_s *bfad)
674 {
675 	struct bfad_im_s      *im;
676 	bfa_status_t    rc = BFA_STATUS_OK;
677 
678 	im = kzalloc(sizeof(struct bfad_im_s), GFP_KERNEL);
679 	if (im == NULL) {
680 		rc = BFA_STATUS_ENOMEM;
681 		goto ext;
682 	}
683 
684 	bfad->im = im;
685 	im->bfad = bfad;
686 
687 	if (bfad_thread_workq(bfad) != BFA_STATUS_OK) {
688 		kfree(im);
689 		rc = BFA_STATUS_FAILED;
690 	}
691 
692 ext:
693 	return rc;
694 }
695 
696 void
697 bfad_im_probe_undo(struct bfad_s *bfad)
698 {
699 	if (bfad->im) {
700 		bfad_destroy_workq(bfad->im);
701 		kfree(bfad->im);
702 		bfad->im = NULL;
703 	}
704 }
705 
706 struct Scsi_Host *
707 bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
708 {
709 	struct scsi_host_template *sht;
710 
711 	if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE)
712 		sht = &bfad_im_scsi_host_template;
713 	else
714 		sht = &bfad_im_vport_template;
715 
716 	sht->sg_tablesize = bfad->cfg_data.io_max_sge;
717 
718 	return scsi_host_alloc(sht, sizeof(unsigned long));
719 }
720 
721 void
722 bfad_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
723 {
724 	if (!(im_port->flags & BFAD_PORT_DELETE))
725 		flush_workqueue(bfad->im->drv_workq);
726 	bfad_im_scsi_host_free(im_port->bfad, im_port);
727 	bfad_im_port_clean(im_port);
728 	kfree(im_port);
729 }
730 
731 void
732 bfad_destroy_workq(struct bfad_im_s *im)
733 {
734 	if (im && im->drv_workq) {
735 		flush_workqueue(im->drv_workq);
736 		destroy_workqueue(im->drv_workq);
737 		im->drv_workq = NULL;
738 	}
739 }
740 
741 bfa_status_t
742 bfad_thread_workq(struct bfad_s *bfad)
743 {
744 	struct bfad_im_s      *im = bfad->im;
745 
746 	bfa_trc(bfad, 0);
747 	snprintf(im->drv_workq_name, KOBJ_NAME_LEN, "bfad_wq_%d",
748 		 bfad->inst_no);
749 	im->drv_workq = create_singlethread_workqueue(im->drv_workq_name);
750 	if (!im->drv_workq)
751 		return BFA_STATUS_FAILED;
752 
753 	return BFA_STATUS_OK;
754 }
755 
756 /*
757  * Scsi_Host template entry.
758  *
759  * Description:
760  * OS entry point to adjust the queue_depths on a per-device basis.
761  * Called once per device during the bus scan.
762  * Return non-zero if fails.
763  */
764 static int
765 bfad_im_slave_configure(struct scsi_device *sdev)
766 {
767 	if (sdev->tagged_supported)
768 		scsi_activate_tcq(sdev, bfa_lun_queue_depth);
769 	else
770 		scsi_deactivate_tcq(sdev, bfa_lun_queue_depth);
771 
772 	return 0;
773 }
774 
775 struct scsi_host_template bfad_im_scsi_host_template = {
776 	.module = THIS_MODULE,
777 	.name = BFAD_DRIVER_NAME,
778 	.info = bfad_im_info,
779 	.queuecommand = bfad_im_queuecommand,
780 	.eh_abort_handler = bfad_im_abort_handler,
781 	.eh_device_reset_handler = bfad_im_reset_lun_handler,
782 	.eh_bus_reset_handler = bfad_im_reset_bus_handler,
783 
784 	.slave_alloc = bfad_im_slave_alloc,
785 	.slave_configure = bfad_im_slave_configure,
786 	.slave_destroy = bfad_im_slave_destroy,
787 
788 	.this_id = -1,
789 	.sg_tablesize = BFAD_IO_MAX_SGE,
790 	.cmd_per_lun = 3,
791 	.use_clustering = ENABLE_CLUSTERING,
792 	.shost_attrs = bfad_im_host_attrs,
793 	.max_sectors = 0xFFFF,
794 };
795 
796 struct scsi_host_template bfad_im_vport_template = {
797 	.module = THIS_MODULE,
798 	.name = BFAD_DRIVER_NAME,
799 	.info = bfad_im_info,
800 	.queuecommand = bfad_im_queuecommand,
801 	.eh_abort_handler = bfad_im_abort_handler,
802 	.eh_device_reset_handler = bfad_im_reset_lun_handler,
803 	.eh_bus_reset_handler = bfad_im_reset_bus_handler,
804 
805 	.slave_alloc = bfad_im_slave_alloc,
806 	.slave_configure = bfad_im_slave_configure,
807 	.slave_destroy = bfad_im_slave_destroy,
808 
809 	.this_id = -1,
810 	.sg_tablesize = BFAD_IO_MAX_SGE,
811 	.cmd_per_lun = 3,
812 	.use_clustering = ENABLE_CLUSTERING,
813 	.shost_attrs = bfad_im_vport_attrs,
814 	.max_sectors = 0xFFFF,
815 };
816 
817 bfa_status_t
818 bfad_im_module_init(void)
819 {
820 	bfad_im_scsi_transport_template =
821 		fc_attach_transport(&bfad_im_fc_function_template);
822 	if (!bfad_im_scsi_transport_template)
823 		return BFA_STATUS_ENOMEM;
824 
825 	bfad_im_scsi_vport_transport_template =
826 		fc_attach_transport(&bfad_im_vport_fc_function_template);
827 	if (!bfad_im_scsi_vport_transport_template) {
828 		fc_release_transport(bfad_im_scsi_transport_template);
829 		return BFA_STATUS_ENOMEM;
830 	}
831 
832 	return BFA_STATUS_OK;
833 }
834 
835 void
836 bfad_im_module_exit(void)
837 {
838 	if (bfad_im_scsi_transport_template)
839 		fc_release_transport(bfad_im_scsi_transport_template);
840 
841 	if (bfad_im_scsi_vport_transport_template)
842 		fc_release_transport(bfad_im_scsi_vport_transport_template);
843 }
844 
845 void
846 bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
847 {
848 	struct scsi_device *tmp_sdev;
849 
850 	if (((jiffies - itnim->last_ramp_up_time) >
851 		BFA_QUEUE_FULL_RAMP_UP_TIME * HZ) &&
852 		((jiffies - itnim->last_queue_full_time) >
853 		BFA_QUEUE_FULL_RAMP_UP_TIME * HZ)) {
854 		shost_for_each_device(tmp_sdev, sdev->host) {
855 			if (bfa_lun_queue_depth > tmp_sdev->queue_depth) {
856 				if (tmp_sdev->id != sdev->id)
857 					continue;
858 				if (tmp_sdev->ordered_tags)
859 					scsi_adjust_queue_depth(tmp_sdev,
860 						MSG_ORDERED_TAG,
861 						tmp_sdev->queue_depth + 1);
862 				else
863 					scsi_adjust_queue_depth(tmp_sdev,
864 						MSG_SIMPLE_TAG,
865 						tmp_sdev->queue_depth + 1);
866 
867 				itnim->last_ramp_up_time = jiffies;
868 			}
869 		}
870 	}
871 }
872 
873 void
874 bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
875 {
876 	struct scsi_device *tmp_sdev;
877 
878 	itnim->last_queue_full_time = jiffies;
879 
880 	shost_for_each_device(tmp_sdev, sdev->host) {
881 		if (tmp_sdev->id != sdev->id)
882 			continue;
883 		scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1);
884 	}
885 }
886 
887 struct bfad_itnim_s *
888 bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
889 {
890 	struct bfad_itnim_s   *itnim = NULL;
891 
892 	/* Search the mapped list for this target ID */
893 	list_for_each_entry(itnim, &im_port->itnim_mapped_list, list_entry) {
894 		if (id == itnim->scsi_tgt_id)
895 			return itnim;
896 	}
897 
898 	return NULL;
899 }
900 
901 /*
902  * Scsi_Host template entry slave_alloc
903  */
904 static int
905 bfad_im_slave_alloc(struct scsi_device *sdev)
906 {
907 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
908 
909 	if (!rport || fc_remote_port_chkready(rport))
910 		return -ENXIO;
911 
912 	sdev->hostdata = rport->dd_data;
913 
914 	return 0;
915 }
916 
917 static u32
918 bfad_im_supported_speeds(struct bfa_s *bfa)
919 {
920 	struct bfa_ioc_attr_s *ioc_attr;
921 	u32 supported_speed = 0;
922 
923 	ioc_attr = kzalloc(sizeof(struct bfa_ioc_attr_s), GFP_KERNEL);
924 	if (!ioc_attr)
925 		return 0;
926 
927 	bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
928 	if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
929 		if (ioc_attr->adapter_attr.is_mezz) {
930 			supported_speed |= FC_PORTSPEED_8GBIT |
931 				FC_PORTSPEED_4GBIT |
932 				FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
933 		} else {
934 			supported_speed |= FC_PORTSPEED_8GBIT |
935 				FC_PORTSPEED_4GBIT |
936 				FC_PORTSPEED_2GBIT;
937 		}
938 	} else if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_4GBPS) {
939 		supported_speed |=  FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
940 				FC_PORTSPEED_1GBIT;
941 	} else if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_10GBPS) {
942 		supported_speed |= FC_PORTSPEED_10GBIT;
943 	}
944 	kfree(ioc_attr);
945 	return supported_speed;
946 }
947 
948 void
949 bfad_fc_host_init(struct bfad_im_port_s *im_port)
950 {
951 	struct Scsi_Host *host = im_port->shost;
952 	struct bfad_s         *bfad = im_port->bfad;
953 	struct bfad_port_s    *port = im_port->port;
954 	char symname[BFA_SYMNAME_MAXLEN];
955 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
956 
957 	fc_host_node_name(host) =
958 		cpu_to_be64((bfa_fcs_lport_get_nwwn(port->fcs_port)));
959 	fc_host_port_name(host) =
960 		cpu_to_be64((bfa_fcs_lport_get_pwwn(port->fcs_port)));
961 	fc_host_max_npiv_vports(host) = bfa_lps_get_max_vport(&bfad->bfa);
962 
963 	fc_host_supported_classes(host) = FC_COS_CLASS3;
964 
965 	memset(fc_host_supported_fc4s(host), 0,
966 	       sizeof(fc_host_supported_fc4s(host)));
967 	if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
968 		/* For FCP type 0x08 */
969 		fc_host_supported_fc4s(host)[2] = 1;
970 	/* For fibre channel services type 0x20 */
971 	fc_host_supported_fc4s(host)[7] = 1;
972 
973 	strncpy(symname, bfad->bfa_fcs.fabric.bport.port_cfg.sym_name.symname,
974 		BFA_SYMNAME_MAXLEN);
975 	sprintf(fc_host_symbolic_name(host), "%s", symname);
976 
977 	fc_host_supported_speeds(host) = bfad_im_supported_speeds(&bfad->bfa);
978 	fc_host_maxframe_size(host) = fcport->cfg.maxfrsize;
979 }
980 
981 static void
982 bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
983 {
984 	struct fc_rport_identifiers rport_ids;
985 	struct fc_rport *fc_rport;
986 	struct bfad_itnim_data_s *itnim_data;
987 
988 	rport_ids.node_name =
989 		cpu_to_be64(bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim));
990 	rport_ids.port_name =
991 		cpu_to_be64(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
992 	rport_ids.port_id =
993 		bfa_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));
994 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
995 
996 	itnim->fc_rport = fc_rport =
997 		fc_remote_port_add(im_port->shost, 0, &rport_ids);
998 
999 	if (!fc_rport)
1000 		return;
1001 
1002 	fc_rport->maxframe_size =
1003 		bfa_fcs_itnim_get_maxfrsize(&itnim->fcs_itnim);
1004 	fc_rport->supported_classes = bfa_fcs_itnim_get_cos(&itnim->fcs_itnim);
1005 
1006 	itnim_data = fc_rport->dd_data;
1007 	itnim_data->itnim = itnim;
1008 
1009 	rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
1010 
1011 	if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
1012 		fc_remote_port_rolechg(fc_rport, rport_ids.roles);
1013 
1014 	if ((fc_rport->scsi_target_id != -1)
1015 	    && (fc_rport->scsi_target_id < MAX_FCP_TARGET))
1016 		itnim->scsi_tgt_id = fc_rport->scsi_target_id;
1017 
1018 	return;
1019 }
1020 
1021 /*
1022  * Work queue handler using FC transport service
1023 * Context: kernel
1024  */
1025 static void
1026 bfad_im_itnim_work_handler(struct work_struct *work)
1027 {
1028 	struct bfad_itnim_s   *itnim = container_of(work, struct bfad_itnim_s,
1029 							itnim_work);
1030 	struct bfad_im_s      *im = itnim->im;
1031 	struct bfad_s         *bfad = im->bfad;
1032 	struct bfad_im_port_s *im_port;
1033 	unsigned long   flags;
1034 	struct fc_rport *fc_rport;
1035 	wwn_t wwpn;
1036 	u32 fcid;
1037 	char wwpn_str[32], fcid_str[16];
1038 
1039 	spin_lock_irqsave(&bfad->bfad_lock, flags);
1040 	im_port = itnim->im_port;
1041 	bfa_trc(bfad, itnim->state);
1042 	switch (itnim->state) {
1043 	case ITNIM_STATE_ONLINE:
1044 		if (!itnim->fc_rport) {
1045 			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1046 			bfad_im_fc_rport_add(im_port, itnim);
1047 			spin_lock_irqsave(&bfad->bfad_lock, flags);
1048 			wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
1049 			fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
1050 			wwn2str(wwpn_str, wwpn);
1051 			fcid2str(fcid_str, fcid);
1052 			list_add_tail(&itnim->list_entry,
1053 				&im_port->itnim_mapped_list);
1054 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
1055 				"ITNIM ONLINE Target: %d:0:%d "
1056 				"FCID: %s WWPN: %s\n",
1057 				im_port->shost->host_no,
1058 				itnim->scsi_tgt_id,
1059 				fcid_str, wwpn_str);
1060 		} else {
1061 			printk(KERN_WARNING
1062 				"%s: itnim %llx is already in online state\n",
1063 				__func__,
1064 				bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
1065 		}
1066 
1067 		break;
1068 	case ITNIM_STATE_OFFLINE_PENDING:
1069 		itnim->state = ITNIM_STATE_OFFLINE;
1070 		if (itnim->fc_rport) {
1071 			fc_rport = itnim->fc_rport;
1072 			((struct bfad_itnim_data_s *)
1073 				fc_rport->dd_data)->itnim = NULL;
1074 			itnim->fc_rport = NULL;
1075 			if (!(im_port->port->flags & BFAD_PORT_DELETE)) {
1076 				spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1077 				fc_rport->dev_loss_tmo =
1078 					bfa_fcpim_path_tov_get(&bfad->bfa) + 1;
1079 				fc_remote_port_delete(fc_rport);
1080 				spin_lock_irqsave(&bfad->bfad_lock, flags);
1081 			}
1082 			wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
1083 			fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
1084 			wwn2str(wwpn_str, wwpn);
1085 			fcid2str(fcid_str, fcid);
1086 			list_del(&itnim->list_entry);
1087 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
1088 				"ITNIM OFFLINE Target: %d:0:%d "
1089 				"FCID: %s WWPN: %s\n",
1090 				im_port->shost->host_no,
1091 				itnim->scsi_tgt_id,
1092 				fcid_str, wwpn_str);
1093 		}
1094 		break;
1095 	case ITNIM_STATE_FREE:
1096 		if (itnim->fc_rport) {
1097 			fc_rport = itnim->fc_rport;
1098 			((struct bfad_itnim_data_s *)
1099 				fc_rport->dd_data)->itnim = NULL;
1100 			itnim->fc_rport = NULL;
1101 			if (!(im_port->port->flags & BFAD_PORT_DELETE)) {
1102 				spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1103 				fc_rport->dev_loss_tmo =
1104 					bfa_fcpim_path_tov_get(&bfad->bfa) + 1;
1105 				fc_remote_port_delete(fc_rport);
1106 				spin_lock_irqsave(&bfad->bfad_lock, flags);
1107 			}
1108 			list_del(&itnim->list_entry);
1109 		}
1110 
1111 		kfree(itnim);
1112 		break;
1113 	default:
1114 		WARN_ON(1);
1115 		break;
1116 	}
1117 
1118 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1119 }
1120 
1121 /*
1122  * Scsi_Host template entry, queue a SCSI command to the BFAD.
1123  */
1124 static int
1125 bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
1126 {
1127 	struct bfad_im_port_s *im_port =
1128 		(struct bfad_im_port_s *) cmnd->device->host->hostdata[0];
1129 	struct bfad_s         *bfad = im_port->bfad;
1130 	struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata;
1131 	struct bfad_itnim_s   *itnim;
1132 	struct bfa_ioim_s *hal_io;
1133 	unsigned long   flags;
1134 	int             rc;
1135 	int       sg_cnt = 0;
1136 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
1137 
1138 	rc = fc_remote_port_chkready(rport);
1139 	if (rc) {
1140 		cmnd->result = rc;
1141 		done(cmnd);
1142 		return 0;
1143 	}
1144 
1145 	sg_cnt = scsi_dma_map(cmnd);
1146 	if (sg_cnt < 0)
1147 		return SCSI_MLQUEUE_HOST_BUSY;
1148 
1149 	cmnd->scsi_done = done;
1150 
1151 	spin_lock_irqsave(&bfad->bfad_lock, flags);
1152 	if (!(bfad->bfad_flags & BFAD_HAL_START_DONE)) {
1153 		printk(KERN_WARNING
1154 			"bfad%d, queuecommand %p %x failed, BFA stopped\n",
1155 		       bfad->inst_no, cmnd, cmnd->cmnd[0]);
1156 		cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
1157 		goto out_fail_cmd;
1158 	}
1159 
1160 
1161 	itnim = itnim_data->itnim;
1162 	if (!itnim) {
1163 		cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
1164 		goto out_fail_cmd;
1165 	}
1166 
1167 	hal_io = bfa_ioim_alloc(&bfad->bfa, (struct bfad_ioim_s *) cmnd,
1168 				    itnim->bfa_itnim, sg_cnt);
1169 	if (!hal_io) {
1170 		printk(KERN_WARNING "hal_io failure\n");
1171 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1172 		scsi_dma_unmap(cmnd);
1173 		return SCSI_MLQUEUE_HOST_BUSY;
1174 	}
1175 
1176 	cmnd->host_scribble = (char *)hal_io;
1177 	bfa_ioim_start(hal_io);
1178 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1179 
1180 	return 0;
1181 
1182 out_fail_cmd:
1183 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1184 	scsi_dma_unmap(cmnd);
1185 	if (done)
1186 		done(cmnd);
1187 
1188 	return 0;
1189 }
1190 
1191 static DEF_SCSI_QCMD(bfad_im_queuecommand)
1192 
1193 void
1194 bfad_rport_online_wait(struct bfad_s *bfad)
1195 {
1196 	int i;
1197 	int rport_delay = 10;
1198 
1199 	for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE)
1200 		&& i < bfa_linkup_delay; i++) {
1201 		set_current_state(TASK_UNINTERRUPTIBLE);
1202 		schedule_timeout(HZ);
1203 	}
1204 
1205 	if (bfad->bfad_flags & BFAD_PORT_ONLINE) {
1206 		rport_delay = rport_delay < bfa_linkup_delay ?
1207 			rport_delay : bfa_linkup_delay;
1208 		for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE)
1209 			&& i < rport_delay; i++) {
1210 			set_current_state(TASK_UNINTERRUPTIBLE);
1211 			schedule_timeout(HZ);
1212 		}
1213 
1214 		if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE)) {
1215 			set_current_state(TASK_UNINTERRUPTIBLE);
1216 			schedule_timeout(rport_delay * HZ);
1217 		}
1218 	}
1219 }
1220 
1221 int
1222 bfad_get_linkup_delay(struct bfad_s *bfad)
1223 {
1224 	u8		nwwns = 0;
1225 	wwn_t		wwns[BFA_PREBOOT_BOOTLUN_MAX];
1226 	int		linkup_delay;
1227 
1228 	/*
1229 	 * Querying for the boot target port wwns
1230 	 * -- read from boot information in flash.
1231 	 * If nwwns > 0 => boot over SAN and set linkup_delay = 30
1232 	 * else => local boot machine set linkup_delay = 0
1233 	 */
1234 
1235 	bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, wwns);
1236 
1237 	if (nwwns > 0)
1238 		/* If Boot over SAN set linkup_delay = 30sec */
1239 		linkup_delay = 30;
1240 	else
1241 		/* If local boot; no linkup_delay */
1242 		linkup_delay = 0;
1243 
1244 	return linkup_delay;
1245 }
1246