You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[S390] Add crypto support for 3592 tape devices
3592 tape devices are able to write data encrpyted on tape mediums. This z/Linux device driver support includes the following functions: * ioctl to switch on/off encryption * ioctl to query encryption status of drive * ioctls to set and query key encrypting keys (kekls) * long busy interrupt handling Signed-off-by: Michael Holzheu <holzheu@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
committed by
Martin Schwidefsky
parent
fe355b7f1c
commit
cced1dd42e
@@ -3,7 +3,7 @@
|
|||||||
* tape device driver for 3480/3490E/3590 tapes.
|
* tape device driver for 3480/3490E/3590 tapes.
|
||||||
*
|
*
|
||||||
* S390 and zSeries version
|
* S390 and zSeries version
|
||||||
* Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
* Copyright IBM Corp. 2001,2006
|
||||||
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
||||||
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
|
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
|
||||||
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||||
@@ -99,7 +99,11 @@ enum tape_op {
|
|||||||
TO_DIS, /* Tape display */
|
TO_DIS, /* Tape display */
|
||||||
TO_ASSIGN, /* Assign tape to channel path */
|
TO_ASSIGN, /* Assign tape to channel path */
|
||||||
TO_UNASSIGN, /* Unassign tape from channel path */
|
TO_UNASSIGN, /* Unassign tape from channel path */
|
||||||
TO_SIZE /* #entries in tape_op_t */
|
TO_CRYPT_ON, /* Enable encrpytion */
|
||||||
|
TO_CRYPT_OFF, /* Disable encrpytion */
|
||||||
|
TO_KEKL_SET, /* Set KEK label */
|
||||||
|
TO_KEKL_QUERY, /* Query KEK label */
|
||||||
|
TO_SIZE, /* #entries in tape_op_t */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
@@ -112,6 +116,7 @@ enum tape_request_status {
|
|||||||
TAPE_REQUEST_IN_IO, /* request is currently in IO */
|
TAPE_REQUEST_IN_IO, /* request is currently in IO */
|
||||||
TAPE_REQUEST_DONE, /* request is completed. */
|
TAPE_REQUEST_DONE, /* request is completed. */
|
||||||
TAPE_REQUEST_CANCEL, /* request should be canceled. */
|
TAPE_REQUEST_CANCEL, /* request should be canceled. */
|
||||||
|
TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Tape CCW request */
|
/* Tape CCW request */
|
||||||
@@ -164,10 +169,11 @@ struct tape_discipline {
|
|||||||
* The discipline irq function either returns an error code (<0) which
|
* The discipline irq function either returns an error code (<0) which
|
||||||
* means that the request has failed with an error or one of the following:
|
* means that the request has failed with an error or one of the following:
|
||||||
*/
|
*/
|
||||||
#define TAPE_IO_SUCCESS 0 /* request successful */
|
#define TAPE_IO_SUCCESS 0 /* request successful */
|
||||||
#define TAPE_IO_PENDING 1 /* request still running */
|
#define TAPE_IO_PENDING 1 /* request still running */
|
||||||
#define TAPE_IO_RETRY 2 /* retry to current request */
|
#define TAPE_IO_RETRY 2 /* retry to current request */
|
||||||
#define TAPE_IO_STOP 3 /* stop the running request */
|
#define TAPE_IO_STOP 3 /* stop the running request */
|
||||||
|
#define TAPE_IO_LONG_BUSY 4 /* delay the running request */
|
||||||
|
|
||||||
/* Char Frontend Data */
|
/* Char Frontend Data */
|
||||||
struct tape_char_data {
|
struct tape_char_data {
|
||||||
@@ -242,6 +248,10 @@ struct tape_device {
|
|||||||
|
|
||||||
/* Function to start or stop the next request later. */
|
/* Function to start or stop the next request later. */
|
||||||
struct delayed_work tape_dnr;
|
struct delayed_work tape_dnr;
|
||||||
|
|
||||||
|
/* Timer for long busy */
|
||||||
|
struct timer_list lb_timeout;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Externals from tape_core.c */
|
/* Externals from tape_core.c */
|
||||||
|
|||||||
+460
-19
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
* drivers/s390/char/tape_3590.h
|
* drivers/s390/char/tape_3590.h
|
||||||
* tape device discipline for 3590 tapes.
|
* tape device discipline for 3590 tapes.
|
||||||
*
|
*
|
||||||
* Copyright (C) IBM Corp. 2001,2006
|
* Copyright IBM Corp. 2001,2006
|
||||||
* Author(s): Stefan Bader <shbader@de.ibm.com>
|
* Author(s): Stefan Bader <shbader@de.ibm.com>
|
||||||
* Michael Holzheu <holzheu@de.ibm.com>
|
* Michael Holzheu <holzheu@de.ibm.com>
|
||||||
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||||
@@ -38,16 +38,22 @@
|
|||||||
#define MSENSE_UNASSOCIATED 0x00
|
#define MSENSE_UNASSOCIATED 0x00
|
||||||
#define MSENSE_ASSOCIATED_MOUNT 0x01
|
#define MSENSE_ASSOCIATED_MOUNT 0x01
|
||||||
#define MSENSE_ASSOCIATED_UMOUNT 0x02
|
#define MSENSE_ASSOCIATED_UMOUNT 0x02
|
||||||
|
#define MSENSE_CRYPT_MASK 0x00000010
|
||||||
|
|
||||||
#define TAPE_3590_MAX_MSG 0xb0
|
#define TAPE_3590_MAX_MSG 0xb0
|
||||||
|
|
||||||
/* Datatypes */
|
/* Datatypes */
|
||||||
|
|
||||||
struct tape_3590_disc_data {
|
struct tape_3590_disc_data {
|
||||||
unsigned char modeset_byte;
|
struct tape390_crypt_info crypt_info;
|
||||||
int read_back_op;
|
int read_back_op;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TAPE_3590_CRYPT_INFO(device) \
|
||||||
|
((struct tape_3590_disc_data*)(device->discdata))->crypt_info
|
||||||
|
#define TAPE_3590_READ_BACK_OP(device) \
|
||||||
|
((struct tape_3590_disc_data*)(device->discdata))->read_back_op
|
||||||
|
|
||||||
struct tape_3590_sense {
|
struct tape_3590_sense {
|
||||||
|
|
||||||
unsigned int command_rej:1;
|
unsigned int command_rej:1;
|
||||||
@@ -118,7 +124,48 @@ struct tape_3590_sense {
|
|||||||
struct tape_3590_med_sense {
|
struct tape_3590_med_sense {
|
||||||
unsigned int macst:4;
|
unsigned int macst:4;
|
||||||
unsigned int masst:4;
|
unsigned int masst:4;
|
||||||
char pad[127];
|
char pad1[7];
|
||||||
|
unsigned int flags;
|
||||||
|
char pad2[116];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* Datastructures for 3592 encryption support */
|
||||||
|
|
||||||
|
struct tape3592_kekl {
|
||||||
|
__u8 flags;
|
||||||
|
char label[64];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct tape3592_kekl_pair {
|
||||||
|
__u8 count;
|
||||||
|
struct tape3592_kekl kekl[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct tape3592_kekl_query_data {
|
||||||
|
__u16 len;
|
||||||
|
__u8 fmt;
|
||||||
|
__u8 mc;
|
||||||
|
__u32 id;
|
||||||
|
__u8 flags;
|
||||||
|
struct tape3592_kekl_pair kekls;
|
||||||
|
char reserved[116];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct tape3592_kekl_query_order {
|
||||||
|
__u8 code;
|
||||||
|
__u8 flags;
|
||||||
|
char reserved1[2];
|
||||||
|
__u8 max_count;
|
||||||
|
char reserved2[35];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct tape3592_kekl_set_order {
|
||||||
|
__u8 code;
|
||||||
|
__u8 flags;
|
||||||
|
char reserved1[2];
|
||||||
|
__u8 op;
|
||||||
|
struct tape3592_kekl_pair kekls;
|
||||||
|
char reserved2[120];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#endif /* _TAPE_3590_H */
|
#endif /* _TAPE_3590_H */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* character device frontend for tape device driver
|
* character device frontend for tape device driver
|
||||||
*
|
*
|
||||||
* S390 and zSeries version
|
* S390 and zSeries version
|
||||||
* Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
* Copyright IBM Corp. 2001,2006
|
||||||
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
||||||
* Michael Holzheu <holzheu@de.ibm.com>
|
* Michael Holzheu <holzheu@de.ibm.com>
|
||||||
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
|
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* basic function of the tape device driver
|
* basic function of the tape device driver
|
||||||
*
|
*
|
||||||
* S390 and zSeries version
|
* S390 and zSeries version
|
||||||
* Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
* Copyright IBM Corp. 2001,2006
|
||||||
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
* Author(s): Carsten Otte <cotte@de.ibm.com>
|
||||||
* Michael Holzheu <holzheu@de.ibm.com>
|
* Michael Holzheu <holzheu@de.ibm.com>
|
||||||
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
|
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
|
||||||
@@ -26,9 +26,11 @@
|
|||||||
#include "tape_std.h"
|
#include "tape_std.h"
|
||||||
|
|
||||||
#define PRINTK_HEADER "TAPE_CORE: "
|
#define PRINTK_HEADER "TAPE_CORE: "
|
||||||
|
#define LONG_BUSY_TIMEOUT 180 /* seconds */
|
||||||
|
|
||||||
static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
|
static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
|
||||||
static void tape_delayed_next_request(struct work_struct *);
|
static void tape_delayed_next_request(struct work_struct *);
|
||||||
|
static void tape_long_busy_timeout(unsigned long data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One list to contain all tape devices of all disciplines, so
|
* One list to contain all tape devices of all disciplines, so
|
||||||
@@ -69,7 +71,9 @@ const char *tape_op_verbose[TO_SIZE] =
|
|||||||
[TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF",
|
[TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF",
|
||||||
[TO_READ_ATTMSG] = "RAT",
|
[TO_READ_ATTMSG] = "RAT",
|
||||||
[TO_DIS] = "DIS", [TO_ASSIGN] = "ASS",
|
[TO_DIS] = "DIS", [TO_ASSIGN] = "ASS",
|
||||||
[TO_UNASSIGN] = "UAS"
|
[TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON",
|
||||||
|
[TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS",
|
||||||
|
[TO_KEKL_QUERY] = "KLQ",
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
@@ -346,6 +350,9 @@ tape_generic_online(struct tape_device *device,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_timer(&device->lb_timeout);
|
||||||
|
device->lb_timeout.function = tape_long_busy_timeout;
|
||||||
|
|
||||||
/* Let the discipline have a go at the device. */
|
/* Let the discipline have a go at the device. */
|
||||||
device->discipline = discipline;
|
device->discipline = discipline;
|
||||||
if (!try_module_get(discipline->owner)) {
|
if (!try_module_get(discipline->owner)) {
|
||||||
@@ -801,6 +808,22 @@ tape_delayed_next_request(struct work_struct *work)
|
|||||||
spin_unlock_irq(get_ccwdev_lock(device->cdev));
|
spin_unlock_irq(get_ccwdev_lock(device->cdev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tape_long_busy_timeout(unsigned long data)
|
||||||
|
{
|
||||||
|
struct tape_request *request;
|
||||||
|
struct tape_device *device;
|
||||||
|
|
||||||
|
device = (struct tape_device *) data;
|
||||||
|
spin_lock_irq(get_ccwdev_lock(device->cdev));
|
||||||
|
request = list_entry(device->req_queue.next, struct tape_request, list);
|
||||||
|
if (request->status != TAPE_REQUEST_LONG_BUSY)
|
||||||
|
BUG();
|
||||||
|
DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
|
||||||
|
__tape_start_next_request(device);
|
||||||
|
device->lb_timeout.data = (unsigned long) tape_put_device(device);
|
||||||
|
spin_unlock_irq(get_ccwdev_lock(device->cdev));
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
__tape_end_request(
|
__tape_end_request(
|
||||||
struct tape_device * device,
|
struct tape_device * device,
|
||||||
@@ -1094,7 +1117,22 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
|||||||
/* May be an unsolicited irq */
|
/* May be an unsolicited irq */
|
||||||
if(request != NULL)
|
if(request != NULL)
|
||||||
request->rescnt = irb->scsw.count;
|
request->rescnt = irb->scsw.count;
|
||||||
|
else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) &&
|
||||||
|
!list_empty(&device->req_queue)) {
|
||||||
|
/* Not Ready to Ready after long busy ? */
|
||||||
|
struct tape_request *req;
|
||||||
|
req = list_entry(device->req_queue.next,
|
||||||
|
struct tape_request, list);
|
||||||
|
if (req->status == TAPE_REQUEST_LONG_BUSY) {
|
||||||
|
DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id);
|
||||||
|
if (del_timer(&device->lb_timeout)) {
|
||||||
|
device->lb_timeout.data = (unsigned long)
|
||||||
|
tape_put_device(device);
|
||||||
|
__tape_start_next_request(device);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (irb->scsw.dstat != 0x0c) {
|
if (irb->scsw.dstat != 0x0c) {
|
||||||
/* Set the 'ONLINE' flag depending on sense byte 1 */
|
/* Set the 'ONLINE' flag depending on sense byte 1 */
|
||||||
if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
|
if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
|
||||||
@@ -1142,6 +1180,15 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
|||||||
break;
|
break;
|
||||||
case TAPE_IO_PENDING:
|
case TAPE_IO_PENDING:
|
||||||
break;
|
break;
|
||||||
|
case TAPE_IO_LONG_BUSY:
|
||||||
|
device->lb_timeout.data =
|
||||||
|
(unsigned long)tape_get_device_reference(device);
|
||||||
|
device->lb_timeout.expires = jiffies +
|
||||||
|
LONG_BUSY_TIMEOUT * HZ;
|
||||||
|
DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id);
|
||||||
|
add_timer(&device->lb_timeout);
|
||||||
|
request->status = TAPE_REQUEST_LONG_BUSY;
|
||||||
|
break;
|
||||||
case TAPE_IO_RETRY:
|
case TAPE_IO_RETRY:
|
||||||
rc = __tape_start_io(device, request);
|
rc = __tape_start_io(device, request);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
*
|
*
|
||||||
* tape390.h
|
* tape390.h
|
||||||
* enables user programs to display messages on the tape device
|
* enables user programs to display messages and control encryption
|
||||||
|
* on s390 tape devices
|
||||||
*
|
*
|
||||||
* S390 and zSeries version
|
* Copyright IBM Corp. 2001,2006
|
||||||
* Copyright (C) 2001 IBM Corporation
|
* Author(s): Michael Holzheu <holzheu@de.ibm.com>
|
||||||
* Author(s): Despina Papadopoulou <despina_p@de.ibm.com>
|
|
||||||
*
|
*
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
@@ -36,4 +36,68 @@ typedef struct display_struct {
|
|||||||
char message2[8];
|
char message2[8];
|
||||||
} display_struct;
|
} display_struct;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tape encryption support
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct tape390_crypt_info {
|
||||||
|
char capability;
|
||||||
|
char status;
|
||||||
|
char medium_status;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
/* Macros for "capable" field */
|
||||||
|
#define TAPE390_CRYPT_SUPPORTED_MASK 0x01
|
||||||
|
#define TAPE390_CRYPT_SUPPORTED(x) \
|
||||||
|
((x.capability & TAPE390_CRYPT_SUPPORTED_MASK))
|
||||||
|
|
||||||
|
/* Macros for "status" field */
|
||||||
|
#define TAPE390_CRYPT_ON_MASK 0x01
|
||||||
|
#define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK))
|
||||||
|
|
||||||
|
/* Macros for "medium status" field */
|
||||||
|
#define TAPE390_MEDIUM_LOADED_MASK 0x01
|
||||||
|
#define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02
|
||||||
|
#define TAPE390_MEDIUM_ENCRYPTED(x) \
|
||||||
|
(((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK))
|
||||||
|
#define TAPE390_MEDIUM_LOADED(x) \
|
||||||
|
(((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption.
|
||||||
|
* The "encryption_capable" and "tape_status" fields are ignored for this ioctl!
|
||||||
|
*/
|
||||||
|
#define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state.
|
||||||
|
*/
|
||||||
|
#define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info)
|
||||||
|
|
||||||
|
/* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */
|
||||||
|
#define TAPE390_KEKL_TYPE_NONE 0
|
||||||
|
#define TAPE390_KEKL_TYPE_LABEL 1
|
||||||
|
#define TAPE390_KEKL_TYPE_HASH 2
|
||||||
|
|
||||||
|
struct tape390_kekl {
|
||||||
|
unsigned char type;
|
||||||
|
unsigned char type_on_tape;
|
||||||
|
char label[65];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct tape390_kekl_pair {
|
||||||
|
struct tape390_kekl kekl[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels.
|
||||||
|
*/
|
||||||
|
#define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels.
|
||||||
|
*/
|
||||||
|
#define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user