1/*
2 *  linux/drivers/scsi/esas2r/esas2r_disc.c
3 *      esas2r device discovery routines
4 *
5 *  Copyright (c) 2001-2013 ATTO Technology, Inc.
6 *  (mailto:linuxdrivers@attotech.com)
7 */
8/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License as published by
12 *  the Free Software Foundation; version 2 of the License.
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  NO WARRANTY
20 *  THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 *  CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 *  LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 *  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 *  solely responsible for determining the appropriateness of using and
25 *  distributing the Program and assumes all risks associated with its
26 *  exercise of rights under this Agreement, including but not limited to
27 *  the risks and costs of program errors, damage to or loss of data,
28 *  programs or equipment, and unavailability or interruption of operations.
29 *
30 *  DISCLAIMER OF LIABILITY
31 *  NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 *  DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 *  USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 *  HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38 *
39 *  You should have received a copy of the GNU General Public License
40 *  along with this program; if not, write to the Free Software
41 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
42 */
43/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
44
45#include "esas2r.h"
46
47/* Miscellaneous internal discovery routines */
48static void esas2r_disc_abort(struct esas2r_adapter *a,
49			      struct esas2r_request *rq);
50static bool esas2r_disc_continue(struct esas2r_adapter *a,
51				 struct esas2r_request *rq);
52static void esas2r_disc_fix_curr_requests(struct esas2r_adapter *a);
53static u32 esas2r_disc_get_phys_addr(struct esas2r_sg_context *sgc, u64 *addr);
54static bool esas2r_disc_start_request(struct esas2r_adapter *a,
55				      struct esas2r_request *rq);
56
57/* Internal discovery routines that process the states */
58static bool esas2r_disc_block_dev_scan(struct esas2r_adapter *a,
59				       struct esas2r_request *rq);
60static void esas2r_disc_block_dev_scan_cb(struct esas2r_adapter *a,
61					  struct esas2r_request *rq);
62static bool esas2r_disc_dev_add(struct esas2r_adapter *a,
63				struct esas2r_request *rq);
64static bool esas2r_disc_dev_remove(struct esas2r_adapter *a,
65				   struct esas2r_request *rq);
66static bool esas2r_disc_part_info(struct esas2r_adapter *a,
67				  struct esas2r_request *rq);
68static void esas2r_disc_part_info_cb(struct esas2r_adapter *a,
69				     struct esas2r_request *rq);
70static bool esas2r_disc_passthru_dev_info(struct esas2r_adapter *a,
71					  struct esas2r_request *rq);
72static void esas2r_disc_passthru_dev_info_cb(struct esas2r_adapter *a,
73					     struct esas2r_request *rq);
74static bool esas2r_disc_passthru_dev_addr(struct esas2r_adapter *a,
75					  struct esas2r_request *rq);
76static void esas2r_disc_passthru_dev_addr_cb(struct esas2r_adapter *a,
77					     struct esas2r_request *rq);
78static bool esas2r_disc_raid_grp_info(struct esas2r_adapter *a,
79				      struct esas2r_request *rq);
80static void esas2r_disc_raid_grp_info_cb(struct esas2r_adapter *a,
81					 struct esas2r_request *rq);
82
83void esas2r_disc_initialize(struct esas2r_adapter *a)
84{
85	struct esas2r_sas_nvram *nvr = a->nvram;
86
87	esas2r_trace_enter();
88
89	clear_bit(AF_DISC_IN_PROG, &a->flags);
90	clear_bit(AF2_DEV_SCAN, &a->flags2);
91	clear_bit(AF2_DEV_CNT_OK, &a->flags2);
92
93	a->disc_start_time = jiffies_to_msecs(jiffies);
94	a->disc_wait_time = nvr->dev_wait_time * 1000;
95	a->disc_wait_cnt = nvr->dev_wait_count;
96
97	if (a->disc_wait_cnt > ESAS2R_MAX_TARGETS)
98		a->disc_wait_cnt = ESAS2R_MAX_TARGETS;
99
100	/*
101	 * If we are doing chip reset or power management processing, always
102	 * wait for devices.  use the NVRAM device count if it is greater than
103	 * previously discovered devices.
104	 */
105
106	esas2r_hdebug("starting discovery...");
107
108	a->general_req.interrupt_cx = NULL;
109
110	if (test_bit(AF_CHPRST_DETECTED, &a->flags) ||
111	    test_bit(AF_POWER_MGT, &a->flags)) {
112		if (a->prev_dev_cnt == 0) {
113			/* Don't bother waiting if there is nothing to wait
114			 * for.
115			 */
116			a->disc_wait_time = 0;
117		} else {
118			/*
119			 * Set the device wait count to what was previously
120			 * found.  We don't care if the user only configured
121			 * a time because we know the exact count to wait for.
122			 * There is no need to honor the user's wishes to
123			 * always wait the full time.
124			 */
125			a->disc_wait_cnt = a->prev_dev_cnt;
126
127			/*
128			 * bump the minimum wait time to 15 seconds since the
129			 * default is 3 (system boot or the boot driver usually
130			 * buys us more time).
131			 */
132			if (a->disc_wait_time < 15000)
133				a->disc_wait_time = 15000;
134		}
135	}
136
137	esas2r_trace("disc wait count: %d", a->disc_wait_cnt);
138	esas2r_trace("disc wait time: %d", a->disc_wait_time);
139
140	if (a->disc_wait_time == 0)
141		esas2r_disc_check_complete(a);
142
143	esas2r_trace_exit();
144}
145
146void esas2r_disc_start_waiting(struct esas2r_adapter *a)
147{
148	unsigned long flags;
149
150	spin_lock_irqsave(&a->mem_lock, flags);
151
152	if (a->disc_ctx.disc_evt)
153		esas2r_disc_start_port(a);
154
155	spin_unlock_irqrestore(&a->mem_lock, flags);
156}
157
158void esas2r_disc_check_for_work(struct esas2r_adapter *a)
159{
160	struct esas2r_request *rq = &a->general_req;
161
162	/* service any pending interrupts first */
163
164	esas2r_polled_interrupt(a);
165
166	/*
167	 * now, interrupt processing may have queued up a discovery event.  go
168	 * see if we have one to start.  we couldn't start it in the ISR since
169	 * polled discovery would cause a deadlock.
170	 */
171
172	esas2r_disc_start_waiting(a);
173
174	if (rq->interrupt_cx == NULL)
175		return;
176
177	if (rq->req_stat == RS_STARTED
178	    && rq->timeout <= RQ_MAX_TIMEOUT) {
179		/* wait for the current discovery request to complete. */
180		esas2r_wait_request(a, rq);
181
182		if (rq->req_stat == RS_TIMEOUT) {
183			esas2r_disc_abort(a, rq);
184			esas2r_local_reset_adapter(a);
185			return;
186		}
187	}
188
189	if (rq->req_stat == RS_PENDING
190	    || rq->req_stat == RS_STARTED)
191		return;
192
193	esas2r_disc_continue(a, rq);
194}
195
196void esas2r_disc_check_complete(struct esas2r_adapter *a)
197{
198	unsigned long flags;
199
200	esas2r_trace_enter();
201
202	/* check to see if we should be waiting for devices */
203	if (a->disc_wait_time) {
204		u32 currtime = jiffies_to_msecs(jiffies);
205		u32 time = currtime - a->disc_start_time;
206
207		/*
208		 * Wait until the device wait time is exhausted or the device
209		 * wait count is satisfied.
210		 */
211		if (time < a->disc_wait_time
212		    && (esas2r_targ_db_get_tgt_cnt(a) < a->disc_wait_cnt
213			|| a->disc_wait_cnt == 0)) {
214			/* After three seconds of waiting, schedule a scan. */
215			if (time >= 3000
216			    && !test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
217				spin_lock_irqsave(&a->mem_lock, flags);
218				esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
219				spin_unlock_irqrestore(&a->mem_lock, flags);
220			}
221
222			esas2r_trace_exit();
223			return;
224		}
225
226		/*
227		 * We are done waiting...we think.  Adjust the wait time to
228		 * consume events after the count is met.
229		 */
230		if (!test_and_set_bit(AF2_DEV_CNT_OK, &a->flags2))
231			a->disc_wait_time = time + 3000;
232
233		/* If we haven't done a full scan yet, do it now. */
234		if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
235			spin_lock_irqsave(&a->mem_lock, flags);
236			esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
237			spin_unlock_irqrestore(&a->mem_lock, flags);
238			esas2r_trace_exit();
239			return;
240		}
241
242		/*
243		 * Now, if there is still time left to consume events, continue
244		 * waiting.
245		 */
246		if (time < a->disc_wait_time) {
247			esas2r_trace_exit();
248			return;
249		}
250	} else {
251		if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) {
252			spin_lock_irqsave(&a->mem_lock, flags);
253			esas2r_disc_queue_event(a, DCDE_DEV_SCAN);
254			spin_unlock_irqrestore(&a->mem_lock, flags);
255		}
256	}
257
258	/* We want to stop waiting for devices. */
259	a->disc_wait_time = 0;
260
261	if (test_bit(AF_DISC_POLLED, &a->flags) &&
262	    test_bit(AF_DISC_IN_PROG, &a->flags)) {
263		/*
264		 * Polled discovery is still pending so continue the active
265		 * discovery until it is done.  At that point, we will stop
266		 * polled discovery and transition to interrupt driven
267		 * discovery.
268		 */
269	} else {
270		/*
271		 * Done waiting for devices.  Note that we get here immediately
272		 * after deferred waiting completes because that is interrupt
273		 * driven; i.e. There is no transition.
274		 */
275		esas2r_disc_fix_curr_requests(a);
276		clear_bit(AF_DISC_PENDING, &a->flags);
277
278		/*
279		 * We have deferred target state changes until now because we
280		 * don't want to report any removals (due to the first arrival)
281		 * until the device wait time expires.
282		 */
283		set_bit(AF_PORT_CHANGE, &a->flags);
284	}
285
286	esas2r_trace_exit();
287}
288
289void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt)
290{
291	struct esas2r_disc_context *dc = &a->disc_ctx;
292
293	esas2r_trace_enter();
294
295	esas2r_trace("disc_event: %d", disc_evt);
296
297	/* Initialize the discovery context */
298	dc->disc_evt |= disc_evt;
299
300	/*
301	 * Don't start discovery before or during polled discovery.  if we did,
302	 * we would have a deadlock if we are in the ISR already.
303	 */
304	if (!test_bit(AF_CHPRST_PENDING, &a->flags) &&
305	    !test_bit(AF_DISC_POLLED, &a->flags))
306		esas2r_disc_start_port(a);
307
308	esas2r_trace_exit();
309}
310
311bool esas2r_disc_start_port(struct esas2r_adapter *a)
312{
313	struct esas2r_request *rq = &a->general_req;
314	struct esas2r_disc_context *dc = &a->disc_ctx;
315	bool ret;
316
317	esas2r_trace_enter();
318
319	if (test_bit(AF_DISC_IN_PROG, &a->flags)) {
320		esas2r_trace_exit();
321
322		return false;
323	}
324
325	/* If there is a discovery waiting, process it. */
326	if (dc->disc_evt) {
327		if (test_bit(AF_DISC_POLLED, &a->flags)
328		    && a->disc_wait_time == 0) {
329			/*
330			 * We are doing polled discovery, but we no longer want
331			 * to wait for devices.  Stop polled discovery and
332			 * transition to interrupt driven discovery.
333			 */
334
335			esas2r_trace_exit();
336
337			return false;
338		}
339	} else {
340		/* Discovery is complete. */
341
342		esas2r_hdebug("disc done");
343
344		set_bit(AF_PORT_CHANGE, &a->flags);
345
346		esas2r_trace_exit();
347
348		return false;
349	}
350
351	/* Handle the discovery context */
352	esas2r_trace("disc_evt: %d", dc->disc_evt);
353	set_bit(AF_DISC_IN_PROG, &a->flags);
354	dc->flags = 0;
355
356	if (test_bit(AF_DISC_POLLED, &a->flags))
357		dc->flags |= DCF_POLLED;
358
359	rq->interrupt_cx = dc;
360	rq->req_stat = RS_SUCCESS;
361
362	/* Decode the event code */
363	if (dc->disc_evt & DCDE_DEV_SCAN) {
364		dc->disc_evt &= ~DCDE_DEV_SCAN;
365
366		dc->flags |= DCF_DEV_SCAN;
367		dc->state = DCS_BLOCK_DEV_SCAN;
368	} else if (dc->disc_evt & DCDE_DEV_CHANGE) {
369		dc->disc_evt &= ~DCDE_DEV_CHANGE;
370
371		dc->flags |= DCF_DEV_CHANGE;
372		dc->state = DCS_DEV_RMV;
373	}
374
375	/* Continue interrupt driven discovery */
376	if (!test_bit(AF_DISC_POLLED, &a->flags))
377		ret = esas2r_disc_continue(a, rq);
378	else
379		ret = true;
380
381	esas2r_trace_exit();
382
383	return ret;
384}
385
386static bool esas2r_disc_continue(struct esas2r_adapter *a,
387				 struct esas2r_request *rq)
388{
389	struct esas2r_disc_context *dc =
390		(struct esas2r_disc_context *)rq->interrupt_cx;
391	bool rslt;
392
393	/* Device discovery/removal */
394	while (dc->flags & (DCF_DEV_CHANGE | DCF_DEV_SCAN)) {
395		rslt = false;
396
397		switch (dc->state) {
398		case DCS_DEV_RMV:
399
400			rslt = esas2r_disc_dev_remove(a, rq);
401			break;
402
403		case DCS_DEV_ADD:
404
405			rslt = esas2r_disc_dev_add(a, rq);
406			break;
407
408		case DCS_BLOCK_DEV_SCAN:
409
410			rslt = esas2r_disc_block_dev_scan(a, rq);
411			break;
412
413		case DCS_RAID_GRP_INFO:
414
415			rslt = esas2r_disc_raid_grp_info(a, rq);
416			break;
417
418		case DCS_PART_INFO:
419
420			rslt = esas2r_disc_part_info(a, rq);
421			break;
422
423		case DCS_PT_DEV_INFO:
424
425			rslt = esas2r_disc_passthru_dev_info(a, rq);
426			break;
427		case DCS_PT_DEV_ADDR:
428
429			rslt = esas2r_disc_passthru_dev_addr(a, rq);
430			break;
431		case DCS_DISC_DONE:
432
433			dc->flags &= ~(DCF_DEV_CHANGE | DCF_DEV_SCAN);
434			break;
435
436		default:
437
438			esas2r_bugon();
439			dc->state = DCS_DISC_DONE;
440			break;
441		}
442
443		if (rslt)
444			return true;
445	}
446
447	/* Discovery is done...for now. */
448	rq->interrupt_cx = NULL;
449
450	if (!test_bit(AF_DISC_PENDING, &a->flags))
451		esas2r_disc_fix_curr_requests(a);
452
453	clear_bit(AF_DISC_IN_PROG, &a->flags);
454
455	/* Start the next discovery. */
456	return esas2r_disc_start_port(a);
457}
458
459static bool esas2r_disc_start_request(struct esas2r_adapter *a,
460				      struct esas2r_request *rq)
461{
462	unsigned long flags;
463
464	/* Set the timeout to a minimum value. */
465	if (rq->timeout < ESAS2R_DEFAULT_TMO)
466		rq->timeout = ESAS2R_DEFAULT_TMO;
467
468	/*
469	 * Override the request type to distinguish discovery requests.  If we
470	 * end up deferring the request, esas2r_disc_local_start_request()
471	 * will be called to restart it.
472	 */
473	rq->req_type = RT_DISC_REQ;
474
475	spin_lock_irqsave(&a->queue_lock, flags);
476
477	if (!test_bit(AF_CHPRST_PENDING, &a->flags) &&
478	    !test_bit(AF_FLASHING, &a->flags))
479		esas2r_disc_local_start_request(a, rq);
480	else
481		list_add_tail(&rq->req_list, &a->defer_list);
482
483	spin_unlock_irqrestore(&a->queue_lock, flags);
484
485	return true;
486}
487
488void esas2r_disc_local_start_request(struct esas2r_adapter *a,
489				     struct esas2r_request *rq)
490{
491	esas2r_trace_enter();
492
493	list_add_tail(&rq->req_list, &a->active_list);
494
495	esas2r_start_vda_request(a, rq);
496
497	esas2r_trace_exit();
498
499	return;
500}
501
502static void esas2r_disc_abort(struct esas2r_adapter *a,
503			      struct esas2r_request *rq)
504{
505	struct esas2r_disc_context *dc =
506		(struct esas2r_disc_context *)rq->interrupt_cx;
507
508	esas2r_trace_enter();
509
510	/* abort the current discovery */
511
512	dc->state = DCS_DISC_DONE;
513
514	esas2r_trace_exit();
515}
516
517static bool esas2r_disc_block_dev_scan(struct esas2r_adapter *a,
518				       struct esas2r_request *rq)
519{
520	struct esas2r_disc_context *dc =
521		(struct esas2r_disc_context *)rq->interrupt_cx;
522	bool rslt;
523
524	esas2r_trace_enter();
525
526	esas2r_rq_init_request(rq, a);
527
528	esas2r_build_mgt_req(a,
529			     rq,
530			     VDAMGT_DEV_SCAN,
531			     0,
532			     0,
533			     0,
534			     NULL);
535
536	rq->comp_cb = esas2r_disc_block_dev_scan_cb;
537
538	rq->timeout = 30000;
539	rq->interrupt_cx = dc;
540
541	rslt = esas2r_disc_start_request(a, rq);
542
543	esas2r_trace_exit();
544
545	return rslt;
546}
547
548static void esas2r_disc_block_dev_scan_cb(struct esas2r_adapter *a,
549					  struct esas2r_request *rq)
550{
551	struct esas2r_disc_context *dc =
552		(struct esas2r_disc_context *)rq->interrupt_cx;
553	unsigned long flags;
554
555	esas2r_trace_enter();
556
557	spin_lock_irqsave(&a->mem_lock, flags);
558
559	if (rq->req_stat == RS_SUCCESS)
560		dc->scan_gen = rq->func_rsp.mgt_rsp.scan_generation;
561
562	dc->state = DCS_RAID_GRP_INFO;
563	dc->raid_grp_ix = 0;
564
565	esas2r_rq_destroy_request(rq, a);
566
567	/* continue discovery if it's interrupt driven */
568
569	if (!(dc->flags & DCF_POLLED))
570		esas2r_disc_continue(a, rq);
571
572	spin_unlock_irqrestore(&a->mem_lock, flags);
573
574	esas2r_trace_exit();
575}
576
577static bool esas2r_disc_raid_grp_info(struct esas2r_adapter *a,
578				      struct esas2r_request *rq)
579{
580	struct esas2r_disc_context *dc =
581		(struct esas2r_disc_context *)rq->interrupt_cx;
582	bool rslt;
583	struct atto_vda_grp_info *grpinfo;
584
585	esas2r_trace_enter();
586
587	esas2r_trace("raid_group_idx: %d", dc->raid_grp_ix);
588
589	if (dc->raid_grp_ix >= VDA_MAX_RAID_GROUPS) {
590		dc->state = DCS_DISC_DONE;
591
592		esas2r_trace_exit();
593
594		return false;
595	}
596
597	esas2r_rq_init_request(rq, a);
598
599	grpinfo = &rq->vda_rsp_data->mgt_data.data.grp_info;
600
601	memset(grpinfo, 0, sizeof(struct atto_vda_grp_info));
602
603	esas2r_build_mgt_req(a,
604			     rq,
605			     VDAMGT_GRP_INFO,
606			     dc->scan_gen,
607			     0,
608			     sizeof(struct atto_vda_grp_info),
609			     NULL);
610
611	grpinfo->grp_index = dc->raid_grp_ix;
612
613	rq->comp_cb = esas2r_disc_raid_grp_info_cb;
614
615	rq->interrupt_cx = dc;
616
617	rslt = esas2r_disc_start_request(a, rq);
618
619	esas2r_trace_exit();
620
621	return rslt;
622}
623
624static void esas2r_disc_raid_grp_info_cb(struct esas2r_adapter *a,
625					 struct esas2r_request *rq)
626{
627	struct esas2r_disc_context *dc =
628		(struct esas2r_disc_context *)rq->interrupt_cx;
629	unsigned long flags;
630	struct atto_vda_grp_info *grpinfo;
631
632	esas2r_trace_enter();
633
634	spin_lock_irqsave(&a->mem_lock, flags);
635
636	if (rq->req_stat == RS_SCAN_GEN) {
637		dc->scan_gen = rq->func_rsp.mgt_rsp.scan_generation;
638		dc->raid_grp_ix = 0;
639		goto done;
640	}
641
642	if (rq->req_stat == RS_SUCCESS) {
643		grpinfo = &rq->vda_rsp_data->mgt_data.data.grp_info;
644
645		if (grpinfo->status != VDA_GRP_STAT_ONLINE
646		    && grpinfo->status != VDA_GRP_STAT_DEGRADED) {
647			/* go to the next group. */
648
649			dc->raid_grp_ix++;
650		} else {
651			memcpy(&dc->raid_grp_name[0],
652			       &grpinfo->grp_name[0],
653			       sizeof(grpinfo->grp_name));
654
655			dc->interleave = le32_to_cpu(grpinfo->interleave);
656			dc->block_size = le32_to_cpu(grpinfo->block_size);
657
658			dc->state = DCS_PART_INFO;
659			dc->part_num = 0;
660		}
661	} else {
662		if (!(rq->req_stat == RS_GRP_INVALID)) {
663			esas2r_log(ESAS2R_LOG_WARN,
664				   "A request for RAID group info failed - "
665				   "returned with %x",
666				   rq->req_stat);
667		}
668
669		dc->dev_ix = 0;
670		dc->state = DCS_PT_DEV_INFO;
671	}
672
673done:
674
675	esas2r_rq_destroy_request(rq, a);
676
677	/* continue discovery if it's interrupt driven */
678
679	if (!(dc->flags & DCF_POLLED))
680		esas2r_disc_continue(a, rq);
681
682	spin_unlock_irqrestore(&a->mem_lock, flags);
683
684	esas2r_trace_exit();
685}
686
687static bool esas2r_disc_part_info(struct esas2r_adapter *a,
688				  struct esas2r_request *rq)
689{
690	struct esas2r_disc_context *dc =
691		(struct esas2r_disc_context *)rq->interrupt_cx;
692	bool rslt;
693	struct atto_vdapart_info *partinfo;
694
695	esas2r_trace_enter();
696
697	esas2r_trace("part_num: %d", dc->part_num);
698
699	if (dc->part_num >= VDA_MAX_PARTITIONS) {
700		dc->state = DCS_RAID_GRP_INFO;
701		dc->raid_grp_ix++;
702
703		esas2r_trace_exit();
704
705		return false;
706	}
707
708	esas2r_rq_init_request(rq, a);
709
710	partinfo = &rq->vda_rsp_data->mgt_data.data.part_info;
711
712	memset(partinfo, 0, sizeof(struct atto_vdapart_info));
713
714	esas2r_build_mgt_req(a,
715			     rq,
716			     VDAMGT_PART_INFO,
717			     dc->scan_gen,
718			     0,
719			     sizeof(struct atto_vdapart_info),
720			     NULL);
721
722	partinfo->part_no = dc->part_num;
723
724	memcpy(&partinfo->grp_name[0],
725	       &dc->raid_grp_name[0],
726	       sizeof(partinfo->grp_name));
727
728	rq->comp_cb = esas2r_disc_part_info_cb;
729
730	rq->interrupt_cx = dc;
731
732	rslt = esas2r_disc_start_request(a, rq);
733
734	esas2r_trace_exit();
735
736	return rslt;
737}
738
739static void esas2r_disc_part_info_cb(struct esas2r_adapter *a,
740				     struct esas2r_request *rq)
741{
742	struct esas2r_disc_context *dc =
743		(struct esas2r_disc_context *)rq->interrupt_cx;
744	unsigned long flags;
745	struct atto_vdapart_info *partinfo;
746
747	esas2r_trace_enter();
748
749	spin_lock_irqsave(&a->mem_lock, flags);
750
751	if (rq->req_stat == RS_SCAN_GEN) {
752		dc->scan_gen = rq->func_rsp.mgt_rsp.scan_generation;
753		dc->raid_grp_ix = 0;
754		dc->state = DCS_RAID_GRP_INFO;
755	} else if (rq->req_stat == RS_SUCCESS) {
756		partinfo = &rq->vda_rsp_data->mgt_data.data.part_info;
757
758		dc->part_num = partinfo->part_no;
759
760		dc->curr_virt_id = le16_to_cpu(partinfo->target_id);
761
762		esas2r_targ_db_add_raid(a, dc);
763
764		dc->part_num++;
765	} else {
766		if (!(rq->req_stat == RS_PART_LAST)) {
767			esas2r_log(ESAS2R_LOG_WARN,
768				   "A request for RAID group partition info "
769				   "failed - status:%d", rq->req_stat);
770		}
771
772		dc->state = DCS_RAID_GRP_INFO;
773		dc->raid_grp_ix++;
774	}
775
776	esas2r_rq_destroy_request(rq, a);
777
778	/* continue discovery if it's interrupt driven */
779
780	if (!(dc->flags & DCF_POLLED))
781		esas2r_disc_continue(a, rq);
782
783	spin_unlock_irqrestore(&a->mem_lock, flags);
784
785	esas2r_trace_exit();
786}
787
788static bool esas2r_disc_passthru_dev_info(struct esas2r_adapter *a,
789					  struct esas2r_request *rq)
790{
791	struct esas2r_disc_context *dc =
792		(struct esas2r_disc_context *)rq->interrupt_cx;
793	bool rslt;
794	struct atto_vda_devinfo *devinfo;
795
796	esas2r_trace_enter();
797
798	esas2r_trace("dev_ix: %d", dc->dev_ix);
799
800	esas2r_rq_init_request(rq, a);
801
802	devinfo = &rq->vda_rsp_data->mgt_data.data.dev_info;
803
804	memset(devinfo, 0, sizeof(struct atto_vda_devinfo));
805
806	esas2r_build_mgt_req(a,
807			     rq,
808			     VDAMGT_DEV_PT_INFO,
809			     dc->scan_gen,
810			     dc->dev_ix,
811			     sizeof(struct atto_vda_devinfo),
812			     NULL);
813
814	rq->comp_cb = esas2r_disc_passthru_dev_info_cb;
815
816	rq->interrupt_cx = dc;
817
818	rslt = esas2r_disc_start_request(a, rq);
819
820	esas2r_trace_exit();
821
822	return rslt;
823}
824
825static void esas2r_disc_passthru_dev_info_cb(struct esas2r_adapter *a,
826					     struct esas2r_request *rq)
827{
828	struct esas2r_disc_context *dc =
829		(struct esas2r_disc_context *)rq->interrupt_cx;
830	unsigned long flags;
831	struct atto_vda_devinfo *devinfo;
832
833	esas2r_trace_enter();
834
835	spin_lock_irqsave(&a->mem_lock, flags);
836
837	if (rq->req_stat == RS_SCAN_GEN) {
838		dc->scan_gen = rq->func_rsp.mgt_rsp.scan_generation;
839		dc->dev_ix = 0;
840		dc->state = DCS_PT_DEV_INFO;
841	} else if (rq->req_stat == RS_SUCCESS) {
842		devinfo = &rq->vda_rsp_data->mgt_data.data.dev_info;
843
844		dc->dev_ix = le16_to_cpu(rq->func_rsp.mgt_rsp.dev_index);
845
846		dc->curr_virt_id = le16_to_cpu(devinfo->target_id);
847
848		if (le16_to_cpu(devinfo->features) & VDADEVFEAT_PHYS_ID) {
849			dc->curr_phys_id =
850				le16_to_cpu(devinfo->phys_target_id);
851			dc->dev_addr_type = ATTO_GDA_AT_PORT;
852			dc->state = DCS_PT_DEV_ADDR;
853
854			esas2r_trace("curr_virt_id: %d", dc->curr_virt_id);
855			esas2r_trace("curr_phys_id: %d", dc->curr_phys_id);
856		} else {
857			dc->dev_ix++;
858		}
859	} else {
860		if (!(rq->req_stat == RS_DEV_INVALID)) {
861			esas2r_log(ESAS2R_LOG_WARN,
862				   "A request for device information failed - "
863				   "status:%d", rq->req_stat);
864		}
865
866		dc->state = DCS_DISC_DONE;
867	}
868
869	esas2r_rq_destroy_request(rq, a);
870
871	/* continue discovery if it's interrupt driven */
872
873	if (!(dc->flags & DCF_POLLED))
874		esas2r_disc_continue(a, rq);
875
876	spin_unlock_irqrestore(&a->mem_lock, flags);
877
878	esas2r_trace_exit();
879}
880
881static bool esas2r_disc_passthru_dev_addr(struct esas2r_adapter *a,
882					  struct esas2r_request *rq)
883{
884	struct esas2r_disc_context *dc =
885		(struct esas2r_disc_context *)rq->interrupt_cx;
886	bool rslt;
887	struct atto_ioctl *hi;
888	struct esas2r_sg_context sgc;
889
890	esas2r_trace_enter();
891
892	esas2r_rq_init_request(rq, a);
893
894	/* format the request. */
895
896	sgc.cur_offset = NULL;
897	sgc.get_phys_addr = (PGETPHYSADDR)esas2r_disc_get_phys_addr;
898	sgc.length = offsetof(struct atto_ioctl, data)
899		     + sizeof(struct atto_hba_get_device_address);
900
901	esas2r_sgc_init(&sgc, a, rq, rq->vrq->ioctl.sge);
902
903	esas2r_build_ioctl_req(a, rq, sgc.length, VDA_IOCTL_HBA);
904
905	if (!esas2r_build_sg_list(a, rq, &sgc)) {
906		esas2r_rq_destroy_request(rq, a);
907
908		esas2r_trace_exit();
909
910		return false;
911	}
912
913	rq->comp_cb = esas2r_disc_passthru_dev_addr_cb;
914
915	rq->interrupt_cx = dc;
916
917	/* format the IOCTL data. */
918
919	hi = (struct atto_ioctl *)a->disc_buffer;
920
921	memset(a->disc_buffer, 0, ESAS2R_DISC_BUF_LEN);
922
923	hi->version = ATTO_VER_GET_DEV_ADDR0;
924	hi->function = ATTO_FUNC_GET_DEV_ADDR;
925	hi->flags = HBAF_TUNNEL;
926
927	hi->data.get_dev_addr.target_id = le32_to_cpu(dc->curr_phys_id);
928	hi->data.get_dev_addr.addr_type = dc->dev_addr_type;
929
930	/* start it up. */
931
932	rslt = esas2r_disc_start_request(a, rq);
933
934	esas2r_trace_exit();
935
936	return rslt;
937}
938
939static void esas2r_disc_passthru_dev_addr_cb(struct esas2r_adapter *a,
940					     struct esas2r_request *rq)
941{
942	struct esas2r_disc_context *dc =
943		(struct esas2r_disc_context *)rq->interrupt_cx;
944	struct esas2r_target *t = NULL;
945	unsigned long flags;
946	struct atto_ioctl *hi;
947	u16 addrlen;
948
949	esas2r_trace_enter();
950
951	spin_lock_irqsave(&a->mem_lock, flags);
952
953	hi = (struct atto_ioctl *)a->disc_buffer;
954
955	if (rq->req_stat == RS_SUCCESS
956	    && hi->status == ATTO_STS_SUCCESS) {
957		addrlen = le16_to_cpu(hi->data.get_dev_addr.addr_len);
958
959		if (dc->dev_addr_type == ATTO_GDA_AT_PORT) {
960			if (addrlen == sizeof(u64))
961				memcpy(&dc->sas_addr,
962				       &hi->data.get_dev_addr.address[0],
963				       addrlen);
964			else
965				memset(&dc->sas_addr, 0, sizeof(dc->sas_addr));
966
967			/* Get the unique identifier. */
968			dc->dev_addr_type = ATTO_GDA_AT_UNIQUE;
969
970			goto next_dev_addr;
971		} else {
972			/* Add the pass through target. */
973			if (HIBYTE(addrlen) == 0) {
974				t = esas2r_targ_db_add_pthru(a,
975							     dc,
976							     &hi->data.
977							     get_dev_addr.
978							     address[0],
979							     (u8)hi->data.
980							     get_dev_addr.
981							     addr_len);
982
983				if (t)
984					memcpy(&t->sas_addr, &dc->sas_addr,
985					       sizeof(t->sas_addr));
986			} else {
987				/* getting the back end data failed */
988
989				esas2r_log(ESAS2R_LOG_WARN,
990					   "an error occurred retrieving the "
991					   "back end data (%s:%d)",
992					   __func__,
993					   __LINE__);
994			}
995		}
996	} else {
997		/* getting the back end data failed */
998
999		esas2r_log(ESAS2R_LOG_WARN,
1000			   "an error occurred retrieving the back end data - "
1001			   "rq->req_stat:%d hi->status:%d",
1002			   rq->req_stat, hi->status);
1003	}
1004
1005	/* proceed to the next device. */
1006
1007	if (dc->flags & DCF_DEV_SCAN) {
1008		dc->dev_ix++;
1009		dc->state = DCS_PT_DEV_INFO;
1010	} else if (dc->flags & DCF_DEV_CHANGE) {
1011		dc->curr_targ++;
1012		dc->state = DCS_DEV_ADD;
1013	} else {
1014		esas2r_bugon();
1015	}
1016
1017next_dev_addr:
1018	esas2r_rq_destroy_request(rq, a);
1019
1020	/* continue discovery if it's interrupt driven */
1021
1022	if (!(dc->flags & DCF_POLLED))
1023		esas2r_disc_continue(a, rq);
1024
1025	spin_unlock_irqrestore(&a->mem_lock, flags);
1026
1027	esas2r_trace_exit();
1028}
1029
1030static u32 esas2r_disc_get_phys_addr(struct esas2r_sg_context *sgc, u64 *addr)
1031{
1032	struct esas2r_adapter *a = sgc->adapter;
1033
1034	if (sgc->length > ESAS2R_DISC_BUF_LEN)
1035		esas2r_bugon();
1036
1037	*addr = a->uncached_phys
1038		+ (u64)((u8 *)a->disc_buffer - a->uncached);
1039
1040	return sgc->length;
1041}
1042
1043static bool esas2r_disc_dev_remove(struct esas2r_adapter *a,
1044				   struct esas2r_request *rq)
1045{
1046	struct esas2r_disc_context *dc =
1047		(struct esas2r_disc_context *)rq->interrupt_cx;
1048	struct esas2r_target *t;
1049	struct esas2r_target *t2;
1050
1051	esas2r_trace_enter();
1052
1053	/* process removals. */
1054
1055	for (t = a->targetdb; t < a->targetdb_end; t++) {
1056		if (t->new_target_state != TS_NOT_PRESENT)
1057			continue;
1058
1059		t->new_target_state = TS_INVALID;
1060
1061		/* remove the right target! */
1062
1063		t2 =
1064			esas2r_targ_db_find_by_virt_id(a,
1065						       esas2r_targ_get_id(t,
1066									  a));
1067
1068		if (t2)
1069			esas2r_targ_db_remove(a, t2);
1070	}
1071
1072	/* removals complete.  process arrivals. */
1073
1074	dc->state = DCS_DEV_ADD;
1075	dc->curr_targ = a->targetdb;
1076
1077	esas2r_trace_exit();
1078
1079	return false;
1080}
1081
1082static bool esas2r_disc_dev_add(struct esas2r_adapter *a,
1083				struct esas2r_request *rq)
1084{
1085	struct esas2r_disc_context *dc =
1086		(struct esas2r_disc_context *)rq->interrupt_cx;
1087	struct esas2r_target *t = dc->curr_targ;
1088
1089	if (t >= a->targetdb_end) {
1090		/* done processing state changes. */
1091
1092		dc->state = DCS_DISC_DONE;
1093	} else if (t->new_target_state == TS_PRESENT) {
1094		struct atto_vda_ae_lu *luevt = &t->lu_event;
1095
1096		esas2r_trace_enter();
1097
1098		/* clear this now in case more events come in. */
1099
1100		t->new_target_state = TS_INVALID;
1101
1102		/* setup the discovery context for adding this device. */
1103
1104		dc->curr_virt_id = esas2r_targ_get_id(t, a);
1105
1106		if ((luevt->hdr.bylength >= offsetof(struct atto_vda_ae_lu, id)
1107		     + sizeof(struct atto_vda_ae_lu_tgt_lun_raid))
1108		    && !(luevt->dwevent & VDAAE_LU_PASSTHROUGH)) {
1109			dc->block_size = luevt->id.tgtlun_raid.dwblock_size;
1110			dc->interleave = luevt->id.tgtlun_raid.dwinterleave;
1111		} else {
1112			dc->block_size = 0;
1113			dc->interleave = 0;
1114		}
1115
1116		/* determine the device type being added. */
1117
1118		if (luevt->dwevent & VDAAE_LU_PASSTHROUGH) {
1119			if (luevt->dwevent & VDAAE_LU_PHYS_ID) {
1120				dc->state = DCS_PT_DEV_ADDR;
1121				dc->dev_addr_type = ATTO_GDA_AT_PORT;
1122				dc->curr_phys_id = luevt->wphys_target_id;
1123			} else {
1124				esas2r_log(ESAS2R_LOG_WARN,
1125					   "luevt->dwevent does not have the "
1126					   "VDAAE_LU_PHYS_ID bit set (%s:%d)",
1127					   __func__, __LINE__);
1128			}
1129		} else {
1130			dc->raid_grp_name[0] = 0;
1131
1132			esas2r_targ_db_add_raid(a, dc);
1133		}
1134
1135		esas2r_trace("curr_virt_id: %d", dc->curr_virt_id);
1136		esas2r_trace("curr_phys_id: %d", dc->curr_phys_id);
1137		esas2r_trace("dwevent: %d", luevt->dwevent);
1138
1139		esas2r_trace_exit();
1140	}
1141
1142	if (dc->state == DCS_DEV_ADD) {
1143		/* go to the next device. */
1144
1145		dc->curr_targ++;
1146	}
1147
1148	return false;
1149}
1150
1151/*
1152 * When discovery is done, find all requests on defer queue and
1153 * test if they need to be modified. If a target is no longer present
1154 * then complete the request with RS_SEL. Otherwise, update the
1155 * target_id since after a hibernate it can be a different value.
1156 * VDA does not make passthrough target IDs persistent.
1157 */
1158static void esas2r_disc_fix_curr_requests(struct esas2r_adapter *a)
1159{
1160	unsigned long flags;
1161	struct esas2r_target *t;
1162	struct esas2r_request *rq;
1163	struct list_head *element;
1164
1165	/* update virt_targ_id in any outstanding esas2r_requests  */
1166
1167	spin_lock_irqsave(&a->queue_lock, flags);
1168
1169	list_for_each(element, &a->defer_list) {
1170		rq = list_entry(element, struct esas2r_request, req_list);
1171		if (rq->vrq->scsi.function == VDA_FUNC_SCSI) {
1172			t = a->targetdb + rq->target_id;
1173
1174			if (t->target_state == TS_PRESENT)
1175				rq->vrq->scsi.target_id = le16_to_cpu(
1176					t->virt_targ_id);
1177			else
1178				rq->req_stat = RS_SEL;
1179		}
1180
1181	}
1182
1183	spin_unlock_irqrestore(&a->queue_lock, flags);
1184}
1185