Commit 6acbe21f authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

s390/zcrypt: remove duplicate low level functions



ap_test_queue, ap_query_facilities, __ap_query_functions all use
the same PQAP(TAPQ) command. Consolidate the three into a single
ap_test_queue function that returns the AP status and the 64-bit
result. The exception table entry for PQAP(TAPQ) can be avoided
if the T bit for the APFT facility is set only if test_facility(15)
indicated that the facility is present.

Integrate ap_query_function into ap_query queue to avoid calling
PQAP(TAPQ) twice.

Reviewed-by: default avatarIngo Tuchscherer <ingo.tuchscherer@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 29b0a825
Loading
Loading
Loading
Loading
+32 −108
Original line number Diff line number Diff line
@@ -182,43 +182,26 @@ static int ap_configuration_available(void)
/**
 * ap_test_queue(): Test adjunct processor queue.
 * @qid: The AP queue number
 * @queue_depth: Pointer to queue depth value
 * @device_type: Pointer to device type value
 * @info: Pointer to queue descriptor
 *
 * Returns AP queue status structure.
 */
static inline struct ap_queue_status
ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
ap_test_queue(ap_qid_t qid, unsigned long *info)
{
	register unsigned long reg0 asm ("0") = qid;
	register struct ap_queue_status reg1 asm ("1");
	register unsigned long reg2 asm ("2") = 0UL;

	if (test_facility(15))
		reg0 |= 1UL << 23;		/* set APFT T bit*/
	asm volatile(".long 0xb2af0000"		/* PQAP(TAPQ) */
		     : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
	*device_type = (int) (reg2 >> 24);
	*queue_depth = (int) (reg2 & 0xff);
	if (info)
		*info = reg2;
	return reg1;
}

/**
 * ap_query_facilities(): PQAP(TAPQ) query facilities.
 * @qid: The AP queue number
 *
 * Returns content of general register 2 after the PQAP(TAPQ)
 * instruction was called.
 */
static inline unsigned long ap_query_facilities(ap_qid_t qid)
{
	register unsigned long reg0 asm ("0") = qid | 0x00800000UL;
	register unsigned long reg1 asm ("1");
	register unsigned long reg2 asm ("2") = 0UL;

	asm volatile(".long 0xb2af0000"  /* PQAP(TAPQ) */
		     : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
	return reg2;
}

/**
 * ap_reset_queue(): Reset adjunct processor queue.
 * @qid: The AP queue number
@@ -259,25 +242,6 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
	return reg1_out;
}

static inline struct ap_queue_status
__ap_query_functions(ap_qid_t qid, unsigned int *functions)
{
	register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
	register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
	register unsigned long reg2 asm ("2");

	asm volatile(
		".long 0xb2af0000\n"		/* PQAP(TAPQ) */
		"0:\n"
		EX_TABLE(0b, 0b)
		: "+d" (reg0), "+d" (reg1), "=d" (reg2)
		:
		: "cc");

	*functions = (unsigned int)(reg2 >> 32);
	return reg1;
}

static inline int __ap_query_configuration(struct ap_config_info *config)
{
	register unsigned long reg0 asm ("0") = 0x04000000UL;
@@ -296,42 +260,6 @@ static inline int __ap_query_configuration(struct ap_config_info *config)
	return reg1;
}

/**
 * ap_query_functions(): Query supported functions.
 * @qid: The AP queue number
 * @functions: Pointer to functions field.
 *
 * Returns
 *   0	     on success.
 *   -ENODEV  if queue not valid.
 *   -EBUSY   if device busy.
 *   -EINVAL  if query function is not supported
 */
static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
{
	struct ap_queue_status status;

	status = __ap_query_functions(qid, functions);

	if (ap_queue_status_invalid_test(&status))
		return -ENODEV;

	switch (status.response_code) {
	case AP_RESPONSE_NORMAL:
		return 0;
	case AP_RESPONSE_Q_NOT_AVAIL:
	case AP_RESPONSE_DECONFIGURED:
	case AP_RESPONSE_CHECKSTOPPED:
	case AP_RESPONSE_INVALID_ADDRESS:
		return -ENODEV;
	case AP_RESPONSE_RESET_IN_PROGRESS:
	case AP_RESPONSE_BUSY:
	case AP_RESPONSE_OTHERWISE_CHANGED:
	default:
		return -EBUSY;
	}
}

/**
 * ap_queue_enable_interruption(): Enable interruption on an AP.
 * @qid: The AP queue number
@@ -515,17 +443,20 @@ static inline void ap_schedule_poll_timer(void)
 * @qid: The AP queue number
 * @queue_depth: Pointer to queue depth value
 * @device_type: Pointer to device type value
 * @facilities: Pointer to facility indicator
 */
static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type,
			  unsigned int *facilities)
{
	struct ap_queue_status status;
	int t_depth, t_device_type;
	unsigned long info;

	status = ap_test_queue(qid, &t_depth, &t_device_type);
	status = ap_test_queue(qid, &info);
	switch (status.response_code) {
	case AP_RESPONSE_NORMAL:
		*queue_depth = t_depth + 1;
		*device_type = t_device_type;
		*queue_depth = (int)(info & 0xff);
		*device_type = (int)((info >> 24) & 0xff);
		*facilities = (unsigned int)(info >> 32);
		return 0;
	case AP_RESPONSE_Q_NOT_AVAIL:
	case AP_RESPONSE_DECONFIGURED:
@@ -1184,6 +1115,7 @@ static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);

static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
{
	struct ap_queue_status status;
	ap_qid_t qid;
	int i, nd, max_domain_id = -1;
	unsigned long fbits;
@@ -1194,7 +1126,9 @@ static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
				if (!ap_test_config_card_id(i))
					continue;
				qid = AP_MKQID(i, ap_domain_index);
				fbits = ap_query_facilities(qid);
				status = ap_test_queue(qid, &fbits);
				if (status.response_code != AP_RESPONSE_NORMAL)
					continue;
				if (fbits & (1UL << 57)) {
					/* the N bit is 0, Nd field is filled */
					nd = (int)((fbits & 0x00FF0000UL)>>16);
@@ -1254,9 +1188,9 @@ static void ap_query_configuration(void)
 */
static int ap_select_domain(void)
{
	int queue_depth, device_type, count, max_count, best_domain;
	ap_qid_t qid;
	int rc, i, j;
	int count, max_count, best_domain;
	struct ap_queue_status status;
	int i, j;

	/* IF APXA isn't installed, only 16 domains could be defined */
	if (!ap_configuration->ap_extended && (ap_domain_index > 15))
@@ -1279,9 +1213,8 @@ static int ap_select_domain(void)
		for (j = 0; j < AP_DEVICES; j++) {
			if (!ap_test_config_card_id(j))
				continue;
			qid = AP_MKQID(j, i);
			rc = ap_query_queue(qid, &queue_depth, &device_type);
			if (rc)
			status = ap_test_queue(AP_MKQID(j, i), NULL);
			if (status.response_code != AP_RESPONSE_NORMAL)
				continue;
			count++;
		}
@@ -1438,7 +1371,8 @@ static void ap_scan_bus(struct work_struct *unused)
				      (void *)(unsigned long)qid,
				      __ap_scan_bus);
		if (ap_test_config_card_id(i))
			rc = ap_query_queue(qid, &queue_depth, &device_type);
			rc = ap_query_queue(qid, &queue_depth, &device_type,
					    &device_functions);
		else
			rc = -ENODEV;
		if (dev) {
@@ -1468,6 +1402,9 @@ static void ap_scan_bus(struct work_struct *unused)
			continue;
		}
		ap_dev->queue_depth = queue_depth;
		ap_dev->raw_hwtype = device_type;
		ap_dev->device_type = device_type;
		ap_dev->functions = device_functions;
		ap_dev->unregistered = 1;
		spin_lock_init(&ap_dev->lock);
		INIT_LIST_HEAD(&ap_dev->pendingq);
@@ -1475,24 +1412,12 @@ static void ap_scan_bus(struct work_struct *unused)
		INIT_LIST_HEAD(&ap_dev->list);
		setup_timer(&ap_dev->timeout, ap_request_timeout,
			    (unsigned long) ap_dev);
		switch (device_type) {
		case 0:
		if (ap_dev->device_type == 0)
			/* device type probing for old cards */
			if (ap_probe_device_type(ap_dev)) {
				kfree(ap_dev);
				continue;
			}
			break;
		default:
			ap_dev->device_type = device_type;
		}
		ap_dev->raw_hwtype = device_type;

		rc = ap_query_functions(qid, &device_functions);
		if (!rc)
			ap_dev->functions = device_functions;
		else
			ap_dev->functions = 0u;

		ap_dev->device.bus = &ap_bus_type;
		ap_dev->device.parent = ap_root_device;
@@ -1640,12 +1565,11 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
 */
static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
{
	int rc, depth, type;
	struct ap_queue_status status;

	int rc;

	if (ap_dev->reset == AP_RESET_IN_PROGRESS) {
		status = ap_test_queue(ap_dev->qid, &depth, &type);
		status = ap_test_queue(ap_dev->qid, NULL);
		switch (status.response_code) {
		case AP_RESPONSE_NORMAL:
			ap_dev->reset = AP_RESET_IGNORE;
@@ -1676,7 +1600,7 @@ static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)

	if ((ap_dev->reset != AP_RESET_IN_PROGRESS) &&
		(ap_dev->interrupt == AP_INTR_IN_PROGRESS)) {
		status = ap_test_queue(ap_dev->qid, &depth, &type);
		status = ap_test_queue(ap_dev->qid, NULL);
		if (ap_using_interrupts()) {
			if (status.int_enabled == 1)
				ap_dev->interrupt = AP_INTR_ENABLED;
+0 −9
Original line number Diff line number Diff line
@@ -75,15 +75,6 @@ struct ap_queue_status {
	unsigned int pad2		: 16;
} __packed;

#define AP_QUEUE_STATUS_INVALID \
		{ 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }

static inline
int ap_queue_status_invalid_test(struct ap_queue_status *status)
{
	struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
	return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
}

#define AP_MAX_BITS 31
static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)