aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
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
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')
-rw-r--r--drivers/scsi/scsi_tgt_if.c42
-rw-r--r--drivers/scsi/scsi_tgt_lib.c83
-rw-r--r--drivers/scsi/scsi_tgt_priv.h22
3 files changed, 122 insertions, 25 deletions
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index ca22ddf81746..9815a1a2db24 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -102,7 +102,8 @@ static int tgt_uspace_send_event(u32 type, struct tgt_event *p)
102 return 0; 102 return 0;
103} 103}
104 104
105int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) 105int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id,
106 struct scsi_lun *lun, u64 tag)
106{ 107{
107 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); 108 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
108 struct tgt_event ev; 109 struct tgt_event ev;
@@ -110,6 +111,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta
110 111
111 memset(&ev, 0, sizeof(ev)); 112 memset(&ev, 0, sizeof(ev));
112 ev.p.cmd_req.host_no = shost->host_no; 113 ev.p.cmd_req.host_no = shost->host_no;
114 ev.p.cmd_req.itn_id = itn_id;
113 ev.p.cmd_req.data_len = cmd->request_bufflen; 115 ev.p.cmd_req.data_len = cmd->request_bufflen;
114 memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); 116 memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb));
115 memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); 117 memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun));
@@ -127,7 +129,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta
127 return err; 129 return err;
128} 130}
129 131
130int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) 132int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag)
131{ 133{
132 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); 134 struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
133 struct tgt_event ev; 135 struct tgt_event ev;
@@ -135,6 +137,7 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
135 137
136 memset(&ev, 0, sizeof(ev)); 138 memset(&ev, 0, sizeof(ev));
137 ev.p.cmd_done.host_no = shost->host_no; 139 ev.p.cmd_done.host_no = shost->host_no;
140 ev.p.cmd_done.itn_id = itn_id;
138 ev.p.cmd_done.tag = tag; 141 ev.p.cmd_done.tag = tag;
139 ev.p.cmd_done.result = cmd->result; 142 ev.p.cmd_done.result = cmd->result;
140 143
@@ -149,14 +152,15 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag)
149 return err; 152 return err;
150} 153}
151 154
152int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, 155int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function,
153 struct scsi_lun *scsilun, void *data) 156 u64 tag, struct scsi_lun *scsilun, void *data)
154{ 157{
155 struct tgt_event ev; 158 struct tgt_event ev;
156 int err; 159 int err;
157 160
158 memset(&ev, 0, sizeof(ev)); 161 memset(&ev, 0, sizeof(ev));
159 ev.p.tsk_mgmt_req.host_no = host_no; 162 ev.p.tsk_mgmt_req.host_no = host_no;
163 ev.p.tsk_mgmt_req.itn_id = itn_id;
160 ev.p.tsk_mgmt_req.function = function; 164 ev.p.tsk_mgmt_req.function = function;
161 ev.p.tsk_mgmt_req.tag = tag; 165 ev.p.tsk_mgmt_req.tag = tag;
162 memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); 166 memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun));
@@ -172,6 +176,29 @@ int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
172 return err; 176 return err;
173} 177}
174 178
179int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id,
180 int function, char *initiator_id)
181{
182 struct tgt_event ev;
183 int err;
184
185 memset(&ev, 0, sizeof(ev));
186 ev.p.it_nexus_req.host_no = host_no;
187 ev.p.it_nexus_req.function = function;
188 ev.p.it_nexus_req.itn_id = itn_id;
189 if (initiator_id)
190 strncpy(ev.p.it_nexus_req.initiator_id, initiator_id,
191 sizeof(ev.p.it_nexus_req.initiator_id));
192
193 dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id);
194
195 err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev);
196 if (err)
197 eprintk("tx buf is full, could not send\n");
198
199 return err;
200}
201
175static int event_recv_msg(struct tgt_event *ev) 202static int event_recv_msg(struct tgt_event *ev)
176{ 203{
177 int err = 0; 204 int err = 0;
@@ -179,6 +206,7 @@ static int event_recv_msg(struct tgt_event *ev)
179 switch (ev->hdr.type) { 206 switch (ev->hdr.type) {
180 case TGT_UEVENT_CMD_RSP: 207 case TGT_UEVENT_CMD_RSP:
181 err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, 208 err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
209 ev->p.cmd_rsp.itn_id,
182 ev->p.cmd_rsp.result, 210 ev->p.cmd_rsp.result,
183 ev->p.cmd_rsp.tag, 211 ev->p.cmd_rsp.tag,
184 ev->p.cmd_rsp.uaddr, 212 ev->p.cmd_rsp.uaddr,
@@ -189,9 +217,15 @@ static int event_recv_msg(struct tgt_event *ev)
189 break; 217 break;
190 case TGT_UEVENT_TSK_MGMT_RSP: 218 case TGT_UEVENT_TSK_MGMT_RSP:
191 err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, 219 err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no,
220 ev->p.tsk_mgmt_rsp.itn_id,
192 ev->p.tsk_mgmt_rsp.mid, 221 ev->p.tsk_mgmt_rsp.mid,
193 ev->p.tsk_mgmt_rsp.result); 222 ev->p.tsk_mgmt_rsp.result);
194 break; 223 break;
224 case TGT_UEVENT_IT_NEXUS_RSP:
225 err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no,
226 ev->p.it_nexus_rsp.itn_id,
227 ev->p.it_nexus_rsp.result);
228 break;
195 default: 229 default:
196 eprintk("unknown type %d\n", ev->hdr.type); 230 eprintk("unknown type %d\n", ev->hdr.type);
197 err = -EINVAL; 231 err = -EINVAL;
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;
diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h
index e9e6db1c417f..cb92888948f9 100644
--- a/drivers/scsi/scsi_tgt_priv.h
+++ b/drivers/scsi/scsi_tgt_priv.h
@@ -15,12 +15,18 @@ do { \
15extern void scsi_tgt_if_exit(void); 15extern void scsi_tgt_if_exit(void);
16extern int scsi_tgt_if_init(void); 16extern int scsi_tgt_if_init(void);
17 17
18extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, 18extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id,
19 u64 tag); 19 struct scsi_lun *lun, u64 tag);
20extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); 20extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id,
21extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, 21 u64 tag);
22 unsigned long uaddr, u32 len, unsigned long sense_uaddr, 22extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag,
23 u32 sense_len, u8 rw); 23 unsigned long uaddr, u32 len,
24extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, 24 unsigned long sense_uaddr, u32 sense_len, u8 rw);
25extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id,
26 int function, u64 tag,
25 struct scsi_lun *scsilun, void *data); 27 struct scsi_lun *scsilun, void *data);
26extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); 28extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id,
29 u64 mid, int result);
30extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id,
31 int function, char *initiator);
32extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result);