aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_tgt_lib.c
diff options
context:
space:
mode:
authorFUJITA Tomonori <tomof@acm.org>2007-07-11 02:08:17 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:37:50 -0400
commit2c47f9efbedbe5749b6bb16e59bc11d6e460855f (patch)
treebfc1a2154f67c3aa45f92e586678ffc37e5f80eb /drivers/scsi/scsi_tgt_lib.c
parentaebd5e476ecc8ceb53577b20f2a352ff4ceffd8d (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.c83
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
187static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, 189static 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 */
304int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, 307int 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
462int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, 465int 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
544int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, 547int 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}
556EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); 560EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request);
557 561
558int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) 562int 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);
581done:
582 scsi_host_put(shost);
583 return err;
584}
585
586int 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}
599EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create);
600
601int 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}
613EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy);
614
615int 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);
577done: 634done:
578 scsi_host_put(shost); 635 scsi_host_put(shost);
579 return err; 636 return err;