4 * Userspace interface for accessing the
5 * Access Control Lists / Control File Data Channel
7 * Copyright IBM Corporation 2008, 2009
10 #define KMSG_COMPONENT "zfcp"
11 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 #include <linux/slab.h>
14 #include <linux/types.h>
15 #include <linux/miscdevice.h>
16 #include <asm/compat.h>
17 #include <asm/ccwdev.h>
22 #define ZFCP_CFDC_CMND_DOWNLOAD_NORMAL 0x00010001
23 #define ZFCP_CFDC_CMND_DOWNLOAD_FORCE 0x00010101
24 #define ZFCP_CFDC_CMND_FULL_ACCESS 0x00000201
25 #define ZFCP_CFDC_CMND_RESTRICTED_ACCESS 0x00000401
26 #define ZFCP_CFDC_CMND_UPLOAD 0x00010002
28 #define ZFCP_CFDC_DOWNLOAD 0x00000001
29 #define ZFCP_CFDC_UPLOAD 0x00000002
30 #define ZFCP_CFDC_WITH_CONTROL_FILE 0x00010000
32 #define ZFCP_CFDC_IOC_MAGIC 0xDD
33 #define ZFCP_CFDC_IOC \
34 _IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_data)
37 * struct zfcp_cfdc_data - data for ioctl cfdc interface
38 * @signature: request signature
39 * @devno: FCP adapter device number
40 * @command: command code
41 * @fsf_status: returns status of FSF command to userspace
42 * @fsf_status_qual: returned to userspace
43 * @payloads: access conflicts list
44 * @control_file: access control table
46 struct zfcp_cfdc_data
{
51 u8 fsf_status_qual
[FSF_STATUS_QUALIFIER_SIZE
];
56 static int zfcp_cfdc_copy_from_user(struct scatterlist
*sg
,
57 void __user
*user_buffer
)
60 unsigned int size
= ZFCP_CFDC_MAX_SIZE
;
63 length
= min((unsigned int)size
, sg
->length
);
64 if (copy_from_user(sg_virt(sg
++), user_buffer
, length
))
66 user_buffer
+= length
;
72 static int zfcp_cfdc_copy_to_user(void __user
*user_buffer
,
73 struct scatterlist
*sg
)
76 unsigned int size
= ZFCP_CFDC_MAX_SIZE
;
79 length
= min((unsigned int) size
, sg
->length
);
80 if (copy_to_user(user_buffer
, sg_virt(sg
++), length
))
82 user_buffer
+= length
;
88 static struct zfcp_adapter
*zfcp_cfdc_get_adapter(u32 devno
)
91 struct ccw_device
*cdev
;
92 struct zfcp_adapter
*adapter
;
94 snprintf(busid
, sizeof(busid
), "0.0.%04x", devno
);
95 cdev
= get_ccwdev_by_busid(&zfcp_ccw_driver
, busid
);
99 adapter
= zfcp_ccw_adapter_by_cdev(cdev
);
101 put_device(&cdev
->dev
);
105 static int zfcp_cfdc_set_fsf(struct zfcp_fsf_cfdc
*fsf_cfdc
, int command
)
108 case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL
:
109 fsf_cfdc
->command
= FSF_QTCB_DOWNLOAD_CONTROL_FILE
;
110 fsf_cfdc
->option
= FSF_CFDC_OPTION_NORMAL_MODE
;
112 case ZFCP_CFDC_CMND_DOWNLOAD_FORCE
:
113 fsf_cfdc
->command
= FSF_QTCB_DOWNLOAD_CONTROL_FILE
;
114 fsf_cfdc
->option
= FSF_CFDC_OPTION_FORCE
;
116 case ZFCP_CFDC_CMND_FULL_ACCESS
:
117 fsf_cfdc
->command
= FSF_QTCB_DOWNLOAD_CONTROL_FILE
;
118 fsf_cfdc
->option
= FSF_CFDC_OPTION_FULL_ACCESS
;
120 case ZFCP_CFDC_CMND_RESTRICTED_ACCESS
:
121 fsf_cfdc
->command
= FSF_QTCB_DOWNLOAD_CONTROL_FILE
;
122 fsf_cfdc
->option
= FSF_CFDC_OPTION_RESTRICTED_ACCESS
;
124 case ZFCP_CFDC_CMND_UPLOAD
:
125 fsf_cfdc
->command
= FSF_QTCB_UPLOAD_CONTROL_FILE
;
126 fsf_cfdc
->option
= 0;
135 static int zfcp_cfdc_sg_setup(int command
, struct scatterlist
*sg
,
136 u8 __user
*control_file
)
139 retval
= zfcp_sg_setup_table(sg
, ZFCP_CFDC_PAGES
);
143 sg
[ZFCP_CFDC_PAGES
- 1].length
= ZFCP_CFDC_MAX_SIZE
% PAGE_SIZE
;
145 if (command
& ZFCP_CFDC_WITH_CONTROL_FILE
&&
146 command
& ZFCP_CFDC_DOWNLOAD
) {
147 retval
= zfcp_cfdc_copy_from_user(sg
, control_file
);
149 zfcp_sg_free_table(sg
, ZFCP_CFDC_PAGES
);
157 static void zfcp_cfdc_req_to_sense(struct zfcp_cfdc_data
*data
,
158 struct zfcp_fsf_req
*req
)
160 data
->fsf_status
= req
->qtcb
->header
.fsf_status
;
161 memcpy(&data
->fsf_status_qual
, &req
->qtcb
->header
.fsf_status_qual
,
162 sizeof(union fsf_status_qual
));
163 memcpy(&data
->payloads
, &req
->qtcb
->bottom
.support
.els
,
164 sizeof(req
->qtcb
->bottom
.support
.els
));
167 static long zfcp_cfdc_dev_ioctl(struct file
*file
, unsigned int command
,
170 struct zfcp_cfdc_data
*data
;
171 struct zfcp_cfdc_data __user
*data_user
;
172 struct zfcp_adapter
*adapter
;
173 struct zfcp_fsf_req
*req
;
174 struct zfcp_fsf_cfdc
*fsf_cfdc
;
177 if (command
!= ZFCP_CFDC_IOC
)
180 if (is_compat_task())
181 data_user
= compat_ptr(arg
);
183 data_user
= (void __user
*)arg
;
188 fsf_cfdc
= kmalloc(sizeof(struct zfcp_fsf_cfdc
), GFP_KERNEL
);
192 data
= kmalloc(sizeof(struct zfcp_cfdc_data
), GFP_KERNEL
);
198 retval
= copy_from_user(data
, data_user
, sizeof(*data
));
204 if (data
->signature
!= 0xCFDCACDF) {
209 retval
= zfcp_cfdc_set_fsf(fsf_cfdc
, data
->command
);
211 adapter
= zfcp_cfdc_get_adapter(data
->devno
);
217 retval
= zfcp_cfdc_sg_setup(data
->command
, fsf_cfdc
->sg
,
218 data_user
->control_file
);
221 req
= zfcp_fsf_control_file(adapter
, fsf_cfdc
);
223 retval
= PTR_ERR(req
);
227 if (req
->status
& ZFCP_STATUS_FSFREQ_ERROR
) {
232 zfcp_cfdc_req_to_sense(data
, req
);
233 retval
= copy_to_user(data_user
, data
, sizeof(*data_user
));
239 if (data
->command
& ZFCP_CFDC_UPLOAD
)
240 retval
= zfcp_cfdc_copy_to_user(&data_user
->control_file
,
244 zfcp_fsf_req_free(req
);
246 zfcp_sg_free_table(fsf_cfdc
->sg
, ZFCP_CFDC_PAGES
);
248 zfcp_ccw_adapter_put(adapter
);
256 static const struct file_operations zfcp_cfdc_fops
= {
257 .unlocked_ioctl
= zfcp_cfdc_dev_ioctl
,
259 .compat_ioctl
= zfcp_cfdc_dev_ioctl
263 struct miscdevice zfcp_cfdc_misc
= {
264 .minor
= MISC_DYNAMIC_MINOR
,
266 .fops
= &zfcp_cfdc_fops
,