diff options
| author | Ingo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com> | 2016-10-14 14:34:51 +0200 | 
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-12-14 16:33:39 +0100 | 
| commit | e47de21dd35bad6d1e71482a66699cd04e83ea40 (patch) | |
| tree | 1089dd285e8cde50690b546db76285efa198b8cc /drivers/s390/crypto | |
| parent | b886a9d1560d6c7d5d58344b16f53ab2cba5b666 (diff) | |
| download | linux-e47de21dd35bad6d1e71482a66699cd04e83ea40.tar.bz2 | |
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 <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/crypto')
| -rw-r--r-- | drivers/s390/crypto/ap_bus.h | 3 | ||||
| -rw-r--r-- | drivers/s390/crypto/ap_card.c | 4 | ||||
| -rw-r--r-- | drivers/s390/crypto/ap_queue.c | 1 | ||||
| -rw-r--r-- | 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; |