Commit e47de21d authored by Ingo Tuchscherer's avatar Ingo Tuchscherer Committed by Martin Schwidefsky

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: default avatarIngo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent b886a9d1
...@@ -195,6 +195,7 @@ struct ap_card { ...@@ -195,6 +195,7 @@ struct ap_card {
unsigned int functions; /* AP device function bitfield. */ unsigned int functions; /* AP device function bitfield. */
int queue_depth; /* AP queue depth.*/ int queue_depth; /* AP queue depth.*/
int id; /* AP card number. */ 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) #define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device)
...@@ -211,7 +212,7 @@ struct ap_queue { ...@@ -211,7 +212,7 @@ struct ap_queue {
enum ap_state state; /* State of the AP device. */ enum ap_state state; /* State of the AP device. */
int pendingq_count; /* # requests on pendingq list. */ int pendingq_count; /* # requests on pendingq list. */
int requestq_count; /* # requests on requestq 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. */ int request_timeout; /* Request timout in jiffies. */
struct timer_list timeout; /* Timer for request timeouts. */ struct timer_list timeout; /* Timer for request timeouts. */
struct list_head pendingq; /* List of message sent to AP queue. */ struct list_head pendingq; /* List of message sent to AP queue. */
......
...@@ -63,13 +63,11 @@ static ssize_t ap_request_count_show(struct device *dev, ...@@ -63,13 +63,11 @@ static ssize_t ap_request_count_show(struct device *dev,
char *buf) char *buf)
{ {
struct ap_card *ac = to_ap_card(dev); struct ap_card *ac = to_ap_card(dev);
struct ap_queue *aq;
unsigned int req_cnt; unsigned int req_cnt;
req_cnt = 0; req_cnt = 0;
spin_lock_bh(&ap_list_lock); spin_lock_bh(&ap_list_lock);
for_each_ap_queue(aq, ac) req_cnt = atomic_read(&ac->total_request_count);
req_cnt += aq->total_request_count;
spin_unlock_bh(&ap_list_lock); spin_unlock_bh(&ap_list_lock);
return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt);
} }
......
...@@ -625,6 +625,7 @@ void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) ...@@ -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); list_add_tail(&ap_msg->list, &aq->requestq);
aq->requestq_count++; aq->requestq_count++;
aq->total_request_count++; aq->total_request_count++;
atomic_inc(&aq->card->total_request_count);
/* Send/receive as many request from the queue as possible. */ /* Send/receive as many request from the queue as possible. */
ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL)); ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL));
spin_unlock_bh(&aq->lock); spin_unlock_bh(&aq->lock);
......
...@@ -188,6 +188,34 @@ static inline void zcrypt_drop_queue(struct zcrypt_card *zc, ...@@ -188,6 +188,34 @@ static inline void zcrypt_drop_queue(struct zcrypt_card *zc,
module_put(mod); 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. * zcrypt ioctls.
*/ */
...@@ -225,15 +253,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) ...@@ -225,15 +253,14 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
continue; continue;
/* get weight index of the card device */ /* get weight index of the card device */
weight = zc->speed_rating[func_code]; weight = zc->speed_rating[func_code];
if (pref_zc && atomic_read(&zc->load) + weight >= if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
atomic_read(&pref_zc->load) + pref_weight)
continue; continue;
for_each_zcrypt_queue(zq, zc) { for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */ /* check if device is online and eligible */
if (!zq->online) if (!zq->online)
continue; continue;
if (pref_zq && atomic_read(&zq->load) + weight >= if (zcrypt_queue_compare(zq, pref_zq,
atomic_read(&pref_zq->load) + pref_weight) weight, pref_weight))
continue; continue;
pref_zc = zc; pref_zc = zc;
pref_zq = zq; pref_zq = zq;
...@@ -289,15 +316,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) ...@@ -289,15 +316,14 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
continue; continue;
/* get weight index of the card device */ /* get weight index of the card device */
weight = zc->speed_rating[func_code]; weight = zc->speed_rating[func_code];
if (pref_zc && atomic_read(&zc->load) + weight >= if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
atomic_read(&pref_zc->load) + pref_weight)
continue; continue;
for_each_zcrypt_queue(zq, zc) { for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */ /* check if device is online and eligible */
if (!zq->online) if (!zq->online)
continue; continue;
if (pref_zq && atomic_read(&zq->load) + weight >= if (zcrypt_queue_compare(zq, pref_zq,
atomic_read(&pref_zq->load) + pref_weight) weight, pref_weight))
continue; continue;
pref_zc = zc; pref_zc = zc;
pref_zq = zq; pref_zq = zq;
...@@ -346,8 +372,7 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) ...@@ -346,8 +372,7 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
continue; continue;
/* get weight index of the card device */ /* get weight index of the card device */
weight = speed_idx_cca(func_code) * zc->speed_rating[SECKEY]; weight = speed_idx_cca(func_code) * zc->speed_rating[SECKEY];
if (pref_zc && atomic_read(&zc->load) + weight >= if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
atomic_read(&pref_zc->load) + pref_weight)
continue; continue;
for_each_zcrypt_queue(zq, zc) { for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */ /* check if device is online and eligible */
...@@ -355,8 +380,8 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) ...@@ -355,8 +380,8 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
((*domain != (unsigned short) AUTOSELECT) && ((*domain != (unsigned short) AUTOSELECT) &&
(*domain != AP_QID_QUEUE(zq->queue->qid)))) (*domain != AP_QID_QUEUE(zq->queue->qid))))
continue; continue;
if (pref_zq && atomic_read(&zq->load) + weight >= if (zcrypt_queue_compare(zq, pref_zq,
atomic_read(&pref_zq->load) + pref_weight) weight, pref_weight))
continue; continue;
pref_zc = zc; pref_zc = zc;
pref_zq = zq; pref_zq = zq;
...@@ -450,8 +475,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) ...@@ -450,8 +475,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
continue; continue;
/* get weight index of the card device */ /* get weight index of the card device */
weight = speed_idx_ep11(func_code) * zc->speed_rating[SECKEY]; weight = speed_idx_ep11(func_code) * zc->speed_rating[SECKEY];
if (pref_zc && atomic_read(&zc->load) + weight >= if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
atomic_read(&pref_zc->load) + pref_weight)
continue; continue;
for_each_zcrypt_queue(zq, zc) { for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */ /* check if device is online and eligible */
...@@ -460,8 +484,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) ...@@ -460,8 +484,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
!is_desired_ep11_queue(zq->queue->qid, !is_desired_ep11_queue(zq->queue->qid,
target_num, targets))) target_num, targets)))
continue; continue;
if (pref_zq && atomic_read(&zq->load) + weight >= if (zcrypt_queue_compare(zq, pref_zq,
atomic_read(&pref_zq->load) + pref_weight) weight, pref_weight))
continue; continue;
pref_zc = zc; pref_zc = zc;
pref_zq = zq; pref_zq = zq;
...@@ -510,15 +534,14 @@ static long zcrypt_rng(char *buffer) ...@@ -510,15 +534,14 @@ static long zcrypt_rng(char *buffer)
continue; continue;
/* get weight index of the card device */ /* get weight index of the card device */
weight = zc->speed_rating[func_code]; weight = zc->speed_rating[func_code];
if (pref_zc && atomic_read(&zc->load) + weight >= if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
atomic_read(&pref_zc->load) + pref_weight)
continue; continue;
for_each_zcrypt_queue(zq, zc) { for_each_zcrypt_queue(zq, zc) {
/* check if device is online and eligible */ /* check if device is online and eligible */
if (!zq->online) if (!zq->online)
continue; continue;
if (pref_zq && atomic_read(&zq->load) + weight >= if (zcrypt_queue_compare(zq, pref_zq,
atomic_read(&pref_zq->load) + pref_weight) weight, pref_weight))
continue; continue;
pref_zc = zc; pref_zc = zc;
pref_zq = zq; pref_zq = zq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment