Commit d4c53ae8 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Alexander Gordeev
Browse files

s390/ap: store TAPQ hwinfo in struct ap_card



As of now the AP card struct held only part of the
queue's hwinfo (that is the GR2 register content returned
with an TAPQ invocation). This patch reworks struct ap_card
to hold the whole hwinfo now.

As there is a nice bit field union on top of this
ap_tapq_hwinfo struct, all the ugly bit checkings can
now get replaced by simple evaluations of the required
bit field.

Suggested-by: default avatarIngo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parent a0d8f4ee
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ static inline bool ap_instructions_available(void)
}

/* TAPQ register GR2 response struct */
struct ap_tapq_gr2 {
struct ap_tapq_hwinfo {
	union {
		unsigned long value;
		struct {
@@ -96,11 +96,13 @@ struct ap_tapq_gr2 {
			unsigned int apinfo : 32; /* ap type, ... */
		};
		struct {
			unsigned int s	   :  1; /* APSC */
			unsigned int m	   :  1; /* AP4KM */
			unsigned int c	   :  1; /* AP4KC */
			unsigned int mode  :  3;
			unsigned int n	   :  1; /* APXA */
			unsigned int apsc  :  1; /* APSC */
			unsigned int mex4k :  1; /* AP4KM */
			unsigned int crt4k :  1; /* AP4KC */
			unsigned int cca   :  1; /* D */
			unsigned int accel :  1; /* A */
			unsigned int ep11  :  1; /* X */
			unsigned int apxa  :  1; /* APXA */
			unsigned int	   :  1;
			unsigned int class :  8;
			unsigned int bs	   :  2; /* SE bind/assoc */
@@ -126,11 +128,12 @@ struct ap_tapq_gr2 {
/**
 * ap_tapq(): Test adjunct processor queue.
 * @qid: The AP queue number
 * @info: Pointer to queue descriptor
 * @info: Pointer to tapq hwinfo struct
 *
 * Returns AP queue status structure.
 */
static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *info)
static inline struct ap_queue_status ap_tapq(ap_qid_t qid,
					     struct ap_tapq_hwinfo *info)
{
	union ap_queue_status_reg reg1;
	unsigned long reg2;
@@ -158,7 +161,7 @@ static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *i
 * Returns AP queue status structure.
 */
static inline struct ap_queue_status ap_test_queue(ap_qid_t qid, int tbit,
						   struct ap_tapq_gr2 *info)
						   struct ap_tapq_hwinfo *info)
{
	if (tbit)
		qid |= 1UL << 23; /* set T bit*/
+31 −38
Original line number Diff line number Diff line
@@ -357,13 +357,12 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);
 *	   -1 invalid APQN, TAPQ error or AP queue status which
 *	      indicates there is no APQN.
 */
static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
			 int *q_depth, int *q_ml, bool *q_decfg, bool *q_cstop)
static int ap_queue_info(ap_qid_t qid, struct ap_tapq_hwinfo *hwinfo,
			 bool *decfg, bool *cstop)
{
	struct ap_queue_status status;
	struct ap_tapq_gr2 tapq_info;

	tapq_info.value = 0;
	hwinfo->value = 0;

	/* make sure we don't run into a specifiation exception */
	if (AP_QID_CARD(qid) > ap_max_adapter_id ||
@@ -371,7 +370,7 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
		return -1;

	/* call TAPQ on this APQN */
	status = ap_test_queue(qid, ap_apft_available(), &tapq_info);
	status = ap_test_queue(qid, ap_apft_available(), hwinfo);

	switch (status.response_code) {
	case AP_RESPONSE_NORMAL:
@@ -389,15 +388,11 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
	}

	/* There should be at least one of the mode bits set */
	if (WARN_ON_ONCE(!tapq_info.value))
	if (WARN_ON_ONCE(!hwinfo->value))
		return 0;

	*q_type = tapq_info.at;
	*q_fac = tapq_info.fac;
	*q_depth = tapq_info.qd;
	*q_ml = tapq_info.ml;
	*q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
	*q_cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED;
	*decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
	*cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED;

	return 1;
}
@@ -642,11 +637,11 @@ static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env)
			return rc;

		/* Add MODE=<accel|cca|ep11> */
		if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL))
		if (ac->hwinfo.accel)
			rc = add_uevent_var(env, "MODE=accel");
		else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
		else if (ac->hwinfo.cca)
			rc = add_uevent_var(env, "MODE=cca");
		else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
		else if (ac->hwinfo.ep11)
			rc = add_uevent_var(env, "MODE=ep11");
		if (rc)
			return rc;
@@ -654,11 +649,11 @@ static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env)
		struct ap_queue *aq = to_ap_queue(&ap_dev->device);

		/* Add MODE=<accel|cca|ep11> */
		if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL))
		if (aq->card->hwinfo.accel)
			rc = add_uevent_var(env, "MODE=accel");
		else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
		else if (aq->card->hwinfo.cca)
			rc = add_uevent_var(env, "MODE=cca");
		else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
		else if (aq->card->hwinfo.ep11)
			rc = add_uevent_var(env, "MODE=ep11");
		if (rc)
			return rc;
@@ -1799,12 +1794,12 @@ static inline void ap_scan_rm_card_dev_and_queue_devs(struct ap_card *ac)
 */
static inline void ap_scan_domains(struct ap_card *ac)
{
	int rc, dom, depth, type, ml;
	struct ap_tapq_hwinfo hwinfo;
	bool decfg, chkstop;
	struct ap_queue *aq;
	struct device *dev;
	unsigned int func;
	ap_qid_t qid;
	int rc, dom;

	/*
	 * Go through the configuration for the domains and compare them
@@ -1827,8 +1822,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
			goto put_dev_and_continue;
		}
		/* domain is valid, get info from this APQN */
		rc = ap_queue_info(qid, &type, &func, &depth,
				   &ml, &decfg, &chkstop);
		rc = ap_queue_info(qid, &hwinfo, &decfg, &chkstop);
		switch (rc) {
		case -1:
			if (dev) {
@@ -1955,11 +1949,11 @@ static inline void ap_scan_domains(struct ap_card *ac)
 */
static inline void ap_scan_adapter(int ap)
{
	int rc, dom, depth, type, comp_type, ml;
	struct ap_tapq_hwinfo hwinfo;
	int rc, dom, comp_type;
	bool decfg, chkstop;
	struct ap_card *ac;
	struct device *dev;
	unsigned int func;
	ap_qid_t qid;

	/* Is there currently a card device for this adapter ? */
@@ -1989,8 +1983,7 @@ static inline void ap_scan_adapter(int ap)
	for (dom = 0; dom <= ap_max_domain_id; dom++)
		if (ap_test_config_usage_domain(dom)) {
			qid = AP_MKQID(ap, dom);
			if (ap_queue_info(qid, &type, &func, &depth,
					  &ml, &decfg, &chkstop) > 0)
			if (ap_queue_info(qid, &hwinfo, &decfg, &chkstop) > 0)
				break;
		}
	if (dom > ap_max_domain_id) {
@@ -2006,7 +1999,7 @@ static inline void ap_scan_adapter(int ap)
		}
		return;
	}
	if (!type) {
	if (!hwinfo.at) {
		/* No apdater type info available, an unusable adapter */
		if (ac) {
			AP_DBF_INFO("%s(%d) no valid type (0) info, rm card and queue devs\n",
@@ -2019,18 +2012,18 @@ static inline void ap_scan_adapter(int ap)
		}
		return;
	}
	hwinfo.value &= TAPQ_CARD_HWINFO_MASK; /* filter card specific hwinfo */
	if (ac) {
		/* Check APQN against existing card device for changes */
		if (ac->raw_hwtype != type) {
		if (ac->hwinfo.at != hwinfo.at) {
			AP_DBF_INFO("%s(%d) hwtype %d changed, rm card and queue devs\n",
				    __func__, ap, type);
				    __func__, ap, hwinfo.at);
			ap_scan_rm_card_dev_and_queue_devs(ac);
			put_device(dev);
			ac = NULL;
		} else if ((ac->functions & TAPQ_CARD_FUNC_CMP_MASK) !=
			   (func & TAPQ_CARD_FUNC_CMP_MASK)) {
		} else if (ac->hwinfo.fac != hwinfo.fac) {
			AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devs\n",
				    __func__, ap, func);
				    __func__, ap, hwinfo.fac);
			ap_scan_rm_card_dev_and_queue_devs(ac);
			put_device(dev);
			ac = NULL;
@@ -2064,13 +2057,13 @@ static inline void ap_scan_adapter(int ap)

	if (!ac) {
		/* Build a new card device */
		comp_type = ap_get_compatible_type(qid, type, func);
		comp_type = ap_get_compatible_type(qid, hwinfo.at, hwinfo.fac);
		if (!comp_type) {
			AP_DBF_WARN("%s(%d) type %d, can't get compatibility type\n",
				    __func__, ap, type);
				    __func__, ap, hwinfo.at);
			return;
		}
		ac = ap_card_create(ap, depth, type, comp_type, func, ml);
		ac = ap_card_create(ap, hwinfo, comp_type);
		if (!ac) {
			AP_DBF_WARN("%s(%d) ap_card_create() failed\n",
				    __func__, ap);
@@ -2101,13 +2094,13 @@ static inline void ap_scan_adapter(int ap)
		get_device(dev);
		if (decfg)
			AP_DBF_INFO("%s(%d) new (decfg) card dev type=%d func=0x%08x created\n",
				    __func__, ap, type, func);
				    __func__, ap, hwinfo.at, hwinfo.fac);
		else if (chkstop)
			AP_DBF_INFO("%s(%d) new (chkstop) card dev type=%d func=0x%08x created\n",
				    __func__, ap, type, func);
				    __func__, ap, hwinfo.at, hwinfo.fac);
		else
			AP_DBF_INFO("%s(%d) new card dev type=%d func=0x%08x created\n",
				    __func__, ap, type, func);
				    __func__, ap, hwinfo.at, hwinfo.fac);
	}

	/* Verify the domains and the queue devices for this card */
+4 −16
Original line number Diff line number Diff line
@@ -75,16 +75,6 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_DEVICE_TYPE_CEX7	13
#define AP_DEVICE_TYPE_CEX8	14

/*
 * Known function facilities
 */
#define AP_FUNC_MEX4K 1
#define AP_FUNC_CRT4K 2
#define AP_FUNC_COPRO 3
#define AP_FUNC_ACCEL 4
#define AP_FUNC_EP11  5
#define AP_FUNC_APXA  6

/*
 * AP queue state machine states
 */
@@ -182,9 +172,7 @@ struct ap_device {

struct ap_card {
	struct ap_device ap_dev;
	int raw_hwtype;			/* AP raw hardware type. */
	unsigned int functions;		/* TAPQ GR2 upper 32 facility bits */
	int queue_depth;		/* AP queue depth.*/
	struct ap_tapq_hwinfo hwinfo;	/* TAPQ GR2 content */
	int id;				/* AP card number. */
	unsigned int maxmsgsize;	/* AP msg limit for this card */
	bool config;			/* configured state */
@@ -192,7 +180,7 @@ struct ap_card {
	atomic64_t total_request_count;	/* # requests ever for this AP device.*/
};

#define TAPQ_CARD_FUNC_CMP_MASK 0xFFFF0000
#define TAPQ_CARD_HWINFO_MASK 0xFEFF0000FFFF0F0FUL
#define ASSOC_IDX_INVALID 0x10000

#define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device)
@@ -290,8 +278,8 @@ void ap_queue_remove(struct ap_queue *aq);
void ap_queue_init_state(struct ap_queue *aq);
void _ap_queue_init_state(struct ap_queue *aq);

struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
			       int comp_type, unsigned int functions, int ml);
struct ap_card *ap_card_create(int id, struct ap_tapq_hwinfo info,
			       int comp_type);

#define APMASKSIZE (BITS_TO_LONGS(AP_DEVICES) * sizeof(unsigned long))
#define AQMASKSIZE (BITS_TO_LONGS(AP_DOMAINS) * sizeof(unsigned long))
+8 −10
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ static ssize_t raw_hwtype_show(struct device *dev,
{
	struct ap_card *ac = to_ap_card(dev);

	return sysfs_emit(buf, "%d\n", ac->raw_hwtype);
	return sysfs_emit(buf, "%d\n", ac->hwinfo.at);
}

static DEVICE_ATTR_RO(raw_hwtype);
@@ -44,7 +44,7 @@ static ssize_t depth_show(struct device *dev, struct device_attribute *attr,
{
	struct ap_card *ac = to_ap_card(dev);

	return sysfs_emit(buf, "%d\n", ac->queue_depth);
	return sysfs_emit(buf, "%d\n", ac->hwinfo.qd);
}

static DEVICE_ATTR_RO(depth);
@@ -54,7 +54,7 @@ static ssize_t ap_functions_show(struct device *dev,
{
	struct ap_card *ac = to_ap_card(dev);

	return sysfs_emit(buf, "0x%08X\n", ac->functions);
	return sysfs_emit(buf, "0x%08X\n", ac->hwinfo.fac);
}

static DEVICE_ATTR_RO(ap_functions);
@@ -229,8 +229,8 @@ static void ap_card_device_release(struct device *dev)
	kfree(ac);
}

struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
			       int comp_type, unsigned int functions, int ml)
struct ap_card *ap_card_create(int id, struct ap_tapq_hwinfo hwinfo,
			       int comp_type)
{
	struct ap_card *ac;

@@ -240,12 +240,10 @@ struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
	ac->ap_dev.device.release = ap_card_device_release;
	ac->ap_dev.device.type = &ap_card_type;
	ac->ap_dev.device_type = comp_type;
	ac->raw_hwtype = raw_type;
	ac->queue_depth = queue_depth;
	ac->functions = functions;
	ac->hwinfo = hwinfo;
	ac->id = id;
	ac->maxmsgsize = ml > 0 ?
		ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
	ac->maxmsgsize = hwinfo.ml > 0 ?
		hwinfo.ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;

	return ac;
}
+16 −17
Original line number Diff line number Diff line
@@ -24,13 +24,12 @@ static void __ap_flush_queue(struct ap_queue *aq);

static inline bool ap_q_supports_bind(struct ap_queue *aq)
{
	return ap_test_bit(&aq->card->functions, AP_FUNC_EP11) ||
		ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL);
	return aq->card->hwinfo.ep11 || aq->card->hwinfo.accel;
}

static inline bool ap_q_supports_assoc(struct ap_queue *aq)
{
	return ap_test_bit(&aq->card->functions, AP_FUNC_EP11);
	return aq->card->hwinfo.ep11;
}

static inline bool ap_q_needs_bind(struct ap_queue *aq)
@@ -257,7 +256,7 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
		list_move_tail(&ap_msg->list, &aq->pendingq);
		aq->requestq_count--;
		aq->pendingq_count++;
		if (aq->queue_count < aq->card->queue_depth) {
		if (aq->queue_count < aq->card->hwinfo.qd) {
			aq->sm_state = AP_SM_STATE_WORKING;
			return AP_SM_WAIT_AGAIN;
		}
@@ -421,9 +420,9 @@ static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq)
static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
{
	struct ap_queue_status status;
	struct ap_tapq_gr2 info;
	struct ap_tapq_hwinfo hwinfo;

	status = ap_test_queue(aq->qid, 1, &info);
	status = ap_test_queue(aq->qid, 1, &hwinfo);
	/* handle asynchronous error on this queue */
	if (status.async && status.response_code) {
		aq->dev_state = AP_DEV_STATE_ERROR;
@@ -443,7 +442,7 @@ static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
	}

	/* check bs bits */
	switch (info.bs) {
	switch (hwinfo.bs) {
	case AP_BS_Q_USABLE:
		/* association is through */
		aq->sm_state = AP_SM_STATE_IDLE;
@@ -460,7 +459,7 @@ static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
		aq->dev_state = AP_DEV_STATE_ERROR;
		aq->last_err_rc = status.response_code;
		AP_DBF_WARN("%s bs 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
			    __func__, info.bs,
			    __func__, hwinfo.bs,
			    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
		return AP_SM_WAIT_NONE;
	}
@@ -687,9 +686,9 @@ static ssize_t ap_functions_show(struct device *dev,
{
	struct ap_queue *aq = to_ap_queue(dev);
	struct ap_queue_status status;
	struct ap_tapq_gr2 info;
	struct ap_tapq_hwinfo hwinfo;

	status = ap_test_queue(aq->qid, 1, &info);
	status = ap_test_queue(aq->qid, 1, &hwinfo);
	if (status.response_code > AP_RESPONSE_BUSY) {
		AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
			   __func__, status.response_code,
@@ -697,7 +696,7 @@ static ssize_t ap_functions_show(struct device *dev,
		return -EIO;
	}

	return sysfs_emit(buf, "0x%08X\n", info.fac);
	return sysfs_emit(buf, "0x%08X\n", hwinfo.fac);
}

static DEVICE_ATTR_RO(ap_functions);
@@ -840,19 +839,19 @@ static ssize_t se_bind_show(struct device *dev,
{
	struct ap_queue *aq = to_ap_queue(dev);
	struct ap_queue_status status;
	struct ap_tapq_gr2 info;
	struct ap_tapq_hwinfo hwinfo;

	if (!ap_q_supports_bind(aq))
		return sysfs_emit(buf, "-\n");

	status = ap_test_queue(aq->qid, 1, &info);
	status = ap_test_queue(aq->qid, 1, &hwinfo);
	if (status.response_code > AP_RESPONSE_BUSY) {
		AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
			   __func__, status.response_code,
			   AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
		return -EIO;
	}
	switch (info.bs) {
	switch (hwinfo.bs) {
	case AP_BS_Q_USABLE:
	case AP_BS_Q_USABLE_NO_SECURE_KEY:
		return sysfs_emit(buf, "bound\n");
@@ -920,12 +919,12 @@ static ssize_t se_associate_show(struct device *dev,
{
	struct ap_queue *aq = to_ap_queue(dev);
	struct ap_queue_status status;
	struct ap_tapq_gr2 info;
	struct ap_tapq_hwinfo hwinfo;

	if (!ap_q_supports_assoc(aq))
		return sysfs_emit(buf, "-\n");

	status = ap_test_queue(aq->qid, 1, &info);
	status = ap_test_queue(aq->qid, 1, &hwinfo);
	if (status.response_code > AP_RESPONSE_BUSY) {
		AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
			   __func__, status.response_code,
@@ -933,7 +932,7 @@ static ssize_t se_associate_show(struct device *dev,
		return -EIO;
	}

	switch (info.bs) {
	switch (hwinfo.bs) {
	case AP_BS_Q_USABLE:
		if (aq->assoc_idx == ASSOC_IDX_INVALID) {
			AP_DBF_WARN("%s AP_BS_Q_USABLE but invalid assoc_idx\n", __func__);
Loading