diff options
author | FUJITA Tomonori <tomof@acm.org> | 2007-07-11 02:08:17 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:37:50 -0400 |
commit | 2c47f9efbedbe5749b6bb16e59bc11d6e460855f (patch) | |
tree | bfc1a2154f67c3aa45f92e586678ffc37e5f80eb /drivers/scsi/scsi_tgt_lib.c | |
parent | aebd5e476ecc8ceb53577b20f2a352ff4ceffd8d (diff) |
[SCSI] tgt: add I_T nexus support
tgt uses scsi_host as I_T nexus. This works for ibmvstgt because it
creates one scsi_host for one initiator. However, other target drivers
don't work like that.
This adds I_T nexus support, which enable one scsi_host to handle
multiple initiators. New scsi_tgt_it_nexus_create/destroy functions
are expected be called transport classes. For example, ibmvstgt
creates an initiator remote port, then the srp transport calls
tgt_it_nexus_create. tgt doesn't manages I_T nexus, instead it tells
tgtd, user-space daemon, to create a new I_T nexus.
On the receiving the response from tgtd, tgt calls
shost->transportt->it_nexus_response. transports should notify a
lld. The srp transport uses it_nexus_response callback in
srp_function_template to do that.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_tgt_lib.c')
-rw-r--r-- | drivers/scsi/scsi_tgt_lib.c | 83 |
1 files changed, 70 insertions, 13 deletions
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 371b69c110bc..fa79e54722db 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <scsi/scsi_cmnd.h> | 27 | #include <scsi/scsi_cmnd.h> |
28 | #include <scsi/scsi_device.h> | 28 | #include <scsi/scsi_device.h> |
29 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
30 | #include <scsi/scsi_transport.h> | ||
30 | #include <scsi/scsi_tgt.h> | 31 | #include <scsi/scsi_tgt.h> |
31 | 32 | ||
32 | #include "scsi_tgt_priv.h" | 33 | #include "scsi_tgt_priv.h" |
@@ -46,6 +47,7 @@ struct scsi_tgt_cmd { | |||
46 | 47 | ||
47 | struct list_head hash_list; | 48 | struct list_head hash_list; |
48 | struct request *rq; | 49 | struct request *rq; |
50 | u64 itn_id; | ||
49 | u64 tag; | 51 | u64 tag; |
50 | }; | 52 | }; |
51 | 53 | ||
@@ -185,12 +187,13 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) | |||
185 | } | 187 | } |
186 | 188 | ||
187 | static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, | 189 | static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, |
188 | u64 tag) | 190 | u64 itn_id, u64 tag) |
189 | { | 191 | { |
190 | struct scsi_tgt_queuedata *qdata = rq->q->queuedata; | 192 | struct scsi_tgt_queuedata *qdata = rq->q->queuedata; |
191 | unsigned long flags; | 193 | unsigned long flags; |
192 | struct list_head *head; | 194 | struct list_head *head; |
193 | 195 | ||
196 | tcmd->itn_id = itn_id; | ||
194 | tcmd->tag = tag; | 197 | tcmd->tag = tag; |
195 | tcmd->bio = NULL; | 198 | tcmd->bio = NULL; |
196 | INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); | 199 | INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); |
@@ -301,14 +304,14 @@ EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); | |||
301 | * @scsilun: scsi lun | 304 | * @scsilun: scsi lun |
302 | * @tag: unique value to identify this command for tmf | 305 | * @tag: unique value to identify this command for tmf |
303 | */ | 306 | */ |
304 | int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, | 307 | int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id, |
305 | u64 tag) | 308 | struct scsi_lun *scsilun, u64 tag) |
306 | { | 309 | { |
307 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | 310 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; |
308 | int err; | 311 | int err; |
309 | 312 | ||
310 | init_scsi_tgt_cmd(cmd->request, tcmd, tag); | 313 | init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag); |
311 | err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); | 314 | err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); |
312 | if (err) | 315 | if (err) |
313 | cmd_hashlist_del(cmd); | 316 | cmd_hashlist_del(cmd); |
314 | 317 | ||
@@ -326,7 +329,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) | |||
326 | 329 | ||
327 | dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); | 330 | dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); |
328 | 331 | ||
329 | scsi_tgt_uspace_send_status(cmd, tcmd->tag); | 332 | scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); |
330 | 333 | ||
331 | if (cmd->request_buffer) | 334 | if (cmd->request_buffer) |
332 | scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); | 335 | scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); |
@@ -459,7 +462,7 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) | |||
459 | return rq; | 462 | return rq; |
460 | } | 463 | } |
461 | 464 | ||
462 | int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, | 465 | int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, |
463 | unsigned long uaddr, u32 len, unsigned long sense_uaddr, | 466 | unsigned long uaddr, u32 len, unsigned long sense_uaddr, |
464 | u32 sense_len, u8 rw) | 467 | u32 sense_len, u8 rw) |
465 | { | 468 | { |
@@ -541,21 +544,22 @@ done: | |||
541 | return err; | 544 | return err; |
542 | } | 545 | } |
543 | 546 | ||
544 | int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, | 547 | int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, |
545 | struct scsi_lun *scsilun, void *data) | 548 | int function, u64 tag, struct scsi_lun *scsilun, |
549 | void *data) | ||
546 | { | 550 | { |
547 | int err; | 551 | int err; |
548 | 552 | ||
549 | /* TODO: need to retry if this fails. */ | 553 | /* TODO: need to retry if this fails. */ |
550 | err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, | 554 | err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id, |
551 | tag, scsilun, data); | 555 | function, tag, scsilun, data); |
552 | if (err < 0) | 556 | if (err < 0) |
553 | eprintk("The task management request lost!\n"); | 557 | eprintk("The task management request lost!\n"); |
554 | return err; | 558 | return err; |
555 | } | 559 | } |
556 | EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); | 560 | EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); |
557 | 561 | ||
558 | int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) | 562 | int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) |
559 | { | 563 | { |
560 | struct Scsi_Host *shost; | 564 | struct Scsi_Host *shost; |
561 | int err = -EINVAL; | 565 | int err = -EINVAL; |
@@ -573,7 +577,60 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) | |||
573 | goto done; | 577 | goto done; |
574 | } | 578 | } |
575 | 579 | ||
576 | err = shost->hostt->tsk_mgmt_response(mid, result); | 580 | err = shost->hostt->tsk_mgmt_response(shost, itn_id, mid, result); |
581 | done: | ||
582 | scsi_host_put(shost); | ||
583 | return err; | ||
584 | } | ||
585 | |||
586 | int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, | ||
587 | char *initiator) | ||
588 | { | ||
589 | int err; | ||
590 | |||
591 | /* TODO: need to retry if this fails. */ | ||
592 | err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0, | ||
593 | initiator); | ||
594 | if (err < 0) | ||
595 | eprintk("The i_t_neuxs request lost, %d %llx!\n", | ||
596 | shost->host_no, (unsigned long long)itn_id); | ||
597 | return err; | ||
598 | } | ||
599 | EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create); | ||
600 | |||
601 | int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) | ||
602 | { | ||
603 | int err; | ||
604 | |||
605 | /* TODO: need to retry if this fails. */ | ||
606 | err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, | ||
607 | itn_id, 1, NULL); | ||
608 | if (err < 0) | ||
609 | eprintk("The i_t_neuxs request lost, %d %llx!\n", | ||
610 | shost->host_no, (unsigned long long)itn_id); | ||
611 | return err; | ||
612 | } | ||
613 | EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy); | ||
614 | |||
615 | int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) | ||
616 | { | ||
617 | struct Scsi_Host *shost; | ||
618 | int err = -EINVAL; | ||
619 | |||
620 | dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); | ||
621 | |||
622 | shost = scsi_host_lookup(host_no); | ||
623 | if (IS_ERR(shost)) { | ||
624 | printk(KERN_ERR "Could not find host no %d\n", host_no); | ||
625 | return err; | ||
626 | } | ||
627 | |||
628 | if (!shost->uspace_req_q) { | ||
629 | printk(KERN_ERR "Not target scsi host %d\n", host_no); | ||
630 | goto done; | ||
631 | } | ||
632 | |||
633 | err = shost->transportt->it_nexus_response(shost, itn_id, result); | ||
577 | done: | 634 | done: |
578 | scsi_host_put(shost); | 635 | scsi_host_put(shost); |
579 | return err; | 636 | return err; |