s390/zcrypt: Fixed attrition of AP adapters and domains
authorIngo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com>
Fri, 14 Oct 2016 12:34:51 +0000 (14:34 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 14 Dec 2016 15:33:39 +0000 (16:33 +0100)
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 <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/ap_card.c
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/zcrypt_api.c

index 54b17e1427928b87ef5109e312933cf6a1101e7d..4dc7c88fb0544622fc2ab9cd641b7212a2f14c32 100644 (file)
@@ -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. */
index 731dc0dbfb75558406042ef7e2af8c04658e49f5..0110d44172a3a5bd3b9c5ffa82464efeba34f461 100644 (file)
@@ -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);
 }
index 8f95a071b67091e85511446c7fd4f0fa957eecab..b58a917dc5107318b31d5a3805f19c55771e11b7 100644 (file)
@@ -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);
index 403af9d1ebde100303e053329c0798c626d11ce3..c7b5e70f2938283af0492111c07b5458913e5f28 100644 (file)
@@ -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;