Branch data Line data Source code
1 : : /*
2 : : * Copyright 2014 Cisco Systems, Inc. All rights reserved.
3 : : *
4 : : * This program is free software; you may redistribute it and/or modify
5 : : * it under the terms of the GNU General Public License as published by
6 : : * the Free Software Foundation; version 2 of the License.
7 : : *
8 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
9 : : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10 : : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11 : : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
12 : : * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13 : : * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 : : * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
15 : : * SOFTWARE.
16 : : */
17 : :
18 : : #include <linux/errno.h>
19 : : #include <linux/mempool.h>
20 : :
21 : : #include <scsi/scsi_tcq.h>
22 : :
23 : : #include "snic_disc.h"
24 : : #include "snic.h"
25 : : #include "snic_io.h"
26 : :
27 : :
28 : : /* snic target types */
29 : : static const char * const snic_tgt_type_str[] = {
30 : : [SNIC_TGT_DAS] = "DAS",
31 : : [SNIC_TGT_SAN] = "SAN",
32 : : };
33 : :
34 : : static inline const char *
35 : 0 : snic_tgt_type_to_str(int typ)
36 : : {
37 : 0 : return ((typ > SNIC_TGT_NONE && typ <= SNIC_TGT_SAN) ?
38 : 0 : snic_tgt_type_str[typ] : "Unknown");
39 : : }
40 : :
41 : : static const char * const snic_tgt_state_str[] = {
42 : : [SNIC_TGT_STAT_INIT] = "INIT",
43 : : [SNIC_TGT_STAT_ONLINE] = "ONLINE",
44 : : [SNIC_TGT_STAT_OFFLINE] = "OFFLINE",
45 : : [SNIC_TGT_STAT_DEL] = "DELETION IN PROGRESS",
46 : : };
47 : :
48 : : const char *
49 : 0 : snic_tgt_state_to_str(int state)
50 : : {
51 : 0 : return ((state >= SNIC_TGT_STAT_INIT && state <= SNIC_TGT_STAT_DEL) ?
52 [ # # ]: 0 : snic_tgt_state_str[state] : "UNKNOWN");
53 : : }
54 : :
55 : : /*
56 : : * Initiate report_tgt req desc
57 : : */
58 : : static void
59 : 0 : snic_report_tgt_init(struct snic_host_req *req, u32 hid, u8 *buf, u32 len,
60 : : dma_addr_t rsp_buf_pa, ulong ctx)
61 : : {
62 : 0 : struct snic_sg_desc *sgd = NULL;
63 : :
64 : :
65 : 0 : snic_io_hdr_enc(&req->hdr, SNIC_REQ_REPORT_TGTS, 0, SCSI_NO_TAG, hid,
66 : : 1, ctx);
67 : :
68 : 0 : req->u.rpt_tgts.sg_cnt = cpu_to_le16(1);
69 : 0 : sgd = req_to_sgl(req);
70 : 0 : sgd[0].addr = cpu_to_le64(rsp_buf_pa);
71 : 0 : sgd[0].len = cpu_to_le32(len);
72 : 0 : sgd[0]._resvd = 0;
73 : 0 : req->u.rpt_tgts.sg_addr = cpu_to_le64((ulong)sgd);
74 : : }
75 : :
76 : : /*
77 : : * snic_queue_report_tgt_req: Queues report target request.
78 : : */
79 : : static int
80 : 0 : snic_queue_report_tgt_req(struct snic *snic)
81 : : {
82 : 0 : struct snic_req_info *rqi = NULL;
83 : 0 : u32 ntgts, buf_len = 0;
84 : 0 : u8 *buf = NULL;
85 : 0 : dma_addr_t pa = 0;
86 : 0 : int ret = 0;
87 : :
88 : 0 : rqi = snic_req_init(snic, 1);
89 [ # # ]: 0 : if (!rqi) {
90 : 0 : ret = -ENOMEM;
91 : 0 : goto error;
92 : : }
93 : :
94 [ # # ]: 0 : if (snic->fwinfo.max_tgts)
95 : 0 : ntgts = min_t(u32, snic->fwinfo.max_tgts, snic->shost->max_id);
96 : : else
97 : 0 : ntgts = snic->shost->max_id;
98 : :
99 : : /* Allocate Response Buffer */
100 [ # # ]: 0 : SNIC_BUG_ON(ntgts == 0);
101 : 0 : buf_len = ntgts * sizeof(struct snic_tgt_id) + SNIC_SG_DESC_ALIGN;
102 : :
103 : 0 : buf = kzalloc(buf_len, GFP_KERNEL|GFP_DMA);
104 [ # # ]: 0 : if (!buf) {
105 : 0 : snic_req_free(snic, rqi);
106 : 0 : SNIC_HOST_ERR(snic->shost, "Resp Buf Alloc Failed.\n");
107 : :
108 : 0 : ret = -ENOMEM;
109 : 0 : goto error;
110 : : }
111 : :
112 [ # # ]: 0 : SNIC_BUG_ON((((unsigned long)buf) % SNIC_SG_DESC_ALIGN) != 0);
113 : :
114 : 0 : pa = dma_map_single(&snic->pdev->dev, buf, buf_len, DMA_FROM_DEVICE);
115 : 0 : if (dma_mapping_error(&snic->pdev->dev, pa)) {
116 : 0 : SNIC_HOST_ERR(snic->shost,
117 : : "Rpt-tgt rspbuf %p: PCI DMA Mapping Failed\n",
118 : : buf);
119 : 0 : kfree(buf);
120 : 0 : snic_req_free(snic, rqi);
121 : 0 : ret = -EINVAL;
122 : :
123 : 0 : goto error;
124 : : }
125 : :
126 : :
127 [ # # ]: 0 : SNIC_BUG_ON(pa == 0);
128 : 0 : rqi->sge_va = (ulong) buf;
129 : :
130 : 0 : snic_report_tgt_init(rqi->req,
131 : 0 : snic->config.hid,
132 : : buf,
133 : : buf_len,
134 : : pa,
135 : : (ulong)rqi);
136 : :
137 : 0 : snic_handle_untagged_req(snic, rqi);
138 : :
139 : 0 : ret = snic_queue_wq_desc(snic, rqi->req, rqi->req_len);
140 [ # # ]: 0 : if (ret) {
141 : 0 : dma_unmap_single(&snic->pdev->dev, pa, buf_len,
142 : : DMA_FROM_DEVICE);
143 : 0 : kfree(buf);
144 : 0 : rqi->sge_va = 0;
145 : 0 : snic_release_untagged_req(snic, rqi);
146 : 0 : SNIC_HOST_ERR(snic->shost, "Queuing Report Tgts Failed.\n");
147 : :
148 : 0 : goto error;
149 : : }
150 : :
151 [ # # ]: 0 : SNIC_DISC_DBG(snic->shost, "Report Targets Issued.\n");
152 : :
153 : : return ret;
154 : :
155 : 0 : error:
156 : 0 : SNIC_HOST_ERR(snic->shost,
157 : : "Queuing Report Targets Failed, err = %d\n",
158 : : ret);
159 : 0 : return ret;
160 : : } /* end of snic_queue_report_tgt_req */
161 : :
162 : : /* call into SML */
163 : : static void
164 : 0 : snic_scsi_scan_tgt(struct work_struct *work)
165 : : {
166 : 0 : struct snic_tgt *tgt = container_of(work, struct snic_tgt, scan_work);
167 : 0 : struct Scsi_Host *shost = dev_to_shost(&tgt->dev);
168 : 0 : unsigned long flags;
169 : :
170 : 0 : SNIC_HOST_INFO(shost, "Scanning Target id 0x%x\n", tgt->id);
171 : 0 : scsi_scan_target(&tgt->dev,
172 : 0 : tgt->channel,
173 : : tgt->scsi_tgt_id,
174 : : SCAN_WILD_CARD,
175 : : SCSI_SCAN_RESCAN);
176 : :
177 : 0 : spin_lock_irqsave(shost->host_lock, flags);
178 : 0 : tgt->flags &= ~SNIC_TGT_SCAN_PENDING;
179 : 0 : spin_unlock_irqrestore(shost->host_lock, flags);
180 : 0 : } /* end of snic_scsi_scan_tgt */
181 : :
182 : : /*
183 : : * snic_tgt_lookup :
184 : : */
185 : : static struct snic_tgt *
186 : 0 : snic_tgt_lookup(struct snic *snic, struct snic_tgt_id *tgtid)
187 : : {
188 : 0 : struct list_head *cur, *nxt;
189 : 0 : struct snic_tgt *tgt = NULL;
190 : :
191 [ # # ]: 0 : list_for_each_safe(cur, nxt, &snic->disc.tgt_list) {
192 : 0 : tgt = list_entry(cur, struct snic_tgt, list);
193 [ # # ]: 0 : if (tgt->id == le32_to_cpu(tgtid->tgt_id))
194 : : return tgt;
195 : 0 : tgt = NULL;
196 : : }
197 : :
198 : : return tgt;
199 : : } /* end of snic_tgt_lookup */
200 : :
201 : : /*
202 : : * snic_tgt_dev_release : Called on dropping last ref for snic_tgt object
203 : : */
204 : : void
205 : 0 : snic_tgt_dev_release(struct device *dev)
206 : : {
207 : 0 : struct snic_tgt *tgt = dev_to_tgt(dev);
208 : :
209 [ # # ]: 0 : SNIC_HOST_INFO(snic_tgt_to_shost(tgt),
210 : : "Target Device ID %d (%s) Permanently Deleted.\n",
211 : : tgt->id,
212 : : dev_name(dev));
213 : :
214 [ # # # # ]: 0 : SNIC_BUG_ON(!list_empty(&tgt->list));
215 : 0 : kfree(tgt);
216 : 0 : }
217 : :
218 : : /*
219 : : * snic_tgt_del : work function to delete snic_tgt
220 : : */
221 : : static void
222 : 0 : snic_tgt_del(struct work_struct *work)
223 : : {
224 : 0 : struct snic_tgt *tgt = container_of(work, struct snic_tgt, del_work);
225 : 0 : struct Scsi_Host *shost = snic_tgt_to_shost(tgt);
226 : :
227 [ # # ]: 0 : if (tgt->flags & SNIC_TGT_SCAN_PENDING)
228 : 0 : scsi_flush_work(shost);
229 : :
230 : : /* Block IOs on child devices, stops new IOs */
231 : 0 : scsi_target_block(&tgt->dev);
232 : :
233 : : /* Cleanup IOs */
234 : 0 : snic_tgt_scsi_abort_io(tgt);
235 : :
236 : : /* Unblock IOs now, to flush if there are any. */
237 : 0 : scsi_target_unblock(&tgt->dev, SDEV_TRANSPORT_OFFLINE);
238 : :
239 : : /* Delete SCSI Target and sdevs */
240 : 0 : scsi_remove_target(&tgt->dev); /* ?? */
241 : 0 : device_del(&tgt->dev);
242 : 0 : put_device(&tgt->dev);
243 : 0 : } /* end of snic_tgt_del */
244 : :
245 : : /* snic_tgt_create: checks for existence of snic_tgt, if it doesn't
246 : : * it creates one.
247 : : */
248 : : static struct snic_tgt *
249 : 0 : snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid)
250 : : {
251 : 0 : struct snic_tgt *tgt = NULL;
252 : 0 : unsigned long flags;
253 : 0 : int ret;
254 : :
255 : 0 : tgt = snic_tgt_lookup(snic, tgtid);
256 [ # # ]: 0 : if (tgt) {
257 : : /* update the information if required */
258 : : return tgt;
259 : : }
260 : :
261 : 0 : tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
262 [ # # ]: 0 : if (!tgt) {
263 : 0 : SNIC_HOST_ERR(snic->shost, "Failure to allocate snic_tgt.\n");
264 : 0 : ret = -ENOMEM;
265 : :
266 : 0 : return tgt;
267 : : }
268 : :
269 [ # # ]: 0 : INIT_LIST_HEAD(&tgt->list);
270 : 0 : tgt->id = le32_to_cpu(tgtid->tgt_id);
271 : 0 : tgt->channel = 0;
272 : :
273 [ # # # # ]: 0 : SNIC_BUG_ON(le16_to_cpu(tgtid->tgt_type) > SNIC_TGT_SAN);
274 : 0 : tgt->tdata.typ = le16_to_cpu(tgtid->tgt_type);
275 : :
276 : : /*
277 : : * Plugging into SML Device Tree
278 : : */
279 : 0 : tgt->tdata.disc_id = 0;
280 : 0 : tgt->state = SNIC_TGT_STAT_INIT;
281 : 0 : device_initialize(&tgt->dev);
282 : 0 : tgt->dev.parent = get_device(&snic->shost->shost_gendev);
283 : 0 : tgt->dev.release = snic_tgt_dev_release;
284 [ # # # ]: 0 : INIT_WORK(&tgt->scan_work, snic_scsi_scan_tgt);
285 : 0 : INIT_WORK(&tgt->del_work, snic_tgt_del);
286 [ # # # ]: 0 : switch (tgt->tdata.typ) {
287 : 0 : case SNIC_TGT_DAS:
288 : 0 : dev_set_name(&tgt->dev, "snic_das_tgt:%d:%d-%d",
289 : 0 : snic->shost->host_no, tgt->channel, tgt->id);
290 : 0 : break;
291 : :
292 : 0 : case SNIC_TGT_SAN:
293 : 0 : dev_set_name(&tgt->dev, "snic_san_tgt:%d:%d-%d",
294 : 0 : snic->shost->host_no, tgt->channel, tgt->id);
295 : 0 : break;
296 : :
297 : 0 : default:
298 : 0 : SNIC_HOST_INFO(snic->shost, "Target type Unknown Detected.\n");
299 : 0 : dev_set_name(&tgt->dev, "snic_das_tgt:%d:%d-%d",
300 : 0 : snic->shost->host_no, tgt->channel, tgt->id);
301 : 0 : break;
302 : : }
303 : :
304 : 0 : spin_lock_irqsave(snic->shost->host_lock, flags);
305 : 0 : list_add_tail(&tgt->list, &snic->disc.tgt_list);
306 : 0 : tgt->scsi_tgt_id = snic->disc.nxt_tgt_id++;
307 : 0 : tgt->state = SNIC_TGT_STAT_ONLINE;
308 : 0 : spin_unlock_irqrestore(snic->shost->host_lock, flags);
309 : :
310 [ # # ]: 0 : SNIC_HOST_INFO(snic->shost,
311 : : "Tgt %d, type = %s detected. Adding..\n",
312 : : tgt->id, snic_tgt_type_to_str(tgt->tdata.typ));
313 : :
314 : 0 : ret = device_add(&tgt->dev);
315 [ # # ]: 0 : if (ret) {
316 : 0 : SNIC_HOST_ERR(snic->shost,
317 : : "Snic Tgt: device_add, with err = %d\n",
318 : : ret);
319 : :
320 : 0 : put_device(&snic->shost->shost_gendev);
321 : 0 : kfree(tgt);
322 : 0 : tgt = NULL;
323 : :
324 : 0 : return tgt;
325 : : }
326 : :
327 [ # # ]: 0 : SNIC_HOST_INFO(snic->shost, "Scanning %s.\n", dev_name(&tgt->dev));
328 : :
329 : 0 : scsi_queue_work(snic->shost, &tgt->scan_work);
330 : :
331 : 0 : return tgt;
332 : : } /* end of snic_tgt_create */
333 : :
334 : : /* Handler for discovery */
335 : : void
336 : 0 : snic_handle_tgt_disc(struct work_struct *work)
337 : : {
338 : 0 : struct snic *snic = container_of(work, struct snic, tgt_work);
339 : 0 : struct snic_tgt_id *tgtid = NULL;
340 : 0 : struct snic_tgt *tgt = NULL;
341 : 0 : unsigned long flags;
342 : 0 : int i;
343 : :
344 : 0 : spin_lock_irqsave(&snic->snic_lock, flags);
345 [ # # ]: 0 : if (snic->in_remove) {
346 : 0 : spin_unlock_irqrestore(&snic->snic_lock, flags);
347 : 0 : kfree(snic->disc.rtgt_info);
348 : :
349 : 0 : return;
350 : : }
351 : 0 : spin_unlock_irqrestore(&snic->snic_lock, flags);
352 : :
353 : 0 : mutex_lock(&snic->disc.mutex);
354 : : /* Discover triggered during disc in progress */
355 [ # # ]: 0 : if (snic->disc.req_cnt) {
356 : 0 : snic->disc.state = SNIC_DISC_DONE;
357 : 0 : snic->disc.req_cnt = 0;
358 : 0 : mutex_unlock(&snic->disc.mutex);
359 : 0 : kfree(snic->disc.rtgt_info);
360 : 0 : snic->disc.rtgt_info = NULL;
361 : :
362 : 0 : SNIC_HOST_INFO(snic->shost, "tgt_disc: Discovery restart.\n");
363 : : /* Start Discovery Again */
364 : 0 : snic_disc_start(snic);
365 : :
366 : 0 : return;
367 : : }
368 : :
369 : 0 : tgtid = (struct snic_tgt_id *)snic->disc.rtgt_info;
370 : :
371 [ # # # # : 0 : SNIC_BUG_ON(snic->disc.rtgt_cnt == 0 || tgtid == NULL);
# # # # #
# ]
372 : :
373 [ # # ]: 0 : for (i = 0; i < snic->disc.rtgt_cnt; i++) {
374 : 0 : tgt = snic_tgt_create(snic, &tgtid[i]);
375 [ # # ]: 0 : if (!tgt) {
376 : 0 : int buf_sz = snic->disc.rtgt_cnt * sizeof(*tgtid);
377 : :
378 : 0 : SNIC_HOST_ERR(snic->shost, "Failed to create tgt.\n");
379 : 0 : snic_hex_dump("rpt_tgt_rsp", (char *)tgtid, buf_sz);
380 : 0 : break;
381 : : }
382 : : }
383 : :
384 : 0 : snic->disc.rtgt_info = NULL;
385 : 0 : snic->disc.state = SNIC_DISC_DONE;
386 : 0 : mutex_unlock(&snic->disc.mutex);
387 : :
388 : 0 : SNIC_HOST_INFO(snic->shost, "Discovery Completed.\n");
389 : :
390 : 0 : kfree(tgtid);
391 : : } /* end of snic_handle_tgt_disc */
392 : :
393 : :
394 : : int
395 : 0 : snic_report_tgt_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
396 : : {
397 : :
398 : 0 : u8 typ, cmpl_stat;
399 : 0 : u32 cmnd_id, hid, tgt_cnt = 0;
400 : 0 : ulong ctx;
401 : 0 : struct snic_req_info *rqi = NULL;
402 : 0 : struct snic_tgt_id *tgtid;
403 : 0 : int i, ret = 0;
404 : :
405 [ # # ]: 0 : snic_io_hdr_dec(&fwreq->hdr, &typ, &cmpl_stat, &cmnd_id, &hid, &ctx);
406 : 0 : rqi = (struct snic_req_info *) ctx;
407 : 0 : tgtid = (struct snic_tgt_id *) rqi->sge_va;
408 : :
409 : 0 : tgt_cnt = le32_to_cpu(fwreq->u.rpt_tgts_cmpl.tgt_cnt);
410 [ # # ]: 0 : if (tgt_cnt == 0) {
411 : 0 : SNIC_HOST_ERR(snic->shost, "No Targets Found on this host.\n");
412 : 0 : ret = 1;
413 : :
414 : 0 : goto end;
415 : : }
416 : :
417 : : /* printing list of targets here */
418 : 0 : SNIC_HOST_INFO(snic->shost, "Target Count = %d\n", tgt_cnt);
419 : :
420 [ # # # # ]: 0 : SNIC_BUG_ON(tgt_cnt > snic->fwinfo.max_tgts);
421 : :
422 [ # # ]: 0 : for (i = 0; i < tgt_cnt; i++)
423 : 0 : SNIC_HOST_INFO(snic->shost,
424 : : "Tgt id = 0x%x\n",
425 : : le32_to_cpu(tgtid[i].tgt_id));
426 : :
427 : : /*
428 : : * Queue work for further processing,
429 : : * Response Buffer Memory is freed after creating targets
430 : : */
431 : 0 : snic->disc.rtgt_cnt = tgt_cnt;
432 : 0 : snic->disc.rtgt_info = (u8 *) tgtid;
433 : 0 : queue_work(snic_glob->event_q, &snic->tgt_work);
434 : 0 : ret = 0;
435 : :
436 : 0 : end:
437 : : /* Unmap Response Buffer */
438 : 0 : snic_pci_unmap_rsp_buf(snic, rqi);
439 [ # # ]: 0 : if (ret)
440 : 0 : kfree(tgtid);
441 : :
442 : 0 : rqi->sge_va = 0;
443 : 0 : snic_release_untagged_req(snic, rqi);
444 : :
445 : 0 : return ret;
446 : : } /* end of snic_report_tgt_cmpl_handler */
447 : :
448 : : /* Discovery init fn */
449 : : void
450 : 0 : snic_disc_init(struct snic_disc *disc)
451 : : {
452 : 0 : INIT_LIST_HEAD(&disc->tgt_list);
453 : 0 : mutex_init(&disc->mutex);
454 : 0 : disc->disc_id = 0;
455 : 0 : disc->nxt_tgt_id = 0;
456 : 0 : disc->state = SNIC_DISC_INIT;
457 : 0 : disc->req_cnt = 0;
458 : 0 : disc->rtgt_cnt = 0;
459 : 0 : disc->rtgt_info = NULL;
460 : 0 : disc->cb = NULL;
461 : 0 : } /* end of snic_disc_init */
462 : :
463 : : /* Discovery, uninit fn */
464 : : void
465 : 0 : snic_disc_term(struct snic *snic)
466 : : {
467 : 0 : struct snic_disc *disc = &snic->disc;
468 : :
469 : 0 : mutex_lock(&disc->mutex);
470 [ # # ]: 0 : if (disc->req_cnt) {
471 : 0 : disc->req_cnt = 0;
472 [ # # ]: 0 : SNIC_SCSI_DBG(snic->shost, "Terminating Discovery.\n");
473 : : }
474 : 0 : mutex_unlock(&disc->mutex);
475 : 0 : }
476 : :
477 : : /*
478 : : * snic_disc_start: Discovery Start ...
479 : : */
480 : : int
481 : 0 : snic_disc_start(struct snic *snic)
482 : : {
483 : 0 : struct snic_disc *disc = &snic->disc;
484 : 0 : unsigned long flags;
485 : 0 : int ret = 0;
486 : :
487 [ # # ]: 0 : SNIC_SCSI_DBG(snic->shost, "Discovery Start.\n");
488 : :
489 : 0 : spin_lock_irqsave(&snic->snic_lock, flags);
490 [ # # ]: 0 : if (snic->in_remove) {
491 : 0 : spin_unlock_irqrestore(&snic->snic_lock, flags);
492 : 0 : SNIC_ERR("snic driver removal in progress ...\n");
493 : 0 : ret = 0;
494 : :
495 : 0 : return ret;
496 : : }
497 : 0 : spin_unlock_irqrestore(&snic->snic_lock, flags);
498 : :
499 : 0 : mutex_lock(&disc->mutex);
500 [ # # ]: 0 : if (disc->state == SNIC_DISC_PENDING) {
501 : 0 : disc->req_cnt++;
502 : 0 : mutex_unlock(&disc->mutex);
503 : :
504 : 0 : return ret;
505 : : }
506 : 0 : disc->state = SNIC_DISC_PENDING;
507 : 0 : mutex_unlock(&disc->mutex);
508 : :
509 : 0 : ret = snic_queue_report_tgt_req(snic);
510 [ # # ]: 0 : if (ret)
511 : 0 : SNIC_HOST_INFO(snic->shost, "Discovery Failed, err=%d.\n", ret);
512 : :
513 : : return ret;
514 : : } /* end of snic_disc_start */
515 : :
516 : : /*
517 : : * snic_disc_work :
518 : : */
519 : : void
520 : 0 : snic_handle_disc(struct work_struct *work)
521 : : {
522 : 0 : struct snic *snic = container_of(work, struct snic, disc_work);
523 : 0 : int ret = 0;
524 : :
525 : 0 : SNIC_HOST_INFO(snic->shost, "disc_work: Discovery\n");
526 : :
527 : 0 : ret = snic_disc_start(snic);
528 : 0 : if (ret)
529 : : goto disc_err;
530 : :
531 : : disc_err:
532 : 0 : SNIC_HOST_ERR(snic->shost,
533 : : "disc_work: Discovery Failed w/ err = %d\n",
534 : : ret);
535 : 0 : } /* end of snic_disc_work */
536 : :
537 : : /*
538 : : * snic_tgt_del_all : cleanup all snic targets
539 : : * Called on unbinding the interface
540 : : */
541 : : void
542 : 0 : snic_tgt_del_all(struct snic *snic)
543 : : {
544 : 0 : struct snic_tgt *tgt = NULL;
545 : 0 : struct list_head *cur, *nxt;
546 : 0 : unsigned long flags;
547 : :
548 : 0 : scsi_flush_work(snic->shost);
549 : :
550 : 0 : mutex_lock(&snic->disc.mutex);
551 : 0 : spin_lock_irqsave(snic->shost->host_lock, flags);
552 : :
553 [ # # ]: 0 : list_for_each_safe(cur, nxt, &snic->disc.tgt_list) {
554 : 0 : tgt = list_entry(cur, struct snic_tgt, list);
555 : 0 : tgt->state = SNIC_TGT_STAT_DEL;
556 : 0 : list_del_init(&tgt->list);
557 : 0 : SNIC_HOST_INFO(snic->shost, "Tgt %d q'ing for del\n", tgt->id);
558 : 0 : queue_work(snic_glob->event_q, &tgt->del_work);
559 : 0 : tgt = NULL;
560 : : }
561 : 0 : spin_unlock_irqrestore(snic->shost->host_lock, flags);
562 : 0 : mutex_unlock(&snic->disc.mutex);
563 : :
564 : 0 : flush_workqueue(snic_glob->event_q);
565 : 0 : } /* end of snic_tgt_del_all */
|