aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2006-11-30 13:00:54 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-12-03 10:28:01 -0500
commit0e5d030bef4de3e35bcca35dd9465e6672128570 (patch)
tree88c3bee5f6d35744e8aac2de8193294e1ced8a9d /drivers/scsi
parent26b14823441382264e6f3dfd01b8687dc18196fe (diff)
[SCSI] scsi tgt: IBM eServer i/pSeries virtual SCSI target driver
This is IBM Virtual SCSI target driver for tgt. The driver is based on the original ibmvscsis driver: http://lkml.org/lkml/2005/10/17/99 Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: Santiago Leon <santil@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Kconfig14
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/ibmvscsi/Makefile2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvstgt.c958
4 files changed, 975 insertions, 0 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 5570cdbf8f11..1b4bfaabcfbc 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -821,6 +821,20 @@ config SCSI_IBMVSCSI
821 To compile this driver as a module, choose M here: the 821 To compile this driver as a module, choose M here: the
822 module will be called ibmvscsic. 822 module will be called ibmvscsic.
823 823
824config SCSI_IBMVSCSIS
825 tristate "IBM Virtual SCSI Server support"
826 depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP
827 help
828 This is the SRP target driver for IBM pSeries virtual environments.
829
830 The userspace component needed to initialize the driver and
831 documentation can be found:
832
833 http://stgt.berlios.de/
834
835 To compile this driver as a module, choose M here: the
836 module will be called ibmvstgt.
837
824config SCSI_INITIO 838config SCSI_INITIO
825 tristate "Initio 9100U(W) support" 839 tristate "Initio 9100U(W) support"
826 depends on PCI && SCSI 840 depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 00691c4c3a6f..bd7c9888f7f4 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -128,6 +128,7 @@ obj-$(CONFIG_SCSI_NSP32) += nsp32.o
128obj-$(CONFIG_SCSI_IPR) += ipr.o 128obj-$(CONFIG_SCSI_IPR) += ipr.o
129obj-$(CONFIG_SCSI_SRP) += libsrp.o 129obj-$(CONFIG_SCSI_SRP) += libsrp.o
130obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ 130obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/
131obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/
131obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o 132obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
132obj-$(CONFIG_SCSI_STEX) += stex.o 133obj-$(CONFIG_SCSI_STEX) += stex.o
133 134
diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
index 4e247b6b8700..6ac0633d5452 100644
--- a/drivers/scsi/ibmvscsi/Makefile
+++ b/drivers/scsi/ibmvscsi/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o
3ibmvscsic-y += ibmvscsi.o 3ibmvscsic-y += ibmvscsi.o
4ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o 4ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o
5ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o 5ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o
6
7obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
new file mode 100644
index 000000000000..0e74174a1b37
--- /dev/null
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -0,0 +1,958 @@
1/*
2 * IBM eServer i/pSeries Virtual SCSI Target Driver
3 * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp.
4 * Santiago Leon (santil@us.ibm.com) IBM Corp.
5 * Linda Xie (lxie@us.ibm.com) IBM Corp.
6 *
7 * Copyright (C) 2005-2006 FUJITA Tomonori <tomof@acm.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 */
24#include <linux/interrupt.h>
25#include <linux/module.h>
26#include <scsi/scsi.h>
27#include <scsi/scsi_host.h>
28#include <scsi/scsi_tgt.h>
29#include <scsi/libsrp.h>
30#include <asm/hvcall.h>
31#include <asm/iommu.h>
32#include <asm/prom.h>
33#include <asm/vio.h>
34
35#include "ibmvscsi.h"
36
37#define INITIAL_SRP_LIMIT 16
38#define DEFAULT_MAX_SECTORS 512
39
40#define TGT_NAME "ibmvstgt"
41
42/*
43 * Hypervisor calls.
44 */
45#define h_copy_rdma(l, sa, sb, da, db) \
46 plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db)
47#define h_send_crq(ua, l, h) \
48 plpar_hcall_norets(H_SEND_CRQ, ua, l, h)
49#define h_reg_crq(ua, tok, sz)\
50 plpar_hcall_norets(H_REG_CRQ, ua, tok, sz);
51#define h_free_crq(ua) \
52 plpar_hcall_norets(H_FREE_CRQ, ua);
53
54/* tmp - will replace with SCSI logging stuff */
55#define eprintk(fmt, args...) \
56do { \
57 printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \
58} while (0)
59/* #define dprintk eprintk */
60#define dprintk(fmt, args...)
61
62struct vio_port {
63 struct vio_dev *dma_dev;
64
65 struct crq_queue crq_queue;
66 struct work_struct crq_work;
67
68 unsigned long liobn;
69 unsigned long riobn;
70};
71
72static struct workqueue_struct *vtgtd;
73
74/*
75 * These are fixed for the system and come from the Open Firmware device tree.
76 * We just store them here to save getting them every time.
77 */
78static char system_id[64] = "";
79static char partition_name[97] = "UNKNOWN";
80static unsigned int partition_number = -1;
81
82static struct vio_port *target_to_port(struct srp_target *target)
83{
84 return (struct vio_port *) target->ldata;
85}
86
87static inline union viosrp_iu *vio_iu(struct iu_entry *iue)
88{
89 return (union viosrp_iu *) (iue->sbuf->buf);
90}
91
92static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format)
93{
94 struct srp_target *target = iue->target;
95 struct vio_port *vport = target_to_port(target);
96 long rc, rc1;
97 union {
98 struct viosrp_crq cooked;
99 uint64_t raw[2];
100 } crq;
101
102 /* First copy the SRP */
103 rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma,
104 vport->riobn, iue->remote_token);
105
106 if (rc)
107 eprintk("Error %ld transferring data\n", rc);
108
109 crq.cooked.valid = 0x80;
110 crq.cooked.format = format;
111 crq.cooked.reserved = 0x00;
112 crq.cooked.timeout = 0x00;
113 crq.cooked.IU_length = length;
114 crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag;
115
116 if (rc == 0)
117 crq.cooked.status = 0x99; /* Just needs to be non-zero */
118 else
119 crq.cooked.status = 0x00;
120
121 rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]);
122
123 if (rc1) {
124 eprintk("%ld sending response\n", rc1);
125 return rc1;
126 }
127
128 return rc;
129}
130
131#define SRP_RSP_SENSE_DATA_LEN 18
132
133static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc,
134 unsigned char status, unsigned char asc)
135{
136 union viosrp_iu *iu = vio_iu(iue);
137 uint64_t tag = iu->srp.rsp.tag;
138
139 /* If the linked bit is on and status is good */
140 if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE))
141 status = 0x10;
142
143 memset(iu, 0, sizeof(struct srp_rsp));
144 iu->srp.rsp.opcode = SRP_RSP;
145 iu->srp.rsp.req_lim_delta = 1;
146 iu->srp.rsp.tag = tag;
147
148 if (test_bit(V_DIOVER, &iue->flags))
149 iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER;
150
151 iu->srp.rsp.data_in_res_cnt = 0;
152 iu->srp.rsp.data_out_res_cnt = 0;
153
154 iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID;
155
156 iu->srp.rsp.resp_data_len = 0;
157 iu->srp.rsp.status = status;
158 if (status) {
159 uint8_t *sense = iu->srp.rsp.data;
160
161 if (sc) {
162 iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
163 iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE;
164 memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE);
165 } else {
166 iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION;
167 iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
168 iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN;
169
170 /* Valid bit and 'current errors' */
171 sense[0] = (0x1 << 7 | 0x70);
172 /* Sense key */
173 sense[2] = status;
174 /* Additional sense length */
175 sense[7] = 0xa; /* 10 bytes */
176 /* Additional sense code */
177 sense[12] = asc;
178 }
179 }
180
181 send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN,
182 VIOSRP_SRP_FORMAT);
183
184 return 0;
185}
186
187static void handle_cmd_queue(struct srp_target *target)
188{
189 struct Scsi_Host *shost = target->shost;
190 struct iu_entry *iue;
191 struct srp_cmd *cmd;
192 unsigned long flags;
193 int err;
194
195retry:
196 spin_lock_irqsave(&target->lock, flags);
197
198 list_for_each_entry(iue, &target->cmd_queue, ilist) {
199 if (!test_and_set_bit(V_FLYING, &iue->flags)) {
200 spin_unlock_irqrestore(&target->lock, flags);
201 cmd = iue->sbuf->buf;
202 err = srp_cmd_queue(shost, cmd, iue, 0);
203 if (err) {
204 eprintk("cannot queue cmd %p %d\n", cmd, err);
205 srp_iu_put(iue);
206 }
207 goto retry;
208 }
209 }
210
211 spin_unlock_irqrestore(&target->lock, flags);
212}
213
214static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
215 struct srp_direct_buf *md, int nmd,
216 enum dma_data_direction dir, unsigned int rest)
217{
218 struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
219 struct srp_target *target = iue->target;
220 struct vio_port *vport = target_to_port(target);
221 dma_addr_t token;
222 long err;
223 unsigned int done = 0;
224 int i, sidx, soff;
225
226 sidx = soff = 0;
227 token = sg_dma_address(sg + sidx);
228
229 for (i = 0; i < nmd && rest; i++) {
230 unsigned int mdone, mlen;
231
232 mlen = min(rest, md[i].len);
233 for (mdone = 0; mlen;) {
234 int slen = min(sg_dma_len(sg + sidx) - soff, mlen);
235
236 if (dir == DMA_TO_DEVICE)
237 err = h_copy_rdma(slen,
238 vport->riobn,
239 md[i].va + mdone,
240 vport->liobn,
241 token + soff);
242 else
243 err = h_copy_rdma(slen,
244 vport->liobn,
245 token + soff,
246 vport->riobn,
247 md[i].va + mdone);
248
249 if (err != H_SUCCESS) {
250 eprintk("rdma error %d %d\n", dir, slen);
251 goto out;
252 }
253
254 mlen -= slen;
255 mdone += slen;
256 soff += slen;
257 done += slen;
258
259 if (soff == sg_dma_len(sg + sidx)) {
260 sidx++;
261 soff = 0;
262 token = sg_dma_address(sg + sidx);
263
264 if (sidx > nsg) {
265 eprintk("out of sg %p %d %d\n",
266 iue, sidx, nsg);
267 goto out;
268 }
269 }
270 };
271
272 rest -= mlen;
273 }
274out:
275
276 return 0;
277}
278
279static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
280 void (*done)(struct scsi_cmnd *))
281{
282 struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
283 int err;
284
285 err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
286
287 done(sc);
288
289 return err;
290}
291
292static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
293 void (*done)(struct scsi_cmnd *))
294{
295 unsigned long flags;
296 struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
297 struct srp_target *target = iue->target;
298
299 dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
300
301 spin_lock_irqsave(&target->lock, flags);
302 list_del(&iue->ilist);
303 spin_unlock_irqrestore(&target->lock, flags);
304
305 if (sc->result != SAM_STAT_GOOD) {
306 eprintk("operation failed %p %d %x\n",
307 iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
308 send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
309 } else
310 send_rsp(iue, sc, NO_SENSE, 0x00);
311
312 done(sc);
313 srp_iu_put(iue);
314 return 0;
315}
316
317int send_adapter_info(struct iu_entry *iue,
318 dma_addr_t remote_buffer, uint16_t length)
319{
320 struct srp_target *target = iue->target;
321 struct vio_port *vport = target_to_port(target);
322 struct Scsi_Host *shost = target->shost;
323 dma_addr_t data_token;
324 struct mad_adapter_info_data *info;
325 int err;
326
327 info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token,
328 GFP_KERNEL);
329 if (!info) {
330 eprintk("bad dma_alloc_coherent %p\n", target);
331 return 1;
332 }
333
334 /* Get remote info */
335 err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer,
336 vport->liobn, data_token);
337 if (err == H_SUCCESS) {
338 dprintk("Client connect: %s (%d)\n",
339 info->partition_name, info->partition_number);
340 }
341
342 memset(info, 0, sizeof(*info));
343
344 strcpy(info->srp_version, "16.a");
345 strncpy(info->partition_name, partition_name,
346 sizeof(info->partition_name));
347 info->partition_number = partition_number;
348 info->mad_version = 1;
349 info->os_type = 2;
350 info->port_max_txu[0] = shost->hostt->max_sectors << 9;
351
352 /* Send our info to remote */
353 err = h_copy_rdma(sizeof(*info), vport->liobn, data_token,
354 vport->riobn, remote_buffer);
355
356 dma_free_coherent(target->dev, sizeof(*info), info, data_token);
357
358 if (err != H_SUCCESS) {
359 eprintk("Error sending adapter info %d\n", err);
360 return 1;
361 }
362
363 return 0;
364}
365
366static void process_login(struct iu_entry *iue)
367{
368 union viosrp_iu *iu = vio_iu(iue);
369 struct srp_login_rsp *rsp = &iu->srp.login_rsp;
370 uint64_t tag = iu->srp.rsp.tag;
371
372 /* TODO handle case that requested size is wrong and
373 * buffer format is wrong
374 */
375 memset(iu, 0, sizeof(struct srp_login_rsp));
376 rsp->opcode = SRP_LOGIN_RSP;
377 rsp->req_lim_delta = INITIAL_SRP_LIMIT;
378 rsp->tag = tag;
379 rsp->max_it_iu_len = sizeof(union srp_iu);
380 rsp->max_ti_iu_len = sizeof(union srp_iu);
381 /* direct and indirect */
382 rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
383
384 send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT);
385}
386
387static inline void queue_cmd(struct iu_entry *iue)
388{
389 struct srp_target *target = iue->target;
390 unsigned long flags;
391
392 spin_lock_irqsave(&target->lock, flags);
393 list_add_tail(&iue->ilist, &target->cmd_queue);
394 spin_unlock_irqrestore(&target->lock, flags);
395}
396
397static int process_tsk_mgmt(struct iu_entry *iue)
398{
399 union viosrp_iu *iu = vio_iu(iue);
400 int fn;
401
402 dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func);
403
404 switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
405 case SRP_TSK_ABORT_TASK:
406 fn = ABORT_TASK;
407 break;
408 case SRP_TSK_ABORT_TASK_SET:
409 fn = ABORT_TASK_SET;
410 break;
411 case SRP_TSK_CLEAR_TASK_SET:
412 fn = CLEAR_TASK_SET;
413 break;
414 case SRP_TSK_LUN_RESET:
415 fn = LOGICAL_UNIT_RESET;
416 break;
417 case SRP_TSK_CLEAR_ACA:
418 fn = CLEAR_ACA;
419 break;
420 default:
421 fn = 0;
422 }
423 if (fn)
424 scsi_tgt_tsk_mgmt_request(iue->target->shost, fn,
425 iu->srp.tsk_mgmt.task_tag,
426 (struct scsi_lun *) &iu->srp.tsk_mgmt.lun,
427 iue);
428 else
429 send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20);
430
431 return !fn;
432}
433
434static int process_mad_iu(struct iu_entry *iue)
435{
436 union viosrp_iu *iu = vio_iu(iue);
437 struct viosrp_adapter_info *info;
438 struct viosrp_host_config *conf;
439
440 switch (iu->mad.empty_iu.common.type) {
441 case VIOSRP_EMPTY_IU_TYPE:
442 eprintk("%s\n", "Unsupported EMPTY MAD IU");
443 break;
444 case VIOSRP_ERROR_LOG_TYPE:
445 eprintk("%s\n", "Unsupported ERROR LOG MAD IU");
446 iu->mad.error_log.common.status = 1;
447 send_iu(iue, sizeof(iu->mad.error_log), VIOSRP_MAD_FORMAT);
448 break;
449 case VIOSRP_ADAPTER_INFO_TYPE:
450 info = &iu->mad.adapter_info;
451 info->common.status = send_adapter_info(iue, info->buffer,
452 info->common.length);
453 send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT);
454 break;
455 case VIOSRP_HOST_CONFIG_TYPE:
456 conf = &iu->mad.host_config;
457 conf->common.status = 1;
458 send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT);
459 break;
460 default:
461 eprintk("Unknown type %u\n", iu->srp.rsp.opcode);
462 }
463
464 return 1;
465}
466
467static int process_srp_iu(struct iu_entry *iue)
468{
469 union viosrp_iu *iu = vio_iu(iue);
470 int done = 1;
471 u8 opcode = iu->srp.rsp.opcode;
472
473 switch (opcode) {
474 case SRP_LOGIN_REQ:
475 process_login(iue);
476 break;
477 case SRP_TSK_MGMT:
478 done = process_tsk_mgmt(iue);
479 break;
480 case SRP_CMD:
481 queue_cmd(iue);
482 done = 0;
483 break;
484 case SRP_LOGIN_RSP:
485 case SRP_I_LOGOUT:
486 case SRP_T_LOGOUT:
487 case SRP_RSP:
488 case SRP_CRED_REQ:
489 case SRP_CRED_RSP:
490 case SRP_AER_REQ:
491 case SRP_AER_RSP:
492 eprintk("Unsupported type %u\n", opcode);
493 break;
494 default:
495 eprintk("Unknown type %u\n", opcode);
496 }
497
498 return done;
499}
500
501static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
502{
503 struct vio_port *vport = target_to_port(target);
504 struct iu_entry *iue;
505 long err, done;
506
507 iue = srp_iu_get(target);
508 if (!iue) {
509 eprintk("Error getting IU from pool, %p\n", target);
510 return;
511 }
512
513 iue->remote_token = crq->IU_data_ptr;
514
515 err = h_copy_rdma(crq->IU_length, vport->riobn,
516 iue->remote_token, vport->liobn, iue->sbuf->dma);
517
518 if (err != H_SUCCESS) {
519 eprintk("%ld transferring data error %p\n", err, iue);
520 done = 1;
521 goto out;
522 }
523
524 if (crq->format == VIOSRP_MAD_FORMAT)
525 done = process_mad_iu(iue);
526 else
527 done = process_srp_iu(iue);
528out:
529 if (done)
530 srp_iu_put(iue);
531}
532
533static irqreturn_t ibmvstgt_interrupt(int irq, void *data)
534{
535 struct srp_target *target = (struct srp_target *) data;
536 struct vio_port *vport = target_to_port(target);
537
538 vio_disable_interrupts(vport->dma_dev);
539 queue_work(vtgtd, &vport->crq_work);
540
541 return IRQ_HANDLED;
542}
543
544static int crq_queue_create(struct crq_queue *queue, struct srp_target *target)
545{
546 int err;
547 struct vio_port *vport = target_to_port(target);
548
549 queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL);
550 if (!queue->msgs)
551 goto malloc_failed;
552 queue->size = PAGE_SIZE / sizeof(*queue->msgs);
553
554 queue->msg_token = dma_map_single(target->dev, queue->msgs,
555 queue->size * sizeof(*queue->msgs),
556 DMA_BIDIRECTIONAL);
557
558 if (dma_mapping_error(queue->msg_token))
559 goto map_failed;
560
561 err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
562 PAGE_SIZE);
563
564 /* If the adapter was left active for some reason (like kexec)
565 * try freeing and re-registering
566 */
567 if (err == H_RESOURCE) {
568 do {
569 err = h_free_crq(vport->dma_dev->unit_address);
570 } while (err == H_BUSY || H_IS_LONG_BUSY(err));
571
572 err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
573 PAGE_SIZE);
574 }
575
576 if (err != H_SUCCESS && err != 2) {
577 eprintk("Error 0x%x opening virtual adapter\n", err);
578 goto reg_crq_failed;
579 }
580
581 err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt,
582 SA_INTERRUPT, "ibmvstgt", target);
583 if (err)
584 goto req_irq_failed;
585
586 vio_enable_interrupts(vport->dma_dev);
587
588 h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0);
589
590 queue->cur = 0;
591 spin_lock_init(&queue->lock);
592
593 return 0;
594
595req_irq_failed:
596 do {
597 err = h_free_crq(vport->dma_dev->unit_address);
598 } while (err == H_BUSY || H_IS_LONG_BUSY(err));
599
600reg_crq_failed:
601 dma_unmap_single(target->dev, queue->msg_token,
602 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
603map_failed:
604 free_page((unsigned long) queue->msgs);
605
606malloc_failed:
607 return -ENOMEM;
608}
609
610static void crq_queue_destroy(struct srp_target *target)
611{
612 struct vio_port *vport = target_to_port(target);
613 struct crq_queue *queue = &vport->crq_queue;
614 int err;
615
616 free_irq(vport->dma_dev->irq, target);
617 do {
618 err = h_free_crq(vport->dma_dev->unit_address);
619 } while (err == H_BUSY || H_IS_LONG_BUSY(err));
620
621 dma_unmap_single(target->dev, queue->msg_token,
622 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
623
624 free_page((unsigned long) queue->msgs);
625}
626
627static void process_crq(struct viosrp_crq *crq, struct srp_target *target)
628{
629 struct vio_port *vport = target_to_port(target);
630 dprintk("%x %x\n", crq->valid, crq->format);
631
632 switch (crq->valid) {
633 case 0xC0:
634 /* initialization */
635 switch (crq->format) {
636 case 0x01:
637 h_send_crq(vport->dma_dev->unit_address,
638 0xC002000000000000, 0);
639 break;
640 case 0x02:
641 break;
642 default:
643 eprintk("Unknown format %u\n", crq->format);
644 }
645 break;
646 case 0xFF:
647 /* transport event */
648 break;
649 case 0x80:
650 /* real payload */
651 switch (crq->format) {
652 case VIOSRP_SRP_FORMAT:
653 case VIOSRP_MAD_FORMAT:
654 process_iu(crq, target);
655 break;
656 case VIOSRP_OS400_FORMAT:
657 case VIOSRP_AIX_FORMAT:
658 case VIOSRP_LINUX_FORMAT:
659 case VIOSRP_INLINE_FORMAT:
660 eprintk("Unsupported format %u\n", crq->format);
661 break;
662 default:
663 eprintk("Unknown format %u\n", crq->format);
664 }
665 break;
666 default:
667 eprintk("unknown message type 0x%02x!?\n", crq->valid);
668 }
669}
670
671static inline struct viosrp_crq *next_crq(struct crq_queue *queue)
672{
673 struct viosrp_crq *crq;
674 unsigned long flags;
675
676 spin_lock_irqsave(&queue->lock, flags);
677 crq = &queue->msgs[queue->cur];
678 if (crq->valid & 0x80) {
679 if (++queue->cur == queue->size)
680 queue->cur = 0;
681 } else
682 crq = NULL;
683 spin_unlock_irqrestore(&queue->lock, flags);
684
685 return crq;
686}
687
688static void handle_crq(void *data)
689{
690 struct srp_target *target = (struct srp_target *) data;
691 struct vio_port *vport = target_to_port(target);
692 struct viosrp_crq *crq;
693 int done = 0;
694
695 while (!done) {
696 while ((crq = next_crq(&vport->crq_queue)) != NULL) {
697 process_crq(crq, target);
698 crq->valid = 0x00;
699 }
700
701 vio_enable_interrupts(vport->dma_dev);
702
703 crq = next_crq(&vport->crq_queue);
704 if (crq) {
705 vio_disable_interrupts(vport->dma_dev);
706 process_crq(crq, target);
707 crq->valid = 0x00;
708 } else
709 done = 1;
710 }
711
712 handle_cmd_queue(target);
713}
714
715
716static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc)
717{
718 unsigned long flags;
719 struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
720 struct srp_target *target = iue->target;
721
722 dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
723
724 spin_lock_irqsave(&target->lock, flags);
725 list_del(&iue->ilist);
726 spin_unlock_irqrestore(&target->lock, flags);
727
728 srp_iu_put(iue);
729
730 return 0;
731}
732
733static int ibmvstgt_tsk_mgmt_response(u64 mid, int result)
734{
735 struct iu_entry *iue = (struct iu_entry *) ((void *) mid);
736 union viosrp_iu *iu = vio_iu(iue);
737 unsigned char status, asc;
738
739 eprintk("%p %d\n", iue, result);
740 status = NO_SENSE;
741 asc = 0;
742
743 switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
744 case SRP_TSK_ABORT_TASK:
745 asc = 0x14;
746 if (result)
747 status = ABORTED_COMMAND;
748 break;
749 default:
750 break;
751 }
752
753 send_rsp(iue, NULL, status, asc);
754 srp_iu_put(iue);
755
756 return 0;
757}
758
759static ssize_t system_id_show(struct class_device *cdev, char *buf)
760{
761 return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
762}
763
764static ssize_t partition_number_show(struct class_device *cdev, char *buf)
765{
766 return snprintf(buf, PAGE_SIZE, "%x\n", partition_number);
767}
768
769static ssize_t unit_address_show(struct class_device *cdev, char *buf)
770{
771 struct Scsi_Host *shost = class_to_shost(cdev);
772 struct srp_target *target = host_to_srp_target(shost);
773 struct vio_port *vport = target_to_port(target);
774 return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address);
775}
776
777static CLASS_DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
778static CLASS_DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
779static CLASS_DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
780
781static struct class_device_attribute *ibmvstgt_attrs[] = {
782 &class_device_attr_system_id,
783 &class_device_attr_partition_number,
784 &class_device_attr_unit_address,
785 NULL,
786};
787
788static struct scsi_host_template ibmvstgt_sht = {
789 .name = TGT_NAME,
790 .module = THIS_MODULE,
791 .can_queue = INITIAL_SRP_LIMIT,
792 .sg_tablesize = SG_ALL,
793 .use_clustering = DISABLE_CLUSTERING,
794 .max_sectors = DEFAULT_MAX_SECTORS,
795 .transfer_response = ibmvstgt_cmd_done,
796 .transfer_data = ibmvstgt_transfer_data,
797 .eh_abort_handler = ibmvstgt_eh_abort_handler,
798 .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response,
799 .shost_attrs = ibmvstgt_attrs,
800 .proc_name = TGT_NAME,
801};
802
803static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
804{
805 struct Scsi_Host *shost;
806 struct srp_target *target;
807 struct vio_port *vport;
808 unsigned int *dma, dma_size;
809 int err = -ENOMEM;
810
811 vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL);
812 if (!vport)
813 return err;
814 shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target));
815 if (!shost)
816 goto free_vport;
817 err = scsi_tgt_alloc_queue(shost);
818 if (err)
819 goto put_host;
820
821 target = host_to_srp_target(shost);
822 target->shost = shost;
823 vport->dma_dev = dev;
824 target->ldata = vport;
825 err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT,
826 SRP_MAX_IU_LEN);
827 if (err)
828 goto put_host;
829
830 dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window",
831 &dma_size);
832 if (!dma || dma_size != 40) {
833 eprintk("Couldn't get window property %d\n", dma_size);
834 err = -EIO;
835 goto free_srp_target;
836 }
837 vport->liobn = dma[0];
838 vport->riobn = dma[5];
839
840 INIT_WORK(&vport->crq_work, handle_crq, target);
841
842 err = crq_queue_create(&vport->crq_queue, target);
843 if (err)
844 goto free_srp_target;
845
846 err = scsi_add_host(shost, target->dev);
847 if (err)
848 goto destroy_queue;
849 return 0;
850
851destroy_queue:
852 crq_queue_destroy(target);
853free_srp_target:
854 srp_target_free(target);
855put_host:
856 scsi_host_put(shost);
857free_vport:
858 kfree(vport);
859 return err;
860}
861
862static int ibmvstgt_remove(struct vio_dev *dev)
863{
864 struct srp_target *target = (struct srp_target *) dev->dev.driver_data;
865 struct Scsi_Host *shost = target->shost;
866 struct vio_port *vport = target->ldata;
867
868 crq_queue_destroy(target);
869 scsi_remove_host(shost);
870 scsi_tgt_free_queue(shost);
871 srp_target_free(target);
872 kfree(vport);
873 scsi_host_put(shost);
874 return 0;
875}
876
877static struct vio_device_id ibmvstgt_device_table[] __devinitdata = {
878 {"v-scsi-host", "IBM,v-scsi-host"},
879 {"",""}
880};
881
882MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table);
883
884static struct vio_driver ibmvstgt_driver = {
885 .id_table = ibmvstgt_device_table,
886 .probe = ibmvstgt_probe,
887 .remove = ibmvstgt_remove,
888 .driver = {
889 .name = "ibmvscsis",
890 .owner = THIS_MODULE,
891 }
892};
893
894static int get_system_info(void)
895{
896 struct device_node *rootdn;
897 const char *id, *model, *name;
898 unsigned int *num;
899
900 rootdn = find_path_device("/");
901 if (!rootdn)
902 return -ENOENT;
903
904 model = get_property(rootdn, "model", NULL);
905 id = get_property(rootdn, "system-id", NULL);
906 if (model && id)
907 snprintf(system_id, sizeof(system_id), "%s-%s", model, id);
908
909 name = get_property(rootdn, "ibm,partition-name", NULL);
910 if (name)
911 strncpy(partition_name, name, sizeof(partition_name));
912
913 num = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL);
914 if (num)
915 partition_number = *num;
916
917 return 0;
918}
919
920static int ibmvstgt_init(void)
921{
922 int err = -ENOMEM;
923
924 printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n");
925
926 vtgtd = create_workqueue("ibmvtgtd");
927 if (!vtgtd)
928 return err;
929
930 err = get_system_info();
931 if (err)
932 goto destroy_wq;
933
934 err = vio_register_driver(&ibmvstgt_driver);
935 if (err)
936 goto destroy_wq;
937
938 return 0;
939
940destroy_wq:
941 destroy_workqueue(vtgtd);
942 return err;
943}
944
945static void ibmvstgt_exit(void)
946{
947 printk("Unregister IBM virtual SCSI driver\n");
948
949 destroy_workqueue(vtgtd);
950 vio_unregister_driver(&ibmvstgt_driver);
951}
952
953MODULE_DESCRIPTION("IBM Virtual SCSI Target");
954MODULE_AUTHOR("Santiago Leon");
955MODULE_LICENSE("GPL");
956
957module_init(ibmvstgt_init);
958module_exit(ibmvstgt_exit);