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
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull second set of s390 patches from Martin Schwidefsky: "The second part of Heikos uaccess rework, the page table walker for uaccess is now a thing of the past (yay!) The code change to fix the theoretical TLB flush problem allows us to add a TLB flush optimization for zEC12, this machine has new instructions that allow to do CPU local TLB flushes for single pages and for all pages of a specific address space. Plus the usual bug fixing and some more cleanup" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/uaccess: rework uaccess code - fix locking issues s390/mm,tlb: optimize TLB flushing for zEC12 s390/mm,tlb: safeguard against speculative TLB creation s390/irq: Use defines for external interruption codes s390/irq: Add defines for external interruption codes s390/sclp: add timeout for queued requests kvm/s390: also set guest pages back to stable on kexec/kdump lcs: Add missing destroy_timer_on_stack() s390/tape: Add missing destroy_timer_on_stack() s390/tape: Use del_timer_sync() s390/3270: fix crash with multiple reset device requests s390/bitops,atomic: add missing memory barriers s390/zcrypt: add length check for aligned data to avoid overflow in msg-type 6
This commit is contained in:
@@ -646,7 +646,7 @@ dasd_diag_init(void)
|
||||
ASCEBC(dasd_diag_discipline.ebcname, 4);
|
||||
|
||||
irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL);
|
||||
register_external_interrupt(0x2603, dasd_ext_handler);
|
||||
register_external_irq(EXT_IRQ_CP_SERVICE, dasd_ext_handler);
|
||||
dasd_diag_discipline_pointer = &dasd_diag_discipline;
|
||||
return 0;
|
||||
}
|
||||
@@ -654,7 +654,7 @@ dasd_diag_init(void)
|
||||
static void __exit
|
||||
dasd_diag_cleanup(void)
|
||||
{
|
||||
unregister_external_interrupt(0x2603, dasd_ext_handler);
|
||||
unregister_external_irq(EXT_IRQ_CP_SERVICE, dasd_ext_handler);
|
||||
irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
|
||||
dasd_diag_discipline_pointer = NULL;
|
||||
}
|
||||
|
||||
@@ -632,6 +632,8 @@ raw3270_reset_device_cb(struct raw3270_request *rq, void *data)
|
||||
raw3270_size_device_done(rp);
|
||||
} else
|
||||
raw3270_writesf_readpart(rp);
|
||||
memset(&rp->init_reset, 0, sizeof(rp->init_reset));
|
||||
memset(&rp->init_data, 0, sizeof(rp->init_data));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -639,9 +641,10 @@ __raw3270_reset_device(struct raw3270 *rp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Check if reset is already pending */
|
||||
if (rp->init_reset.view)
|
||||
return -EBUSY;
|
||||
/* Store reset data stream to init_data/init_reset */
|
||||
memset(&rp->init_reset, 0, sizeof(rp->init_reset));
|
||||
memset(&rp->init_data, 0, sizeof(rp->init_data));
|
||||
rp->init_data[0] = TW_KR;
|
||||
rp->init_reset.ccw.cmd_code = TC_EWRITEA;
|
||||
rp->init_reset.ccw.flags = CCW_FLAG_SLI;
|
||||
@@ -850,7 +853,7 @@ raw3270_create_device(struct ccw_device *cdev)
|
||||
char *ascebc;
|
||||
int rc;
|
||||
|
||||
rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
|
||||
rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
|
||||
if (!rp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ascebc = kmalloc(256, GFP_KERNEL);
|
||||
|
||||
@@ -91,6 +91,9 @@ static struct sclp_req sclp_suspend_req;
|
||||
/* Timer for request retries. */
|
||||
static struct timer_list sclp_request_timer;
|
||||
|
||||
/* Timer for queued requests. */
|
||||
static struct timer_list sclp_queue_timer;
|
||||
|
||||
/* Internal state: is the driver initialized? */
|
||||
static volatile enum sclp_init_state_t {
|
||||
sclp_init_state_uninitialized,
|
||||
@@ -215,6 +218,76 @@ sclp_request_timeout(unsigned long data)
|
||||
sclp_process_queue();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the expire value in jiffies of the next pending request timeout,
|
||||
* if any. Needs to be called with sclp_lock.
|
||||
*/
|
||||
static unsigned long __sclp_req_queue_find_next_timeout(void)
|
||||
{
|
||||
unsigned long expires_next = 0;
|
||||
struct sclp_req *req;
|
||||
|
||||
list_for_each_entry(req, &sclp_req_queue, list) {
|
||||
if (!req->queue_expires)
|
||||
continue;
|
||||
if (!expires_next ||
|
||||
(time_before(req->queue_expires, expires_next)))
|
||||
expires_next = req->queue_expires;
|
||||
}
|
||||
return expires_next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns expired request, if any, and removes it from the list.
|
||||
*/
|
||||
static struct sclp_req *__sclp_req_queue_remove_expired_req(void)
|
||||
{
|
||||
unsigned long flags, now;
|
||||
struct sclp_req *req;
|
||||
|
||||
spin_lock_irqsave(&sclp_lock, flags);
|
||||
now = jiffies;
|
||||
/* Don't need list_for_each_safe because we break out after list_del */
|
||||
list_for_each_entry(req, &sclp_req_queue, list) {
|
||||
if (!req->queue_expires)
|
||||
continue;
|
||||
if (time_before_eq(req->queue_expires, now)) {
|
||||
if (req->status == SCLP_REQ_QUEUED) {
|
||||
req->status = SCLP_REQ_QUEUED_TIMEOUT;
|
||||
list_del(&req->list);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
req = NULL;
|
||||
out:
|
||||
spin_unlock_irqrestore(&sclp_lock, flags);
|
||||
return req;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timeout handler for queued requests. Removes request from list and
|
||||
* invokes callback. This timer can be set per request in situations where
|
||||
* waiting too long would be harmful to the system, e.g. during SE reboot.
|
||||
*/
|
||||
static void sclp_req_queue_timeout(unsigned long data)
|
||||
{
|
||||
unsigned long flags, expires_next;
|
||||
struct sclp_req *req;
|
||||
|
||||
do {
|
||||
req = __sclp_req_queue_remove_expired_req();
|
||||
if (req && req->callback)
|
||||
req->callback(req, req->callback_data);
|
||||
} while (req);
|
||||
|
||||
spin_lock_irqsave(&sclp_lock, flags);
|
||||
expires_next = __sclp_req_queue_find_next_timeout();
|
||||
if (expires_next)
|
||||
mod_timer(&sclp_queue_timer, expires_next);
|
||||
spin_unlock_irqrestore(&sclp_lock, flags);
|
||||
}
|
||||
|
||||
/* Try to start a request. Return zero if the request was successfully
|
||||
* started or if it will be started at a later time. Return non-zero otherwise.
|
||||
* Called while sclp_lock is locked. */
|
||||
@@ -317,6 +390,13 @@ sclp_add_request(struct sclp_req *req)
|
||||
req->start_count = 0;
|
||||
list_add_tail(&req->list, &sclp_req_queue);
|
||||
rc = 0;
|
||||
if (req->queue_timeout) {
|
||||
req->queue_expires = jiffies + req->queue_timeout * HZ;
|
||||
if (!timer_pending(&sclp_queue_timer) ||
|
||||
time_after(sclp_queue_timer.expires, req->queue_expires))
|
||||
mod_timer(&sclp_queue_timer, req->queue_expires);
|
||||
} else
|
||||
req->queue_expires = 0;
|
||||
/* Start if request is first in list */
|
||||
if (sclp_running_state == sclp_running_state_idle &&
|
||||
req->list.prev == &sclp_req_queue) {
|
||||
@@ -892,7 +972,7 @@ sclp_check_interface(void)
|
||||
|
||||
spin_lock_irqsave(&sclp_lock, flags);
|
||||
/* Prepare init mask command */
|
||||
rc = register_external_interrupt(0x2401, sclp_check_handler);
|
||||
rc = register_external_irq(EXT_IRQ_SERVICE_SIG, sclp_check_handler);
|
||||
if (rc) {
|
||||
spin_unlock_irqrestore(&sclp_lock, flags);
|
||||
return rc;
|
||||
@@ -925,7 +1005,7 @@ sclp_check_interface(void)
|
||||
} else
|
||||
rc = -EBUSY;
|
||||
}
|
||||
unregister_external_interrupt(0x2401, sclp_check_handler);
|
||||
unregister_external_irq(EXT_IRQ_SERVICE_SIG, sclp_check_handler);
|
||||
spin_unlock_irqrestore(&sclp_lock, flags);
|
||||
return rc;
|
||||
}
|
||||
@@ -1113,6 +1193,8 @@ sclp_init(void)
|
||||
INIT_LIST_HEAD(&sclp_reg_list);
|
||||
list_add(&sclp_state_change_event.list, &sclp_reg_list);
|
||||
init_timer(&sclp_request_timer);
|
||||
init_timer(&sclp_queue_timer);
|
||||
sclp_queue_timer.function = sclp_req_queue_timeout;
|
||||
/* Check interface */
|
||||
spin_unlock_irqrestore(&sclp_lock, flags);
|
||||
rc = sclp_check_interface();
|
||||
@@ -1124,7 +1206,7 @@ sclp_init(void)
|
||||
if (rc)
|
||||
goto fail_init_state_uninitialized;
|
||||
/* Register interrupt handler */
|
||||
rc = register_external_interrupt(0x2401, sclp_interrupt_handler);
|
||||
rc = register_external_irq(EXT_IRQ_SERVICE_SIG, sclp_interrupt_handler);
|
||||
if (rc)
|
||||
goto fail_unregister_reboot_notifier;
|
||||
sclp_init_state = sclp_init_state_initialized;
|
||||
|
||||
@@ -133,6 +133,11 @@ struct sclp_req {
|
||||
/* Callback that is called after reaching final status. */
|
||||
void (*callback)(struct sclp_req *, void *data);
|
||||
void *callback_data;
|
||||
int queue_timeout; /* request queue timeout (sec), set by
|
||||
caller of sclp_add_request(), if
|
||||
needed */
|
||||
/* Internal fields */
|
||||
unsigned long queue_expires; /* request queue timeout (jiffies) */
|
||||
};
|
||||
|
||||
#define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */
|
||||
@@ -140,6 +145,9 @@ struct sclp_req {
|
||||
#define SCLP_REQ_RUNNING 0x02 /* request is currently running */
|
||||
#define SCLP_REQ_DONE 0x03 /* request is completed successfully */
|
||||
#define SCLP_REQ_FAILED 0x05 /* request is finally failed */
|
||||
#define SCLP_REQ_QUEUED_TIMEOUT 0x06 /* request on queue timed out */
|
||||
|
||||
#define SCLP_QUEUE_INTERVAL 5 /* timeout interval for request queue */
|
||||
|
||||
/* function pointers that a high level driver has to use for registration */
|
||||
/* of some routines it wants to be called from the low level driver */
|
||||
@@ -173,6 +181,7 @@ int sclp_deactivate(void);
|
||||
int sclp_reactivate(void);
|
||||
int sclp_service_call(sclp_cmdw_t command, void *sccb);
|
||||
int sclp_sync_request(sclp_cmdw_t command, void *sccb);
|
||||
int sclp_sync_request_timeout(sclp_cmdw_t command, void *sccb, int timeout);
|
||||
|
||||
int sclp_sdias_init(void);
|
||||
void sclp_sdias_exit(void);
|
||||
|
||||
@@ -36,6 +36,11 @@ static void sclp_sync_callback(struct sclp_req *req, void *data)
|
||||
}
|
||||
|
||||
int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)
|
||||
{
|
||||
return sclp_sync_request_timeout(cmd, sccb, 0);
|
||||
}
|
||||
|
||||
int sclp_sync_request_timeout(sclp_cmdw_t cmd, void *sccb, int timeout)
|
||||
{
|
||||
struct completion completion;
|
||||
struct sclp_req *request;
|
||||
@@ -44,6 +49,8 @@ int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)
|
||||
request = kzalloc(sizeof(*request), GFP_KERNEL);
|
||||
if (!request)
|
||||
return -ENOMEM;
|
||||
if (timeout)
|
||||
request->queue_timeout = timeout;
|
||||
request->command = cmd;
|
||||
request->sccb = sccb;
|
||||
request->status = SCLP_REQ_FILLED;
|
||||
@@ -110,7 +117,8 @@ int sclp_get_cpu_info(struct sclp_cpu_info *info)
|
||||
if (!sccb)
|
||||
return -ENOMEM;
|
||||
sccb->header.length = sizeof(*sccb);
|
||||
rc = sclp_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
|
||||
rc = sclp_sync_request_timeout(SCLP_CMDW_READ_CPU_INFO, sccb,
|
||||
SCLP_QUEUE_INTERVAL);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (sccb->header.response_code != 0x0010) {
|
||||
@@ -144,7 +152,7 @@ static int do_cpu_configure(sclp_cmdw_t cmd)
|
||||
if (!sccb)
|
||||
return -ENOMEM;
|
||||
sccb->header.length = sizeof(*sccb);
|
||||
rc = sclp_sync_request(cmd, sccb);
|
||||
rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);
|
||||
if (rc)
|
||||
goto out;
|
||||
switch (sccb->header.response_code) {
|
||||
@@ -214,7 +222,7 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
|
||||
return -ENOMEM;
|
||||
sccb->header.length = PAGE_SIZE;
|
||||
sccb->rn = rn;
|
||||
rc = sclp_sync_request(cmd, sccb);
|
||||
rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);
|
||||
if (rc)
|
||||
goto out;
|
||||
switch (sccb->header.response_code) {
|
||||
@@ -269,7 +277,8 @@ static int sclp_attach_storage(u8 id)
|
||||
if (!sccb)
|
||||
return -ENOMEM;
|
||||
sccb->header.length = PAGE_SIZE;
|
||||
rc = sclp_sync_request(0x00080001 | id << 8, sccb);
|
||||
rc = sclp_sync_request_timeout(0x00080001 | id << 8, sccb,
|
||||
SCLP_QUEUE_INTERVAL);
|
||||
if (rc)
|
||||
goto out;
|
||||
switch (sccb->header.response_code) {
|
||||
|
||||
@@ -78,7 +78,8 @@ tape_std_assign(struct tape_device *device)
|
||||
|
||||
rc = tape_do_io_interruptible(device, request);
|
||||
|
||||
del_timer(&timeout);
|
||||
del_timer_sync(&timeout);
|
||||
destroy_timer_on_stack(&timeout);
|
||||
|
||||
if (rc != 0) {
|
||||
DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
|
||||
|
||||
@@ -626,8 +626,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(ep11_dev_list.targets,
|
||||
(struct ep11_target_dev *)xcrb->targets,
|
||||
xcrb->targets_num *
|
||||
(struct ep11_target_dev __force __user *)
|
||||
xcrb->targets, xcrb->targets_num *
|
||||
sizeof(struct ep11_target_dev)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@@ -315,6 +315,10 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
|
||||
char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
|
||||
char *function_code;
|
||||
|
||||
if (CEIL4(xcRB->request_control_blk_length) <
|
||||
xcRB->request_control_blk_length)
|
||||
return -EINVAL; /* overflow after alignment*/
|
||||
|
||||
/* length checks */
|
||||
ap_msg->length = sizeof(struct type6_hdr) +
|
||||
CEIL4(xcRB->request_control_blk_length) +
|
||||
@@ -333,6 +337,10 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (CEIL4(xcRB->reply_control_blk_length) <
|
||||
xcRB->reply_control_blk_length)
|
||||
return -EINVAL; /* overflow after alignment*/
|
||||
|
||||
replylen = sizeof(struct type86_fmt2_msg) +
|
||||
CEIL4(xcRB->reply_control_blk_length) +
|
||||
xcRB->reply_data_length;
|
||||
@@ -415,12 +423,18 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev,
|
||||
unsigned int dom_val; /* domain id */
|
||||
} __packed * payload_hdr;
|
||||
|
||||
if (CEIL4(xcRB->req_len) < xcRB->req_len)
|
||||
return -EINVAL; /* overflow after alignment*/
|
||||
|
||||
/* length checks */
|
||||
ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len;
|
||||
if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE -
|
||||
(sizeof(struct type6_hdr)))
|
||||
return -EINVAL;
|
||||
|
||||
if (CEIL4(xcRB->resp_len) < xcRB->resp_len)
|
||||
return -EINVAL; /* overflow after alignment*/
|
||||
|
||||
if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE -
|
||||
(sizeof(struct type86_fmt2_msg)))
|
||||
return -EINVAL;
|
||||
@@ -432,7 +446,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev,
|
||||
|
||||
/* Import CPRB data from the ioctl input parameter */
|
||||
if (copy_from_user(&(msg->cprbx.cprb_len),
|
||||
(char *)xcRB->req, xcRB->req_len)) {
|
||||
(char __force __user *)xcRB->req, xcRB->req_len)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@@ -645,7 +659,7 @@ static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev,
|
||||
return -EINVAL;
|
||||
|
||||
/* Copy response CPRB to user */
|
||||
if (copy_to_user((char *)xcRB->resp,
|
||||
if (copy_to_user((char __force __user *)xcRB->resp,
|
||||
data + msg->fmt2.offset1, msg->fmt2.count1))
|
||||
return -EFAULT;
|
||||
xcRB->resp_len = msg->fmt2.count1;
|
||||
|
||||
@@ -477,7 +477,7 @@ static int __init kvm_devices_init(void)
|
||||
INIT_WORK(&hotplug_work, hotplug_devices);
|
||||
|
||||
irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL);
|
||||
register_external_interrupt(0x2603, kvm_extint_handler);
|
||||
register_external_irq(EXT_IRQ_CP_SERVICE, kvm_extint_handler);
|
||||
|
||||
scan_devices();
|
||||
return 0;
|
||||
|
||||
@@ -899,6 +899,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
|
||||
add_timer(&timer);
|
||||
wait_event(reply->wait_q, reply->received);
|
||||
del_timer_sync(&timer);
|
||||
destroy_timer_on_stack(&timer);
|
||||
LCS_DBF_TEXT_(4, trace, "rc:%d",reply->rc);
|
||||
rc = reply->rc;
|
||||
lcs_put_reply(reply);
|
||||
|
||||
Reference in New Issue
Block a user