mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 22:53:55 +08:00
s390/zcrypt: get rid of ap_poll_requests
The poll thread of the AP bus is burning CPU while waiting for crypto requests to complete. We can as well burn a few more cycles in the poll thread to check if there are pending requests and remove the atomic operations with the ap_poll_requests. This improves the code if the machine has adapter interrupts. Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
0db78559f9
commit
9af3e04ee4
@ -91,7 +91,6 @@ static DECLARE_WORK(ap_scan_work, ap_scan_bus);
|
||||
*/
|
||||
static void ap_tasklet_fn(unsigned long);
|
||||
static DECLARE_TASKLET(ap_tasklet, ap_tasklet_fn, 0);
|
||||
static atomic_t ap_poll_requests = ATOMIC_INIT(0);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
|
||||
static struct task_struct *ap_poll_kthread = NULL;
|
||||
static DEFINE_MUTEX(ap_poll_thread_mutex);
|
||||
@ -419,7 +418,6 @@ static struct ap_queue_status ap_sm_recv(struct ap_device *ap_dev)
|
||||
ap_dev->reply->message, ap_dev->reply->length);
|
||||
switch (status.response_code) {
|
||||
case AP_RESPONSE_NORMAL:
|
||||
atomic_dec(&ap_poll_requests);
|
||||
ap_dev->queue_count--;
|
||||
if (ap_dev->queue_count > 0)
|
||||
mod_timer(&ap_dev->timeout,
|
||||
@ -436,7 +434,6 @@ static struct ap_queue_status ap_sm_recv(struct ap_device *ap_dev)
|
||||
if (!status.queue_empty || ap_dev->queue_count <= 0)
|
||||
break;
|
||||
/* The card shouldn't forget requests but who knows. */
|
||||
atomic_sub(ap_dev->queue_count, &ap_poll_requests);
|
||||
ap_dev->queue_count = 0;
|
||||
list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
|
||||
ap_dev->requestq_count += ap_dev->pendingq_count;
|
||||
@ -524,7 +521,6 @@ static enum ap_wait ap_sm_write(struct ap_device *ap_dev)
|
||||
ap_msg->message, ap_msg->length, ap_msg->special);
|
||||
switch (status.response_code) {
|
||||
case AP_RESPONSE_NORMAL:
|
||||
atomic_inc(&ap_poll_requests);
|
||||
ap_dev->queue_count++;
|
||||
if (ap_dev->queue_count == 1)
|
||||
mod_timer(&ap_dev->timeout,
|
||||
@ -796,6 +792,27 @@ static void ap_tasklet_fn(unsigned long dummy)
|
||||
ap_sm_wait(wait);
|
||||
}
|
||||
|
||||
static int ap_pending_requests(void)
|
||||
{
|
||||
struct ap_device *ap_dev;
|
||||
int id, pending = 0;
|
||||
|
||||
for (id = 0; pending == 0 && id < AP_DEVICES; id++) {
|
||||
spin_lock_bh(&ap_device_list_lock);
|
||||
list_for_each_entry(ap_dev, &ap_device_list, list) {
|
||||
spin_lock_bh(&ap_dev->lock);
|
||||
if (ap_dev->queue_count)
|
||||
pending = 1;
|
||||
spin_unlock_bh(&ap_dev->lock);
|
||||
if (pending)
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&ap_device_list_lock);
|
||||
}
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
/**
|
||||
* ap_poll_thread(): Thread that polls for finished requests.
|
||||
* @data: Unused pointer
|
||||
@ -815,8 +832,7 @@ static int ap_poll_thread(void *data)
|
||||
while (!kthread_should_stop()) {
|
||||
add_wait_queue(&ap_poll_wait, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (ap_suspend_flag ||
|
||||
atomic_read(&ap_poll_requests) <= 0) {
|
||||
if (ap_suspend_flag || !ap_pending_requests()) {
|
||||
schedule();
|
||||
try_to_freeze();
|
||||
}
|
||||
@ -828,7 +844,8 @@ static int ap_poll_thread(void *data)
|
||||
continue;
|
||||
}
|
||||
ap_tasklet_fn(0);
|
||||
} while (!kthread_should_stop());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1267,9 +1284,6 @@ static int ap_device_remove(struct device *dev)
|
||||
spin_unlock_bh(&ap_device_list_lock);
|
||||
if (ap_drv->remove)
|
||||
ap_drv->remove(ap_dev);
|
||||
spin_lock_bh(&ap_dev->lock);
|
||||
atomic_sub(ap_dev->queue_count, &ap_poll_requests);
|
||||
spin_unlock_bh(&ap_dev->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user