提交 af512ed0 编写于 作者: R Ralph Wuerthner 提交者: Martin Schwidefsky

[S390] zcrypt: fix request timeout handling

Under very high load zcrypt requests may timeout while waiting on the
request queue. Modify zcrypt that timeouts are based on crypto adapter
responses. A timeout occurs only if a crypto adapter does not respond
within a given time frame to sumitted requests.
Signed-off-by: NRalph Wuerthner <rwuerthn@de.ibm.com>
Signed-off-by: NMartin Schwidefsky <schwidefsky@de.ibm.com>
上级 987ad70a
...@@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long); ...@@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long);
static void ap_poll_timeout(unsigned long); static void ap_poll_timeout(unsigned long);
static int ap_poll_thread_start(void); static int ap_poll_thread_start(void);
static void ap_poll_thread_stop(void); static void ap_poll_thread_stop(void);
static void ap_request_timeout(unsigned long);
/** /**
* Module description. * Module description.
...@@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) ...@@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
case AP_RESPONSE_NORMAL: case AP_RESPONSE_NORMAL:
return 0; return 0;
case AP_RESPONSE_Q_FULL: case AP_RESPONSE_Q_FULL:
case AP_RESPONSE_RESET_IN_PROGRESS:
return -EBUSY; return -EBUSY;
default: /* Device is gone. */ default: /* Device is gone. */
return -ENODEV; return -ENODEV;
...@@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) ...@@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
if (status.queue_empty) if (status.queue_empty)
return -ENOENT; return -ENOENT;
return -EBUSY; return -EBUSY;
case AP_RESPONSE_RESET_IN_PROGRESS:
return -EBUSY;
default: default:
return -ENODEV; return -ENODEV;
} }
...@@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid) ...@@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid)
i = AP_MAX_RESET; /* return with -ENODEV */ i = AP_MAX_RESET; /* return with -ENODEV */
break; break;
case AP_RESPONSE_RESET_IN_PROGRESS: case AP_RESPONSE_RESET_IN_PROGRESS:
rc = -EBUSY;
case AP_RESPONSE_BUSY: case AP_RESPONSE_BUSY:
default: default:
break; break;
} }
if (rc != -ENODEV) if (rc != -ENODEV && rc != -EBUSY)
break; break;
if (i < AP_MAX_RESET - 1) { if (i < AP_MAX_RESET - 1) {
udelay(5); udelay(5);
...@@ -340,6 +345,40 @@ static int ap_init_queue(ap_qid_t qid) ...@@ -340,6 +345,40 @@ static int ap_init_queue(ap_qid_t qid)
return rc; return rc;
} }
/**
* Arm request timeout if a AP device was idle and a new request is submitted.
*/
static void ap_increase_queue_count(struct ap_device *ap_dev)
{
int timeout = ap_dev->drv->request_timeout;
ap_dev->queue_count++;
if (ap_dev->queue_count == 1) {
mod_timer(&ap_dev->timeout, jiffies + timeout);
ap_dev->reset = AP_RESET_ARMED;
}
}
/**
* AP device is still alive, re-schedule request timeout if there are still
* pending requests.
*/
static void ap_decrease_queue_count(struct ap_device *ap_dev)
{
int timeout = ap_dev->drv->request_timeout;
ap_dev->queue_count--;
if (ap_dev->queue_count > 0)
mod_timer(&ap_dev->timeout, jiffies + timeout);
else
/**
* The timeout timer should to be disabled now - since
* del_timer_sync() is very expensive, we just tell via the
* reset flag to ignore the pending timeout timer.
*/
ap_dev->reset = AP_RESET_IGNORE;
}
/** /**
* AP device related attributes. * AP device related attributes.
*/ */
...@@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev) ...@@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev)
struct ap_driver *ap_drv = ap_dev->drv; struct ap_driver *ap_drv = ap_dev->drv;
ap_flush_queue(ap_dev); ap_flush_queue(ap_dev);
del_timer_sync(&ap_dev->timeout);
if (ap_drv->remove) if (ap_drv->remove)
ap_drv->remove(ap_dev); ap_drv->remove(ap_dev);
spin_lock_bh(&ap_device_lock); spin_lock_bh(&ap_device_lock);
...@@ -759,17 +799,21 @@ static void ap_scan_bus(struct work_struct *unused) ...@@ -759,17 +799,21 @@ static void ap_scan_bus(struct work_struct *unused)
__ap_scan_bus); __ap_scan_bus);
rc = ap_query_queue(qid, &queue_depth, &device_type); rc = ap_query_queue(qid, &queue_depth, &device_type);
if (dev) { if (dev) {
if (rc == -EBUSY) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(AP_RESET_TIMEOUT);
rc = ap_query_queue(qid, &queue_depth,
&device_type);
}
ap_dev = to_ap_dev(dev); ap_dev = to_ap_dev(dev);
spin_lock_bh(&ap_dev->lock); spin_lock_bh(&ap_dev->lock);
if (rc || ap_dev->unregistered) { if (rc || ap_dev->unregistered) {
spin_unlock_bh(&ap_dev->lock); spin_unlock_bh(&ap_dev->lock);
put_device(dev);
device_unregister(dev); device_unregister(dev);
put_device(dev);
continue; continue;
} else
spin_unlock_bh(&ap_dev->lock);
} }
if (dev) { spin_unlock_bh(&ap_dev->lock);
put_device(dev); put_device(dev);
continue; continue;
} }
...@@ -788,6 +832,8 @@ static void ap_scan_bus(struct work_struct *unused) ...@@ -788,6 +832,8 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->pendingq); INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq); INIT_LIST_HEAD(&ap_dev->requestq);
INIT_LIST_HEAD(&ap_dev->list); INIT_LIST_HEAD(&ap_dev->list);
setup_timer(&ap_dev->timeout, ap_request_timeout,
(unsigned long) ap_dev);
if (device_type == 0) if (device_type == 0)
ap_probe_device_type(ap_dev); ap_probe_device_type(ap_dev);
else else
...@@ -853,7 +899,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) ...@@ -853,7 +899,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) { switch (status.response_code) {
case AP_RESPONSE_NORMAL: case AP_RESPONSE_NORMAL:
atomic_dec(&ap_poll_requests); atomic_dec(&ap_poll_requests);
ap_dev->queue_count--; ap_decrease_queue_count(ap_dev);
list_for_each_entry(ap_msg, &ap_dev->pendingq, list) { list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
if (ap_msg->psmid != ap_dev->reply->psmid) if (ap_msg->psmid != ap_dev->reply->psmid)
continue; continue;
...@@ -904,7 +950,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) ...@@ -904,7 +950,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) { switch (status.response_code) {
case AP_RESPONSE_NORMAL: case AP_RESPONSE_NORMAL:
atomic_inc(&ap_poll_requests); atomic_inc(&ap_poll_requests);
ap_dev->queue_count++; ap_increase_queue_count(ap_dev);
list_move_tail(&ap_msg->list, &ap_dev->pendingq); list_move_tail(&ap_msg->list, &ap_dev->pendingq);
ap_dev->requestq_count--; ap_dev->requestq_count--;
ap_dev->pendingq_count++; ap_dev->pendingq_count++;
...@@ -914,6 +960,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) ...@@ -914,6 +960,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
*flags |= 2; *flags |= 2;
break; break;
case AP_RESPONSE_Q_FULL: case AP_RESPONSE_Q_FULL:
case AP_RESPONSE_RESET_IN_PROGRESS:
*flags |= 2; *flags |= 2;
break; break;
case AP_RESPONSE_MESSAGE_TOO_BIG: case AP_RESPONSE_MESSAGE_TOO_BIG:
...@@ -960,10 +1007,11 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms ...@@ -960,10 +1007,11 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
list_add_tail(&ap_msg->list, &ap_dev->pendingq); list_add_tail(&ap_msg->list, &ap_dev->pendingq);
atomic_inc(&ap_poll_requests); atomic_inc(&ap_poll_requests);
ap_dev->pendingq_count++; ap_dev->pendingq_count++;
ap_dev->queue_count++; ap_increase_queue_count(ap_dev);
ap_dev->total_request_count++; ap_dev->total_request_count++;
break; break;
case AP_RESPONSE_Q_FULL: case AP_RESPONSE_Q_FULL:
case AP_RESPONSE_RESET_IN_PROGRESS:
list_add_tail(&ap_msg->list, &ap_dev->requestq); list_add_tail(&ap_msg->list, &ap_dev->requestq);
ap_dev->requestq_count++; ap_dev->requestq_count++;
ap_dev->total_request_count++; ap_dev->total_request_count++;
...@@ -1045,6 +1093,25 @@ static void ap_poll_timeout(unsigned long unused) ...@@ -1045,6 +1093,25 @@ static void ap_poll_timeout(unsigned long unused)
tasklet_schedule(&ap_tasklet); tasklet_schedule(&ap_tasklet);
} }
/**
* Reset a not responding AP device and move all requests from the
* pending queue to the request queue.
*/
static void ap_reset(struct ap_device *ap_dev)
{
int rc;
ap_dev->reset = AP_RESET_IGNORE;
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;
ap_dev->pendingq_count = 0;
rc = ap_init_queue(ap_dev->qid);
if (rc == -ENODEV)
ap_dev->unregistered = 1;
}
/** /**
* Poll all AP devices on the bus in a round robin fashion. Continue * Poll all AP devices on the bus in a round robin fashion. Continue
* polling until bit 2^0 of the control flags is not set. If bit 2^1 * polling until bit 2^0 of the control flags is not set. If bit 2^1
...@@ -1056,6 +1123,8 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags) ...@@ -1056,6 +1123,8 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
if (!ap_dev->unregistered) { if (!ap_dev->unregistered) {
if (ap_poll_queue(ap_dev, flags)) if (ap_poll_queue(ap_dev, flags))
ap_dev->unregistered = 1; ap_dev->unregistered = 1;
if (ap_dev->reset == AP_RESET_DO)
ap_reset(ap_dev);
} }
spin_unlock(&ap_dev->lock); spin_unlock(&ap_dev->lock);
return 0; return 0;
...@@ -1147,6 +1216,17 @@ static void ap_poll_thread_stop(void) ...@@ -1147,6 +1216,17 @@ static void ap_poll_thread_stop(void)
mutex_unlock(&ap_poll_thread_mutex); mutex_unlock(&ap_poll_thread_mutex);
} }
/**
* Handling of request timeouts
*/
static void ap_request_timeout(unsigned long data)
{
struct ap_device *ap_dev = (struct ap_device *) data;
if (ap_dev->reset == AP_RESET_ARMED)
ap_dev->reset = AP_RESET_DO;
}
static void ap_reset_domain(void) static void ap_reset_domain(void)
{ {
int i; int i;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#define AP_DEVICES 64 /* Number of AP devices. */ #define AP_DEVICES 64 /* Number of AP devices. */
#define AP_DOMAINS 16 /* Number of AP domains. */ #define AP_DOMAINS 16 /* Number of AP domains. */
#define AP_MAX_RESET 90 /* Maximum number of resets. */ #define AP_MAX_RESET 90 /* Maximum number of resets. */
#define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */
#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */
#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */
...@@ -83,6 +84,13 @@ struct ap_queue_status { ...@@ -83,6 +84,13 @@ struct ap_queue_status {
#define AP_DEVICE_TYPE_CEX2A 6 #define AP_DEVICE_TYPE_CEX2A 6
#define AP_DEVICE_TYPE_CEX2C 7 #define AP_DEVICE_TYPE_CEX2C 7
/**
* AP reset flag states
*/
#define AP_RESET_IGNORE 0 /* request timeout will be ignored */
#define AP_RESET_ARMED 1 /* request timeout timer is active */
#define AP_RESET_DO 2 /* AP reset required */
struct ap_device; struct ap_device;
struct ap_message; struct ap_message;
...@@ -95,6 +103,7 @@ struct ap_driver { ...@@ -95,6 +103,7 @@ struct ap_driver {
/* receive is called from tasklet context */ /* receive is called from tasklet context */
void (*receive)(struct ap_device *, struct ap_message *, void (*receive)(struct ap_device *, struct ap_message *,
struct ap_message *); struct ap_message *);
int request_timeout; /* request timeout in jiffies */
}; };
#define to_ap_drv(x) container_of((x), struct ap_driver, driver) #define to_ap_drv(x) container_of((x), struct ap_driver, driver)
...@@ -112,6 +121,8 @@ struct ap_device { ...@@ -112,6 +121,8 @@ struct ap_device {
int queue_depth; /* AP queue depth.*/ int queue_depth; /* AP queue depth.*/
int device_type; /* AP device type. */ int device_type; /* AP device type. */
int unregistered; /* marks AP device as unregistered */ int unregistered; /* marks AP device as unregistered */
struct timer_list timeout; /* Timer for request timeouts. */
int reset; /* Reset required after req. timeout. */
int queue_count; /* # messages currently on AP queue. */ int queue_count; /* # messages currently on AP queue. */
......
...@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_cex2a_driver = { ...@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_cex2a_driver = {
.remove = zcrypt_cex2a_remove, .remove = zcrypt_cex2a_remove,
.receive = zcrypt_cex2a_receive, .receive = zcrypt_cex2a_receive,
.ids = zcrypt_cex2a_ids, .ids = zcrypt_cex2a_ids,
.request_timeout = CEX2A_CLEANUP_TIME,
}; };
/** /**
...@@ -306,18 +307,13 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, ...@@ -306,18 +307,13 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&work); init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&work);
&work, CEX2A_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata, rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength); mex->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
kfree(ap_msg.message); kfree(ap_msg.message);
return rc; return rc;
...@@ -348,18 +344,13 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, ...@@ -348,18 +344,13 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&work); init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&work);
&work, CEX2A_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata, rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength); crt->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
kfree(ap_msg.message); kfree(ap_msg.message);
return rc; return rc;
......
...@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_pcica_driver = { ...@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_pcica_driver = {
.remove = zcrypt_pcica_remove, .remove = zcrypt_pcica_remove,
.receive = zcrypt_pcica_receive, .receive = zcrypt_pcica_receive,
.ids = zcrypt_pcica_ids, .ids = zcrypt_pcica_ids,
.request_timeout = PCICA_CLEANUP_TIME,
}; };
/** /**
...@@ -290,18 +291,13 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev, ...@@ -290,18 +291,13 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&work); init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&work);
&work, PCICA_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata, rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength); mex->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
kfree(ap_msg.message); kfree(ap_msg.message);
return rc; return rc;
...@@ -332,18 +328,13 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev, ...@@ -332,18 +328,13 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&work); init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&work);
&work, PCICA_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata, rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength); crt->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
kfree(ap_msg.message); kfree(ap_msg.message);
return rc; return rc;
......
...@@ -82,6 +82,7 @@ static struct ap_driver zcrypt_pcicc_driver = { ...@@ -82,6 +82,7 @@ static struct ap_driver zcrypt_pcicc_driver = {
.remove = zcrypt_pcicc_remove, .remove = zcrypt_pcicc_remove,
.receive = zcrypt_pcicc_receive, .receive = zcrypt_pcicc_receive,
.ids = zcrypt_pcicc_ids, .ids = zcrypt_pcicc_ids,
.request_timeout = PCICC_CLEANUP_TIME,
}; };
/** /**
...@@ -501,18 +502,13 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev, ...@@ -501,18 +502,13 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&work); init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&work);
&work, PCICC_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata, rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength); mex->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
free_page((unsigned long) ap_msg.message); free_page((unsigned long) ap_msg.message);
return rc; return rc;
...@@ -544,18 +540,13 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev, ...@@ -544,18 +540,13 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&work); init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&work);
&work, PCICC_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata, rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength); crt->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
free_page((unsigned long) ap_msg.message); free_page((unsigned long) ap_msg.message);
return rc; return rc;
......
...@@ -93,6 +93,7 @@ static struct ap_driver zcrypt_pcixcc_driver = { ...@@ -93,6 +93,7 @@ static struct ap_driver zcrypt_pcixcc_driver = {
.remove = zcrypt_pcixcc_remove, .remove = zcrypt_pcixcc_remove,
.receive = zcrypt_pcixcc_receive, .receive = zcrypt_pcixcc_receive,
.ids = zcrypt_pcixcc_ids, .ids = zcrypt_pcixcc_ids,
.request_timeout = PCIXCC_CLEANUP_TIME,
}; };
/** /**
...@@ -641,18 +642,13 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev, ...@@ -641,18 +642,13 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&resp_type.work); init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&resp_type.work);
&resp_type.work, PCIXCC_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength); mex->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
free_page((unsigned long) ap_msg.message); free_page((unsigned long) ap_msg.message);
return rc; return rc;
...@@ -685,18 +681,13 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, ...@@ -685,18 +681,13 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&resp_type.work); init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&resp_type.work);
&resp_type.work, PCIXCC_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength); crt->outputdatalength);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
free_page((unsigned long) ap_msg.message); free_page((unsigned long) ap_msg.message);
return rc; return rc;
...@@ -729,17 +720,12 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, ...@@ -729,17 +720,12 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
goto out_free; goto out_free;
init_completion(&resp_type.work); init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg); ap_queue_message(zdev->ap_dev, &ap_msg);
rc = wait_for_completion_interruptible_timeout( rc = wait_for_completion_interruptible(&resp_type.work);
&resp_type.work, PCIXCC_CLEANUP_TIME); if (rc == 0)
if (rc > 0)
rc = convert_response_xcrb(zdev, &ap_msg, xcRB); rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
else { else
/* Signal pending or message timed out. */ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg); ap_cancel_message(zdev->ap_dev, &ap_msg);
if (rc == 0)
/* Message timed out. */
rc = -ETIME;
}
out_free: out_free:
memset(ap_msg.message, 0x0, ap_msg.length); memset(ap_msg.message, 0x0, ap_msg.length);
kfree(ap_msg.message); kfree(ap_msg.message);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册