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_if.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_if.c')
-rw-r--r-- | drivers/scsi/scsi_tgt_if.c | 42 |
1 files changed, 38 insertions, 4 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 | ||
105 | int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) | 105 | int 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 | ||
130 | int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) | 132 | int 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 | ||
152 | int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, | 155 | int 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 | ||
179 | int 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 | |||
175 | static int event_recv_msg(struct tgt_event *ev) | 202 | static 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; |