From e47de21dd35bad6d1e71482a66699cd04e83ea40 Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Fri, 14 Oct 2016 14:34:51 +0200 Subject: [PATCH] s390/zcrypt: Fixed attrition of AP adapters and domains Currently the first eligible AP adapter respectively domain will be selected to service requests. In case of sequential workload, the very same adapter/domain will be used. The adapter/domain selection algorithm now considers the completed transactions per adaper/domain and therefore ensures a homogeneous utilization. Signed-off-by: Ingo Tuchscherer Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.h | 3 +- drivers/s390/crypto/ap_card.c | 4 +- drivers/s390/crypto/ap_queue.c | 1 + drivers/s390/crypto/zcrypt_api.c | 63 ++++++++++++++++++++++---------- 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 54b17e142792..4dc7c88fb054 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -195,6 +195,7 @@ struct ap_card { unsigned int functions; /* AP device function bitfield. */ int queue_depth; /* AP queue depth.*/ int id; /* AP card number. */ + atomic_t total_request_count; /* # requests ever for this AP device.*/ }; #define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device) @@ -211,7 +212,7 @@ struct ap_queue { enum ap_state state; /* State of the AP device. */ int pendingq_count; /* # requests on pendingq list. */ int requestq_count; /* # requests on requestq list. */ - int total_request_count; /* # requests ever for this AP device. */ + int total_request_count; /* # requests ever for this AP device.*/ int request_timeout; /* Request timout in jiffies. */ struct timer_list timeout; /* Timer for request timeouts. */ struct list_head pendingq; /* List of message sent to AP queue. */ diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c index 731dc0dbfb75..0110d44172a3 100644 --- a/drivers/s390/crypto/ap_card.c +++ b/drivers/s390/crypto/ap_card.c @@ -63,13 +63,11 @@ static ssize_t ap_request_count_show(struct device *dev, char *buf) { struct ap_card *ac = to_ap_card(dev); - struct ap_queue *aq; unsigned int req_cnt; req_cnt = 0; spin_lock_bh(&ap_list_lock); - for_each_ap_queue(aq, ac) - req_cnt += aq->total_request_count; + req_cnt = atomic_read(&ac->total_request_count); spin_unlock_bh(&ap_list_lock); return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); } diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 8f95a071b670..b58a917dc510 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -625,6 +625,7 @@ void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) list_add_tail(&ap_msg->list, &aq->requestq); aq->requestq_count++; aq->total_request_count++; + atomic_inc(&aq->card->total_request_count); /* Send/receive as many request from the queue as possible. */ ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL)); spin_unlock_bh(&aq->lock); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 403af9d1ebde..c7b5e70f2938 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -188,6 +188,34 @@ static inline void zcrypt_drop_queue(struct zcrypt_card *zc, module_put(mod); } +static inline bool zcrypt_card_compare(struct zcrypt_card *zc, + struct zcrypt_card *pref_zc, + unsigned weight, unsigned pref_weight) +{ + if (!pref_zc) + return 0; + weight += atomic_read(&zc->load); + pref_weight += atomic_read(&pref_zc->load); + if (weight == pref_weight) + return atomic_read(&zc->card->total_request_count) > + atomic_read(&pref_zc->card->total_request_count); + return weight > pref_weight; +} + +static inline bool zcrypt_queue_compare(struct zcrypt_queue *zq, + struct zcrypt_queue *pref_zq, + unsigned weight, unsigned pref_weight) +{ + if (!pref_zq) + return 0; + weight += atomic_read(&zq->load); + pref_weight += atomic_read(&pref_zq->load); + if (weight == pref_weight) + return &zq->queue->total_request_count > + &pref_zq->queue->total_request_count; + return weight > pref_weight; +} + /* * zcrypt ioctls. */ @@ -225,15 +253,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) continue; /* get weight index of the card device */ weight = zc->speed_rating[func_code]; - if (pref_zc && atomic_read(&zc->load) + weight >= - atomic_read(&pref_zc->load) + pref_weight) + if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight)) continue; for_each_zcrypt_queue(zq, zc) { /* check if device is online and eligible */ if (!zq->online) continue; - if (pref_zq && atomic_read(&zq->load) + weight >= - atomic_read(&pref_zq->load) + pref_weight) + if (zcrypt_queue_compare(zq, pref_zq, + weight, pref_weight)) continue; pref_zc = zc; pref_zq = zq; @@ -289,15 +316,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) continue; /* get weight index of the card device */ weight = zc->speed_rating[func_code]; - if (pref_zc && atomic_read(&zc->load) + weight >= - atomic_read(&pref_zc->load) + pref_weight) + if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight)) continue; for_each_zcrypt_queue(zq, zc) { /* check if device is online and eligible */ if (!zq->online) continue; - if (pref_zq && atomic_read(&zq->load) + weight >= - atomic_read(&pref_zq->load) + pref_weight) + if (zcrypt_queue_compare(zq, pref_zq, + weight, pref_weight)) continue; pref_zc = zc; pref_zq = zq; @@ -346,8 +372,7 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) continue; /* get weight index of the card device */ weight = speed_idx_cca(func_code) * zc->speed_rating[SECKEY]; - if (pref_zc && atomic_read(&zc->load) + weight >= - atomic_read(&pref_zc->load) + pref_weight) + if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight)) continue; for_each_zcrypt_queue(zq, zc) { /* check if device is online and eligible */ @@ -355,8 +380,8 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) ((*domain != (unsigned short) AUTOSELECT) && (*domain != AP_QID_QUEUE(zq->queue->qid)))) continue; - if (pref_zq && atomic_read(&zq->load) + weight >= - atomic_read(&pref_zq->load) + pref_weight) + if (zcrypt_queue_compare(zq, pref_zq, + weight, pref_weight)) continue; pref_zc = zc; pref_zq = zq; @@ -450,8 +475,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) continue; /* get weight index of the card device */ weight = speed_idx_ep11(func_code) * zc->speed_rating[SECKEY]; - if (pref_zc && atomic_read(&zc->load) + weight >= - atomic_read(&pref_zc->load) + pref_weight) + if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight)) continue; for_each_zcrypt_queue(zq, zc) { /* check if device is online and eligible */ @@ -460,8 +484,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) !is_desired_ep11_queue(zq->queue->qid, target_num, targets))) continue; - if (pref_zq && atomic_read(&zq->load) + weight >= - atomic_read(&pref_zq->load) + pref_weight) + if (zcrypt_queue_compare(zq, pref_zq, + weight, pref_weight)) continue; pref_zc = zc; pref_zq = zq; @@ -510,15 +534,14 @@ static long zcrypt_rng(char *buffer) continue; /* get weight index of the card device */ weight = zc->speed_rating[func_code]; - if (pref_zc && atomic_read(&zc->load) + weight >= - atomic_read(&pref_zc->load) + pref_weight) + if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight)) continue; for_each_zcrypt_queue(zq, zc) { /* check if device is online and eligible */ if (!zq->online) continue; - if (pref_zq && atomic_read(&zq->load) + weight >= - atomic_read(&pref_zq->load) + pref_weight) + if (zcrypt_queue_compare(zq, pref_zq, + weight, pref_weight)) continue; pref_zc = zc; pref_zq = zq; -- 2.39.5