aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/Makefile2
-rw-r--r--drivers/s390/scsi/zfcp_aux.c425
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c259
-rw-r--r--drivers/s390/scsi/zfcp_def.h43
-rw-r--r--drivers/s390/scsi/zfcp_ext.h8
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c246
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h12
7 files changed, 331 insertions, 664 deletions
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile
index f775f9e6030c..c0fa8ffe5448 100644
--- a/drivers/s390/scsi/Makefile
+++ b/drivers/s390/scsi/Makefile
@@ -4,6 +4,6 @@
4 4
5zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \ 5zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
6 zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \ 6 zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
7 zfcp_sysfs_unit.o zfcp_sysfs_driver.o zfcp_fc.o 7 zfcp_sysfs_unit.o zfcp_sysfs_driver.o zfcp_fc.o zfcp_cfdc.o
8 8
9obj-$(CONFIG_ZFCP) += zfcp.o 9obj-$(CONFIG_ZFCP) += zfcp.o
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 9eb8827e19e2..735f7af43d6a 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -33,6 +33,7 @@
33 * Ralph Wuerthner 33 * Ralph Wuerthner
34 */ 34 */
35 35
36#include <linux/miscdevice.h>
36#include "zfcp_ext.h" 37#include "zfcp_ext.h"
37 38
38/* accumulated log level (module parameter) */ 39/* accumulated log level (module parameter) */
@@ -43,33 +44,6 @@ static char *device;
43/* written against the module interface */ 44/* written against the module interface */
44static int __init zfcp_module_init(void); 45static int __init zfcp_module_init(void);
45 46
46/* miscellaneous */
47static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
48static void zfcp_sg_list_free(struct zfcp_sg_list *);
49static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
50 void __user *, size_t);
51static int zfcp_sg_list_copy_to_user(void __user *,
52 struct zfcp_sg_list *, size_t);
53static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long);
54
55#define ZFCP_CFDC_IOC_MAGIC 0xDD
56#define ZFCP_CFDC_IOC \
57 _IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)
58
59
60static const struct file_operations zfcp_cfdc_fops = {
61 .unlocked_ioctl = zfcp_cfdc_dev_ioctl,
62#ifdef CONFIG_COMPAT
63 .compat_ioctl = zfcp_cfdc_dev_ioctl
64#endif
65};
66
67static struct miscdevice zfcp_cfdc_misc = {
68 .minor = ZFCP_CFDC_DEV_MINOR,
69 .name = ZFCP_CFDC_DEV_NAME,
70 .fops = &zfcp_cfdc_fops
71};
72
73/*********************** KERNEL/MODULE PARAMETERS ***************************/ 47/*********************** KERNEL/MODULE PARAMETERS ***************************/
74 48
75/* declare driver module init/cleanup functions */ 49/* declare driver module init/cleanup functions */
@@ -294,9 +268,6 @@ zfcp_module_init(void)
294 goto out_misc; 268 goto out_misc;
295 } 269 }
296 270
297 ZFCP_LOG_TRACE("major/minor for zfcp_cfdc: %d/%d\n",
298 ZFCP_CFDC_DEV_MAJOR, zfcp_cfdc_misc.minor);
299
300 /* Initialise proc semaphores */ 271 /* Initialise proc semaphores */
301 sema_init(&zfcp_data.config_sema, 1); 272 sema_init(&zfcp_data.config_sema, 1);
302 273
@@ -329,372 +300,6 @@ zfcp_module_init(void)
329 return retval; 300 return retval;
330} 301}
331 302
332/*
333 * function: zfcp_cfdc_dev_ioctl
334 *
335 * purpose: Handle control file upload/download transaction via IOCTL
336 * interface
337 *
338 * returns: 0 - Operation completed successfuly
339 * -ENOTTY - Unknown IOCTL command
340 * -EINVAL - Invalid sense data record
341 * -ENXIO - The FCP adapter is not available
342 * -EOPNOTSUPP - The FCP adapter does not have CFDC support
343 * -ENOMEM - Insufficient memory
344 * -EFAULT - User space memory I/O operation fault
345 * -EPERM - Cannot create or queue FSF request or create SBALs
346 * -ERESTARTSYS- Received signal (is mapped to EAGAIN by VFS)
347 */
348static long
349zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
350 unsigned long buffer)
351{
352 struct zfcp_cfdc_sense_data *sense_data, __user *sense_data_user;
353 struct zfcp_adapter *adapter = NULL;
354 struct zfcp_fsf_req *fsf_req = NULL;
355 struct zfcp_sg_list *sg_list = NULL;
356 u32 fsf_command, option;
357 char *bus_id = NULL;
358 int retval = 0;
359
360 sense_data = kmalloc(sizeof(struct zfcp_cfdc_sense_data), GFP_KERNEL);
361 if (sense_data == NULL) {
362 retval = -ENOMEM;
363 goto out;
364 }
365
366 sg_list = kzalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
367 if (sg_list == NULL) {
368 retval = -ENOMEM;
369 goto out;
370 }
371
372 if (command != ZFCP_CFDC_IOC) {
373 ZFCP_LOG_INFO("IOC request code 0x%x invalid\n", command);
374 retval = -ENOTTY;
375 goto out;
376 }
377
378 if ((sense_data_user = (void __user *) buffer) == NULL) {
379 ZFCP_LOG_INFO("sense data record is required\n");
380 retval = -EINVAL;
381 goto out;
382 }
383
384 retval = copy_from_user(sense_data, sense_data_user,
385 sizeof(struct zfcp_cfdc_sense_data));
386 if (retval) {
387 retval = -EFAULT;
388 goto out;
389 }
390
391 if (sense_data->signature != ZFCP_CFDC_SIGNATURE) {
392 ZFCP_LOG_INFO("invalid sense data request signature 0x%08x\n",
393 ZFCP_CFDC_SIGNATURE);
394 retval = -EINVAL;
395 goto out;
396 }
397
398 switch (sense_data->command) {
399
400 case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL:
401 fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
402 option = FSF_CFDC_OPTION_NORMAL_MODE;
403 break;
404
405 case ZFCP_CFDC_CMND_DOWNLOAD_FORCE:
406 fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
407 option = FSF_CFDC_OPTION_FORCE;
408 break;
409
410 case ZFCP_CFDC_CMND_FULL_ACCESS:
411 fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
412 option = FSF_CFDC_OPTION_FULL_ACCESS;
413 break;
414
415 case ZFCP_CFDC_CMND_RESTRICTED_ACCESS:
416 fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
417 option = FSF_CFDC_OPTION_RESTRICTED_ACCESS;
418 break;
419
420 case ZFCP_CFDC_CMND_UPLOAD:
421 fsf_command = FSF_QTCB_UPLOAD_CONTROL_FILE;
422 option = 0;
423 break;
424
425 default:
426 ZFCP_LOG_INFO("invalid command code 0x%08x\n",
427 sense_data->command);
428 retval = -EINVAL;
429 goto out;
430 }
431
432 bus_id = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
433 if (bus_id == NULL) {
434 retval = -ENOMEM;
435 goto out;
436 }
437 snprintf(bus_id, BUS_ID_SIZE, "%d.%d.%04x",
438 (sense_data->devno >> 24),
439 (sense_data->devno >> 16) & 0xFF,
440 (sense_data->devno & 0xFFFF));
441
442 read_lock_irq(&zfcp_data.config_lock);
443 adapter = zfcp_get_adapter_by_busid(bus_id);
444 if (adapter)
445 zfcp_adapter_get(adapter);
446 read_unlock_irq(&zfcp_data.config_lock);
447
448 kfree(bus_id);
449
450 if (adapter == NULL) {
451 ZFCP_LOG_INFO("invalid adapter\n");
452 retval = -ENXIO;
453 goto out;
454 }
455
456 if (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE) {
457 retval = zfcp_sg_list_alloc(sg_list,
458 ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
459 if (retval) {
460 retval = -ENOMEM;
461 goto out;
462 }
463 }
464
465 if ((sense_data->command & ZFCP_CFDC_DOWNLOAD) &&
466 (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE)) {
467 retval = zfcp_sg_list_copy_from_user(
468 sg_list, &sense_data_user->control_file,
469 ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
470 if (retval) {
471 retval = -EFAULT;
472 goto out;
473 }
474 }
475
476 retval = zfcp_fsf_control_file(adapter, &fsf_req, fsf_command,
477 option, sg_list);
478 if (retval)
479 goto out;
480
481 if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
482 (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
483 retval = -ENXIO;
484 goto out;
485 }
486
487 sense_data->fsf_status = fsf_req->qtcb->header.fsf_status;
488 memcpy(&sense_data->fsf_status_qual,
489 &fsf_req->qtcb->header.fsf_status_qual,
490 sizeof(union fsf_status_qual));
491 memcpy(&sense_data->payloads, &fsf_req->qtcb->bottom.support.els, 256);
492
493 retval = copy_to_user(sense_data_user, sense_data,
494 sizeof(struct zfcp_cfdc_sense_data));
495 if (retval) {
496 retval = -EFAULT;
497 goto out;
498 }
499
500 if (sense_data->command & ZFCP_CFDC_UPLOAD) {
501 retval = zfcp_sg_list_copy_to_user(
502 &sense_data_user->control_file, sg_list,
503 ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);
504 if (retval) {
505 retval = -EFAULT;
506 goto out;
507 }
508 }
509
510 out:
511 if (fsf_req != NULL)
512 zfcp_fsf_req_free(fsf_req);
513
514 if ((adapter != NULL) && (retval != -ENXIO))
515 zfcp_adapter_put(adapter);
516
517 if (sg_list != NULL) {
518 zfcp_sg_list_free(sg_list);
519 kfree(sg_list);
520 }
521
522 kfree(sense_data);
523
524 return retval;
525}
526
527
528/**
529 * zfcp_sg_list_alloc - create a scatter-gather list of the specified size
530 * @sg_list: structure describing a scatter gather list
531 * @size: size of scatter-gather list
532 * Return: 0 on success, else -ENOMEM
533 *
534 * In sg_list->sg a pointer to the created scatter-gather list is returned,
535 * or NULL if we run out of memory. sg_list->count specifies the number of
536 * elements of the scatter-gather list. The maximum size of a single element
537 * in the scatter-gather list is PAGE_SIZE.
538 */
539static int
540zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
541{
542 struct scatterlist *sg;
543 unsigned int i;
544 int retval = 0;
545 void *address;
546
547 BUG_ON(sg_list == NULL);
548
549 sg_list->count = size >> PAGE_SHIFT;
550 if (size & ~PAGE_MASK)
551 sg_list->count++;
552 sg_list->sg = kcalloc(sg_list->count, sizeof(struct scatterlist),
553 GFP_KERNEL);
554 if (sg_list->sg == NULL) {
555 sg_list->count = 0;
556 retval = -ENOMEM;
557 goto out;
558 }
559 sg_init_table(sg_list->sg, sg_list->count);
560
561 for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
562 address = (void *) get_zeroed_page(GFP_KERNEL);
563 if (address == NULL) {
564 sg_list->count = i;
565 zfcp_sg_list_free(sg_list);
566 retval = -ENOMEM;
567 goto out;
568 }
569 zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE));
570 size -= sg->length;
571 }
572
573 out:
574 return retval;
575}
576
577
578/**
579 * zfcp_sg_list_free - free memory of a scatter-gather list
580 * @sg_list: structure describing a scatter-gather list
581 *
582 * Memory for each element in the scatter-gather list is freed.
583 * Finally sg_list->sg is freed itself and sg_list->count is reset.
584 */
585static void
586zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
587{
588 struct scatterlist *sg;
589 unsigned int i;
590
591 BUG_ON(sg_list == NULL);
592
593 for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++)
594 free_page((unsigned long) zfcp_sg_to_address(sg));
595
596 sg_list->count = 0;
597 kfree(sg_list->sg);
598}
599
600/**
601 * zfcp_sg_size - determine size of a scatter-gather list
602 * @sg: array of (struct scatterlist)
603 * @sg_count: elements in array
604 * Return: size of entire scatter-gather list
605 */
606static size_t zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
607{
608 unsigned int i;
609 struct scatterlist *p;
610 size_t size;
611
612 size = 0;
613 for (i = 0, p = sg; i < sg_count; i++, p++) {
614 BUG_ON(p == NULL);
615 size += p->length;
616 }
617
618 return size;
619}
620
621
622/**
623 * zfcp_sg_list_copy_from_user -copy data from user space to scatter-gather list
624 * @sg_list: structure describing a scatter-gather list
625 * @user_buffer: pointer to buffer in user space
626 * @size: number of bytes to be copied
627 * Return: 0 on success, -EFAULT if copy_from_user fails.
628 */
629static int
630zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
631 void __user *user_buffer,
632 size_t size)
633{
634 struct scatterlist *sg;
635 unsigned int length;
636 void *zfcp_buffer;
637 int retval = 0;
638
639 BUG_ON(sg_list == NULL);
640
641 if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
642 return -EFAULT;
643
644 for (sg = sg_list->sg; size > 0; sg++) {
645 length = min((unsigned int)size, sg->length);
646 zfcp_buffer = zfcp_sg_to_address(sg);
647 if (copy_from_user(zfcp_buffer, user_buffer, length)) {
648 retval = -EFAULT;
649 goto out;
650 }
651 user_buffer += length;
652 size -= length;
653 }
654
655 out:
656 return retval;
657}
658
659
660/**
661 * zfcp_sg_list_copy_to_user - copy data from scatter-gather list to user space
662 * @user_buffer: pointer to buffer in user space
663 * @sg_list: structure describing a scatter-gather list
664 * @size: number of bytes to be copied
665 * Return: 0 on success, -EFAULT if copy_to_user fails
666 */
667static int
668zfcp_sg_list_copy_to_user(void __user *user_buffer,
669 struct zfcp_sg_list *sg_list,
670 size_t size)
671{
672 struct scatterlist *sg;
673 unsigned int length;
674 void *zfcp_buffer;
675 int retval = 0;
676
677 BUG_ON(sg_list == NULL);
678
679 if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
680 return -EFAULT;
681
682 for (sg = sg_list->sg; size > 0; sg++) {
683 length = min((unsigned int) size, sg->length);
684 zfcp_buffer = zfcp_sg_to_address(sg);
685 if (copy_to_user(user_buffer, zfcp_buffer, length)) {
686 retval = -EFAULT;
687 goto out;
688 }
689 user_buffer += length;
690 size -= length;
691 }
692
693 out:
694 return retval;
695}
696
697
698#undef ZFCP_LOG_AREA 303#undef ZFCP_LOG_AREA
699 304
700/****************************************************************/ 305/****************************************************************/
@@ -1345,4 +950,32 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
1345 return 0; 950 return 0;
1346} 951}
1347 952
953void zfcp_sg_free_table(struct scatterlist *sg, int count)
954{
955 int i;
956
957 for (i = 0; i < count; i++, sg++)
958 if (sg)
959 free_page((unsigned long) sg_virt(sg));
960 else
961 break;
962}
963
964int zfcp_sg_setup_table(struct scatterlist *sg, int count)
965{
966 void *addr;
967 int i;
968
969 sg_init_table(sg, count);
970 for (i = 0; i < count; i++, sg++) {
971 addr = (void *) get_zeroed_page(GFP_KERNEL);
972 if (!addr) {
973 zfcp_sg_free_table(sg, i);
974 return -ENOMEM;
975 }
976 sg_set_buf(sg, addr, PAGE_SIZE);
977 }
978 return 0;
979}
980
1348#undef ZFCP_LOG_AREA 981#undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
new file mode 100644
index 000000000000..ec2abceca6dc
--- /dev/null
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -0,0 +1,259 @@
1/*
2 * zfcp device driver
3 *
4 * Userspace interface for accessing the
5 * Access Control Lists / Control File Data Channel
6 *
7 * Copyright IBM Corporation 2008
8 */
9
10#include <linux/types.h>
11#include <linux/miscdevice.h>
12#include <asm/ccwdev.h>
13#include "zfcp_def.h"
14#include "zfcp_ext.h"
15#include "zfcp_fsf.h"
16
17#define ZFCP_CFDC_CMND_DOWNLOAD_NORMAL 0x00010001
18#define ZFCP_CFDC_CMND_DOWNLOAD_FORCE 0x00010101
19#define ZFCP_CFDC_CMND_FULL_ACCESS 0x00000201
20#define ZFCP_CFDC_CMND_RESTRICTED_ACCESS 0x00000401
21#define ZFCP_CFDC_CMND_UPLOAD 0x00010002
22
23#define ZFCP_CFDC_DOWNLOAD 0x00000001
24#define ZFCP_CFDC_UPLOAD 0x00000002
25#define ZFCP_CFDC_WITH_CONTROL_FILE 0x00010000
26
27#define ZFCP_CFDC_IOC_MAGIC 0xDD
28#define ZFCP_CFDC_IOC \
29 _IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_data)
30
31/**
32 * struct zfcp_cfdc_data - data for ioctl cfdc interface
33 * @signature: request signature
34 * @devno: FCP adapter device number
35 * @command: command code
36 * @fsf_status: returns status of FSF command to userspace
37 * @fsf_status_qual: returned to userspace
38 * @payloads: access conflicts list
39 * @control_file: access control table
40 */
41struct zfcp_cfdc_data {
42 u32 signature;
43 u32 devno;
44 u32 command;
45 u32 fsf_status;
46 u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
47 u8 payloads[256];
48 u8 control_file[0];
49};
50
51static int zfcp_cfdc_copy_from_user(struct scatterlist *sg,
52 void __user *user_buffer)
53{
54 unsigned int length;
55 unsigned int size = ZFCP_CFDC_MAX_SIZE;
56
57 while (size) {
58 length = min((unsigned int)size, sg->length);
59 if (copy_from_user(sg_virt(sg++), user_buffer, length))
60 return -EFAULT;
61 user_buffer += length;
62 size -= length;
63 }
64 return 0;
65}
66
67static int zfcp_cfdc_copy_to_user(void __user *user_buffer,
68 struct scatterlist *sg)
69{
70 unsigned int length;
71 unsigned int size = ZFCP_CFDC_MAX_SIZE;
72
73 while (size) {
74 length = min((unsigned int) size, sg->length);
75 if (copy_to_user(user_buffer, sg_virt(sg++), length))
76 return -EFAULT;
77 user_buffer += length;
78 size -= length;
79 }
80 return 0;
81}
82
83static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno)
84{
85 struct zfcp_adapter *adapter = NULL, *cur_adapter;
86 struct ccw_dev_id dev_id;
87
88 read_lock_irq(&zfcp_data.config_lock);
89 list_for_each_entry(cur_adapter, &zfcp_data.adapter_list_head, list) {
90 ccw_device_get_id(cur_adapter->ccw_device, &dev_id);
91 if (dev_id.devno == devno) {
92 adapter = cur_adapter;
93 zfcp_adapter_get(adapter);
94 break;
95 }
96 }
97 read_unlock_irq(&zfcp_data.config_lock);
98 return adapter;
99}
100
101static int zfcp_cfdc_set_fsf(struct zfcp_fsf_cfdc *fsf_cfdc, int command)
102{
103 switch (command) {
104 case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL:
105 fsf_cfdc->command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
106 fsf_cfdc->option = FSF_CFDC_OPTION_NORMAL_MODE;
107 break;
108 case ZFCP_CFDC_CMND_DOWNLOAD_FORCE:
109 fsf_cfdc->command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
110 fsf_cfdc->option = FSF_CFDC_OPTION_FORCE;
111 break;
112 case ZFCP_CFDC_CMND_FULL_ACCESS:
113 fsf_cfdc->command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
114 fsf_cfdc->option = FSF_CFDC_OPTION_FULL_ACCESS;
115 break;
116 case ZFCP_CFDC_CMND_RESTRICTED_ACCESS:
117 fsf_cfdc->command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;
118 fsf_cfdc->option = FSF_CFDC_OPTION_RESTRICTED_ACCESS;
119 break;
120 case ZFCP_CFDC_CMND_UPLOAD:
121 fsf_cfdc->command = FSF_QTCB_UPLOAD_CONTROL_FILE;
122 fsf_cfdc->option = 0;
123 break;
124 default:
125 return -EINVAL;
126 }
127
128 return 0;
129}
130
131static int zfcp_cfdc_sg_setup(int command, struct scatterlist *sg,
132 u8 __user *control_file)
133{
134 int retval;
135 retval = zfcp_sg_setup_table(sg, ZFCP_CFDC_PAGES);
136 if (retval)
137 return retval;
138
139 sg[ZFCP_CFDC_PAGES - 1].length = ZFCP_CFDC_MAX_SIZE % PAGE_SIZE;
140
141 if (command & ZFCP_CFDC_WITH_CONTROL_FILE &&
142 command & ZFCP_CFDC_DOWNLOAD) {
143 retval = zfcp_cfdc_copy_from_user(sg, control_file);
144 if (retval) {
145 zfcp_sg_free_table(sg, ZFCP_CFDC_PAGES);
146 return -EFAULT;
147 }
148 }
149
150 return 0;
151}
152
153static void zfcp_cfdc_req_to_sense(struct zfcp_cfdc_data *data,
154 struct zfcp_fsf_req *req)
155{
156 data->fsf_status = req->qtcb->header.fsf_status;
157 memcpy(&data->fsf_status_qual, &req->qtcb->header.fsf_status_qual,
158 sizeof(union fsf_status_qual));
159 memcpy(&data->payloads, &req->qtcb->bottom.support.els,
160 sizeof(req->qtcb->bottom.support.els));
161}
162
163static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
164 unsigned long buffer)
165{
166 struct zfcp_cfdc_data *data;
167 struct zfcp_cfdc_data __user *data_user;
168 struct zfcp_adapter *adapter;
169 struct zfcp_fsf_req *req;
170 struct zfcp_fsf_cfdc *fsf_cfdc;
171 int retval;
172
173 if (command != ZFCP_CFDC_IOC)
174 return -ENOTTY;
175
176 data_user = (void __user *) buffer;
177 if (!data_user)
178 return -EINVAL;
179
180 fsf_cfdc = kmalloc(sizeof(struct zfcp_fsf_cfdc), GFP_KERNEL);
181 if (!fsf_cfdc)
182 return -ENOMEM;
183
184 data = kmalloc(sizeof(struct zfcp_cfdc_data), GFP_KERNEL);
185 if (!data) {
186 retval = -ENOMEM;
187 goto no_mem_sense;
188 }
189
190 retval = copy_from_user(data, data_user, sizeof(*data));
191 if (retval) {
192 retval = -EFAULT;
193 goto free_buffer;
194 }
195
196 if (data->signature != 0xCFDCACDF) {
197 retval = -EINVAL;
198 goto free_buffer;
199 }
200
201 retval = zfcp_cfdc_set_fsf(fsf_cfdc, data->command);
202
203 adapter = zfcp_cfdc_get_adapter(data->devno);
204 if (!adapter) {
205 retval = -ENXIO;
206 goto free_buffer;
207 }
208
209 retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg,
210 data_user->control_file);
211 if (retval)
212 goto adapter_put;
213 req = zfcp_fsf_control_file(adapter, fsf_cfdc);
214 if (IS_ERR(req)) {
215 retval = PTR_ERR(req);
216 goto free_sg;
217 }
218
219 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
220 retval = -ENXIO;
221 goto free_fsf;
222 }
223
224 zfcp_cfdc_req_to_sense(data, req);
225 retval = copy_to_user(data_user, data, sizeof(*data_user));
226 if (retval) {
227 retval = -EFAULT;
228 goto free_fsf;
229 }
230
231 if (data->command & ZFCP_CFDC_UPLOAD)
232 retval = zfcp_cfdc_copy_to_user(&data_user->control_file,
233 fsf_cfdc->sg);
234
235 free_fsf:
236 zfcp_fsf_req_free(req);
237 free_sg:
238 zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES);
239 adapter_put:
240 zfcp_adapter_put(adapter);
241 free_buffer:
242 kfree(data);
243 no_mem_sense:
244 kfree(fsf_cfdc);
245 return retval;
246}
247
248static const struct file_operations zfcp_cfdc_fops = {
249 .unlocked_ioctl = zfcp_cfdc_dev_ioctl,
250#ifdef CONFIG_COMPAT
251 .compat_ioctl = zfcp_cfdc_dev_ioctl
252#endif
253};
254
255struct miscdevice zfcp_cfdc_misc = {
256 .minor = MISC_DYNAMIC_MINOR,
257 .name = "zfcp_cfdc",
258 .fops = &zfcp_cfdc_fops,
259};
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d23c3b9b283e..72f225817ebd 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -26,7 +26,6 @@
26 26
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/moduleparam.h> 28#include <linux/moduleparam.h>
29#include <linux/miscdevice.h>
30#include <linux/major.h> 29#include <linux/major.h>
31#include <linux/blkdev.h> 30#include <linux/blkdev.h>
32#include <linux/delay.h> 31#include <linux/delay.h>
@@ -534,38 +533,6 @@ do { \
534#define ZFCP_ERP_DISMISSED 0x4 533#define ZFCP_ERP_DISMISSED 0x4
535#define ZFCP_ERP_NOMEM 0x5 534#define ZFCP_ERP_NOMEM 0x5
536 535
537
538/******************** CFDC SPECIFIC STUFF *****************************/
539
540/* Firewall data channel sense data record */
541struct zfcp_cfdc_sense_data {
542 u32 signature; /* Request signature */
543 u32 devno; /* FCP adapter device number */
544 u32 command; /* Command code */
545 u32 fsf_status; /* FSF request status and status qualifier */
546 u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
547 u8 payloads[256]; /* Access conflicts list */
548 u8 control_file[0]; /* Access control table */
549};
550
551#define ZFCP_CFDC_SIGNATURE 0xCFDCACDF
552
553#define ZFCP_CFDC_CMND_DOWNLOAD_NORMAL 0x00010001
554#define ZFCP_CFDC_CMND_DOWNLOAD_FORCE 0x00010101
555#define ZFCP_CFDC_CMND_FULL_ACCESS 0x00000201
556#define ZFCP_CFDC_CMND_RESTRICTED_ACCESS 0x00000401
557#define ZFCP_CFDC_CMND_UPLOAD 0x00010002
558
559#define ZFCP_CFDC_DOWNLOAD 0x00000001
560#define ZFCP_CFDC_UPLOAD 0x00000002
561#define ZFCP_CFDC_WITH_CONTROL_FILE 0x00010000
562
563#define ZFCP_CFDC_DEV_NAME "zfcp_cfdc"
564#define ZFCP_CFDC_DEV_MAJOR MISC_MAJOR
565#define ZFCP_CFDC_DEV_MINOR MISC_DYNAMIC_MINOR
566
567#define ZFCP_CFDC_MAX_CONTROL_FILE_SIZE 127 * 1024
568
569/************************* STRUCTURE DEFINITIONS *****************************/ 536/************************* STRUCTURE DEFINITIONS *****************************/
570 537
571struct zfcp_fsf_req; 538struct zfcp_fsf_req;
@@ -897,16 +864,6 @@ struct zfcp_data {
897 struct kmem_cache *gid_pn_cache; 864 struct kmem_cache *gid_pn_cache;
898}; 865};
899 866
900/**
901 * struct zfcp_sg_list - struct describing a scatter-gather list
902 * @sg: pointer to array of (struct scatterlist)
903 * @count: number of elements in scatter-gather list
904 */
905struct zfcp_sg_list {
906 struct scatterlist *sg;
907 unsigned int count;
908};
909
910/* number of elements for various memory pools */ 867/* number of elements for various memory pools */
911#define ZFCP_POOL_FSF_REQ_ERP_NR 1 868#define ZFCP_POOL_FSF_REQ_ERP_NR 1
912#define ZFCP_POOL_FSF_REQ_SCSI_NR 1 869#define ZFCP_POOL_FSF_REQ_SCSI_NR 1
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 91d58843205c..867972898cb1 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -86,8 +86,8 @@ extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *,
86extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *); 86extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *);
87extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *, 87extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *,
88 struct fsf_qtcb_bottom_port *); 88 struct fsf_qtcb_bottom_port *);
89extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, 89extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
90 u32, u32, struct zfcp_sg_list *); 90 struct zfcp_fsf_cfdc *fsf_cfdc);
91extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); 91extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
92extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); 92extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
93extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); 93extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
@@ -167,6 +167,8 @@ extern void zfcp_erp_port_access_changed(struct zfcp_port *, u8, void *);
167extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *); 167extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *);
168 168
169/******************************** AUX ****************************************/ 169/******************************** AUX ****************************************/
170extern void zfcp_sg_free_table(struct scatterlist *sg, int count);
171extern int zfcp_sg_setup_table(struct scatterlist *sg, int count);
170extern void zfcp_rec_dbf_event_thread(u8 id, struct zfcp_adapter *adapter); 172extern void zfcp_rec_dbf_event_thread(u8 id, struct zfcp_adapter *adapter);
171extern void zfcp_rec_dbf_event_thread_lock(u8 id, struct zfcp_adapter *adapter); 173extern void zfcp_rec_dbf_event_thread_lock(u8 id, struct zfcp_adapter *adapter);
172extern void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *); 174extern void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *);
@@ -200,4 +202,6 @@ extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
200 struct scsi_cmnd *); 202 struct scsi_cmnd *);
201extern int zfcp_reqlist_isempty(struct zfcp_adapter *); 203extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
202 204
205extern struct miscdevice zfcp_cfdc_misc;
206
203#endif /* ZFCP_EXT_H */ 207#endif /* ZFCP_EXT_H */
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 8568b6f3f27c..de42a01fc4b1 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -36,7 +36,7 @@ static int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *);
36static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *); 36static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *);
37static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *); 37static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *);
38static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *); 38static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *);
39static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *); 39static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *);
40static inline int zfcp_fsf_req_sbal_check( 40static inline int zfcp_fsf_req_sbal_check(
41 unsigned long *, struct zfcp_qdio_queue *, int); 41 unsigned long *, struct zfcp_qdio_queue *, int);
42static inline int zfcp_use_one_sbal( 42static inline int zfcp_use_one_sbal(
@@ -4183,53 +4183,35 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
4183 * -ENOMEM - Insufficient memory 4183 * -ENOMEM - Insufficient memory
4184 * -EPERM - Cannot create FSF request or place it in QDIO queue 4184 * -EPERM - Cannot create FSF request or place it in QDIO queue
4185 */ 4185 */
4186int 4186struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
4187zfcp_fsf_control_file(struct zfcp_adapter *adapter, 4187 struct zfcp_fsf_cfdc *fsf_cfdc)
4188 struct zfcp_fsf_req **fsf_req_ptr,
4189 u32 fsf_command,
4190 u32 option,
4191 struct zfcp_sg_list *sg_list)
4192{ 4188{
4193 struct zfcp_fsf_req *fsf_req; 4189 struct zfcp_fsf_req *fsf_req;
4194 struct fsf_qtcb_bottom_support *bottom; 4190 struct fsf_qtcb_bottom_support *bottom;
4195 volatile struct qdio_buffer_element *sbale; 4191 volatile struct qdio_buffer_element *sbale;
4196 unsigned long lock_flags; 4192 unsigned long lock_flags;
4197 int req_flags = 0;
4198 int direction; 4193 int direction;
4199 int retval = 0; 4194 int retval;
4200 4195 int bytes;
4201 if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) {
4202 ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n",
4203 zfcp_get_busid_by_adapter(adapter));
4204 retval = -EOPNOTSUPP;
4205 goto out;
4206 }
4207 4196
4208 switch (fsf_command) { 4197 if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
4198 return ERR_PTR(-EOPNOTSUPP);
4209 4199
4200 switch (fsf_cfdc->command) {
4210 case FSF_QTCB_DOWNLOAD_CONTROL_FILE: 4201 case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
4211 direction = SBAL_FLAGS0_TYPE_WRITE; 4202 direction = SBAL_FLAGS0_TYPE_WRITE;
4212 if ((option != FSF_CFDC_OPTION_FULL_ACCESS) &&
4213 (option != FSF_CFDC_OPTION_RESTRICTED_ACCESS))
4214 req_flags = ZFCP_WAIT_FOR_SBAL;
4215 break; 4203 break;
4216
4217 case FSF_QTCB_UPLOAD_CONTROL_FILE: 4204 case FSF_QTCB_UPLOAD_CONTROL_FILE:
4218 direction = SBAL_FLAGS0_TYPE_READ; 4205 direction = SBAL_FLAGS0_TYPE_READ;
4219 break; 4206 break;
4220
4221 default: 4207 default:
4222 ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command); 4208 return ERR_PTR(-EINVAL);
4223 retval = -EINVAL;
4224 goto out;
4225 } 4209 }
4226 4210
4227 retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags, 4211 retval = zfcp_fsf_req_create(adapter, fsf_cfdc->command,
4212 ZFCP_WAIT_FOR_SBAL,
4228 NULL, &lock_flags, &fsf_req); 4213 NULL, &lock_flags, &fsf_req);
4229 if (retval < 0) { 4214 if (retval < 0) {
4230 ZFCP_LOG_INFO("error: Could not create FSF request for the "
4231 "adapter %s\n",
4232 zfcp_get_busid_by_adapter(adapter));
4233 retval = -EPERM; 4215 retval = -EPERM;
4234 goto unlock_queue_lock; 4216 goto unlock_queue_lock;
4235 } 4217 }
@@ -4239,220 +4221,40 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
4239 4221
4240 bottom = &fsf_req->qtcb->bottom.support; 4222 bottom = &fsf_req->qtcb->bottom.support;
4241 bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; 4223 bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
4242 bottom->option = option; 4224 bottom->option = fsf_cfdc->option;
4243 4225
4244 if (sg_list->count > 0) { 4226 bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction,
4245 int bytes; 4227 fsf_cfdc->sg, ZFCP_CFDC_PAGES,
4246 4228 ZFCP_MAX_SBALS_PER_REQ);
4247 bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction, 4229 if (bytes != ZFCP_CFDC_MAX_SIZE) {
4248 sg_list->sg, sg_list->count, 4230 retval = -ENOMEM;
4249 ZFCP_MAX_SBALS_PER_REQ); 4231 goto free_fsf_req;
4250 if (bytes != ZFCP_CFDC_MAX_CONTROL_FILE_SIZE) { 4232 }
4251 ZFCP_LOG_INFO(
4252 "error: Could not create sufficient number of "
4253 "SBALS for an FSF request to the adapter %s\n",
4254 zfcp_get_busid_by_adapter(adapter));
4255 retval = -ENOMEM;
4256 goto free_fsf_req;
4257 }
4258 } else
4259 sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
4260 4233
4261 zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); 4234 zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
4262 retval = zfcp_fsf_req_send(fsf_req); 4235 retval = zfcp_fsf_req_send(fsf_req);
4263 if (retval < 0) { 4236 if (retval < 0) {
4264 ZFCP_LOG_INFO("initiation of cfdc up/download failed"
4265 "(adapter %s)\n",
4266 zfcp_get_busid_by_adapter(adapter));
4267 retval = -EPERM; 4237 retval = -EPERM;
4268 goto free_fsf_req; 4238 goto free_fsf_req;
4269 } 4239 }
4270 write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 4240 write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
4271 4241
4272 ZFCP_LOG_NORMAL("Control file %s FSF request has been sent to the "
4273 "adapter %s\n",
4274 fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ?
4275 "download" : "upload",
4276 zfcp_get_busid_by_adapter(adapter));
4277
4278 wait_event(fsf_req->completion_wq, 4242 wait_event(fsf_req->completion_wq,
4279 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); 4243 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
4280 4244
4281 *fsf_req_ptr = fsf_req; 4245 return fsf_req;
4282 goto out;
4283 4246
4284 free_fsf_req: 4247 free_fsf_req:
4285 zfcp_fsf_req_free(fsf_req); 4248 zfcp_fsf_req_free(fsf_req);
4286 unlock_queue_lock: 4249 unlock_queue_lock:
4287 write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); 4250 write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
4288 out: 4251 return ERR_PTR(retval);
4289 return retval;
4290} 4252}
4291 4253
4292 4254static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
4293/*
4294 * function: zfcp_fsf_control_file_handler
4295 *
4296 * purpose: Handler of the control file upload/download FSF requests
4297 *
4298 * returns: 0 - FSF request successfuly processed
4299 * -EAGAIN - Operation has to be repeated because of a temporary problem
4300 * -EACCES - There is no permission to execute an operation
4301 * -EPERM - The control file is not in a right format
4302 * -EIO - There is a problem with the FCP adapter
4303 * -EINVAL - Invalid operation
4304 * -EFAULT - User space memory I/O operation fault
4305 */
4306static int
4307zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
4308{ 4255{
4309 struct zfcp_adapter *adapter = fsf_req->adapter; 4256 if (fsf_req->qtcb->header.fsf_status != FSF_GOOD)
4310 struct fsf_qtcb_header *header = &fsf_req->qtcb->header;
4311 struct fsf_qtcb_bottom_support *bottom = &fsf_req->qtcb->bottom.support;
4312 int retval = 0;
4313
4314 if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
4315 retval = -EINVAL;
4316 goto skip_fsfstatus;
4317 }
4318
4319 switch (header->fsf_status) {
4320
4321 case FSF_GOOD:
4322 ZFCP_LOG_NORMAL(
4323 "The FSF request has been successfully completed "
4324 "on the adapter %s\n",
4325 zfcp_get_busid_by_adapter(adapter));
4326 break;
4327
4328 case FSF_OPERATION_PARTIALLY_SUCCESSFUL:
4329 if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) {
4330 switch (header->fsf_status_qual.word[0]) {
4331
4332 case FSF_SQ_CFDC_HARDENED_ON_SE:
4333 ZFCP_LOG_NORMAL(
4334 "CFDC on the adapter %s has being "
4335 "hardened on primary and secondary SE\n",
4336 zfcp_get_busid_by_adapter(adapter));
4337 break;
4338
4339 case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE:
4340 ZFCP_LOG_NORMAL(
4341 "CFDC of the adapter %s could not "
4342 "be saved on the SE\n",
4343 zfcp_get_busid_by_adapter(adapter));
4344 break;
4345
4346 case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2:
4347 ZFCP_LOG_NORMAL(
4348 "CFDC of the adapter %s could not "
4349 "be copied to the secondary SE\n",
4350 zfcp_get_busid_by_adapter(adapter));
4351 break;
4352
4353 default:
4354 ZFCP_LOG_NORMAL(
4355 "CFDC could not be hardened "
4356 "on the adapter %s\n",
4357 zfcp_get_busid_by_adapter(adapter));
4358 }
4359 }
4360 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4361 retval = -EAGAIN;
4362 break;
4363
4364 case FSF_AUTHORIZATION_FAILURE:
4365 ZFCP_LOG_NORMAL(
4366 "Adapter %s does not accept privileged commands\n",
4367 zfcp_get_busid_by_adapter(adapter));
4368 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4369 retval = -EACCES;
4370 break;
4371
4372 case FSF_CFDC_ERROR_DETECTED:
4373 ZFCP_LOG_NORMAL(
4374 "Error at position %d in the CFDC, "
4375 "CFDC is discarded by the adapter %s\n",
4376 header->fsf_status_qual.word[0],
4377 zfcp_get_busid_by_adapter(adapter));
4378 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4379 retval = -EPERM;
4380 break;
4381
4382 case FSF_CONTROL_FILE_UPDATE_ERROR:
4383 ZFCP_LOG_NORMAL(
4384 "Adapter %s cannot harden the control file, "
4385 "file is discarded\n",
4386 zfcp_get_busid_by_adapter(adapter));
4387 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4388 retval = -EIO;
4389 break;
4390
4391 case FSF_CONTROL_FILE_TOO_LARGE:
4392 ZFCP_LOG_NORMAL(
4393 "Control file is too large, file is discarded "
4394 "by the adapter %s\n",
4395 zfcp_get_busid_by_adapter(adapter));
4396 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4397 retval = -EIO;
4398 break;
4399
4400 case FSF_ACCESS_CONFLICT_DETECTED:
4401 if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
4402 ZFCP_LOG_NORMAL(
4403 "CFDC has been discarded by the adapter %s, "
4404 "because activation would impact "
4405 "%d active connection(s)\n",
4406 zfcp_get_busid_by_adapter(adapter),
4407 header->fsf_status_qual.word[0]);
4408 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4409 retval = -EIO;
4410 break;
4411
4412 case FSF_CONFLICTS_OVERRULED:
4413 if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
4414 ZFCP_LOG_NORMAL(
4415 "CFDC has been activated on the adapter %s, "
4416 "but activation has impacted "
4417 "%d active connection(s)\n",
4418 zfcp_get_busid_by_adapter(adapter),
4419 header->fsf_status_qual.word[0]);
4420 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4421 retval = -EIO;
4422 break;
4423
4424 case FSF_UNKNOWN_OP_SUBTYPE:
4425 ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, "
4426 "op_subtype=0x%x)\n",
4427 zfcp_get_busid_by_adapter(adapter),
4428 bottom->operation_subtype);
4429 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4430 retval = -EINVAL;
4431 break;
4432
4433 case FSF_INVALID_COMMAND_OPTION:
4434 ZFCP_LOG_NORMAL(
4435 "Invalid option 0x%x has been specified "
4436 "in QTCB bottom sent to the adapter %s\n",
4437 bottom->option,
4438 zfcp_get_busid_by_adapter(adapter));
4439 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 4257 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4440 retval = -EINVAL;
4441 break;
4442
4443 default:
4444 ZFCP_LOG_NORMAL(
4445 "bug: An unknown/unexpected FSF status 0x%08x "
4446 "was presented on the adapter %s\n",
4447 header->fsf_status,
4448 zfcp_get_busid_by_adapter(adapter));
4449 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4450 retval = -EINVAL;
4451 break;
4452 }
4453
4454skip_fsfstatus:
4455 return retval;
4456} 4258}
4457 4259
4458static inline int 4260static inline int
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 8b1a7d9c840f..598eba9baa31 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -22,6 +22,8 @@
22#ifndef FSF_H 22#ifndef FSF_H
23#define FSF_H 23#define FSF_H
24 24
25#include <linux/pfn.h>
26
25#define FSF_QTCB_CURRENT_VERSION 0x00000001 27#define FSF_QTCB_CURRENT_VERSION 0x00000001
26 28
27/* FSF commands */ 29/* FSF commands */
@@ -258,6 +260,16 @@
258#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 260#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000
259#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 261#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000
260 262
263/* FSF interface for CFDC */
264#define ZFCP_CFDC_MAX_SIZE 127 * 1024
265#define ZFCP_CFDC_PAGES PFN_UP(ZFCP_CFDC_MAX_SIZE)
266
267struct zfcp_fsf_cfdc {
268 struct scatterlist sg[ZFCP_CFDC_PAGES];
269 u32 command;
270 u32 option;
271};
272
261struct fsf_queue_designator { 273struct fsf_queue_designator {
262 u8 cssid; 274 u8 cssid;
263 u8 chpid; 275 u8 chpid;