diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /drivers/s390/crypto/ap_bus.c | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
| -rw-r--r-- | drivers/s390/crypto/ap_bus.c | 296 | 
1 files changed, 172 insertions, 124 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index f4cc1720156f..8d6b9a52bf3c 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -122,7 +122,13 @@ static struct hrtimer ap_poll_timer;   * In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.   * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.   */ -static unsigned long long poll_timeout = 250000; +static unsigned long poll_high_timeout = 250000UL; + +/* + * Some state machine states only require a low frequency polling. + * We use 25 Hz frequency for these. + */ +static unsigned long poll_low_timeout = 40000000UL;  /* Maximum domain id, if not given via qci */  static int ap_max_domain_id = 15; @@ -201,6 +207,18 @@ static inline int ap_qact_available(void)  }  /* + * ap_sb_available(): Test if the AP secure binding facility is available. + * + * Returns 1 if secure binding facility is available. + */ +int ap_sb_available(void) +{ +	if (ap_qci_info) +		return ap_qci_info->apsb; +	return 0; +} + +/*   * ap_fetch_qci_info(): Fetch cryptographic config info   *   * Returns the ap configuration info fetched via PQAP(QCI). @@ -248,13 +266,13 @@ static void __init ap_init_qci_info(void)  	AP_DBF_INFO("%s successful fetched initial qci info\n", __func__);  	if (ap_qci_info->apxa) { -		if (ap_qci_info->Na) { -			ap_max_adapter_id = ap_qci_info->Na; +		if (ap_qci_info->na) { +			ap_max_adapter_id = ap_qci_info->na;  			AP_DBF_INFO("%s new ap_max_adapter_id is %d\n",  				    __func__, ap_max_adapter_id);  		} -		if (ap_qci_info->Nd) { -			ap_max_domain_id = ap_qci_info->Nd; +		if (ap_qci_info->nd) { +			ap_max_domain_id = ap_qci_info->nd;  			AP_DBF_INFO("%s new ap_max_domain_id is %d\n",  				    __func__, ap_max_domain_id);  		} @@ -324,35 +342,32 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);  /*   * ap_queue_info(): Check and get AP queue info. - * Returns true if TAPQ succeeded and the info is filled or - * false otherwise. + * Returns: 1 if APQN exists and info is filled, + *	    0 if APQN seems to exit but there is no info + *	      available (eg. caused by an asynch pending error) + *	   -1 invalid APQN, TAPQ error or AP queue status which + *	      indicates there is no APQN.   */ -static bool 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, int *q_type, unsigned int *q_fac, +			 int *q_depth, int *q_ml, bool *q_decfg, bool *q_cstop)  {  	struct ap_queue_status status; -	union { -		unsigned long value; -		struct { -			unsigned int fac   : 32; /* facility bits */ -			unsigned int at	   :  8; /* ap type */ -			unsigned int _res1 :  8; -			unsigned int _res2 :  4; -			unsigned int ml	   :  4; /* apxl ml */ -			unsigned int _res3 :  4; -			unsigned int qd	   :  4; /* queue depth */ -		} tapq_gr2; -	} tapq_info; +	struct ap_tapq_gr2 tapq_info;  	tapq_info.value = 0;  	/* make sure we don't run into a specifiation exception */  	if (AP_QID_CARD(qid) > ap_max_adapter_id ||  	    AP_QID_QUEUE(qid) > ap_max_domain_id) -		return false; +		return -1;  	/* call TAPQ on this APQN */ -	status = ap_test_queue(qid, ap_apft_available(), &tapq_info.value); +	status = ap_test_queue(qid, ap_apft_available(), &tapq_info); + +	/* handle pending async error with return 'no info available' */ +	if (status.async) +		return 0; +  	switch (status.response_code) {  	case AP_RESPONSE_NORMAL:  	case AP_RESPONSE_RESET_IN_PROGRESS: @@ -365,11 +380,11 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,  		 * there is at least one of the mode bits set.  		 */  		if (WARN_ON_ONCE(!tapq_info.value)) -			return false; -		*q_type = tapq_info.tapq_gr2.at; -		*q_fac = tapq_info.tapq_gr2.fac; -		*q_depth = tapq_info.tapq_gr2.qd; -		*q_ml = tapq_info.tapq_gr2.ml; +			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;  		switch (*q_type) { @@ -389,12 +404,12 @@ static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,  		default:  			break;  		} -		return true; +		return 1;  	default:  		/*  		 * A response code which indicates, there is no info available.  		 */ -		return false; +		return -1;  	}  } @@ -412,10 +427,13 @@ void ap_wait(enum ap_sm_wait wait)  			break;  		}  		fallthrough; -	case AP_SM_WAIT_TIMEOUT: +	case AP_SM_WAIT_LOW_TIMEOUT: +	case AP_SM_WAIT_HIGH_TIMEOUT:  		spin_lock_bh(&ap_poll_timer_lock);  		if (!hrtimer_is_queued(&ap_poll_timer)) { -			hr_time = poll_timeout; +			hr_time = +				wait == AP_SM_WAIT_LOW_TIMEOUT ? +				poll_low_timeout : poll_high_timeout;  			hrtimer_forward_now(&ap_poll_timer, hr_time);  			hrtimer_restart(&ap_poll_timer);  		} @@ -1166,12 +1184,12 @@ EXPORT_SYMBOL(ap_parse_mask_str);   * AP bus attributes.   */ -static ssize_t ap_domain_show(struct bus_type *bus, char *buf) +static ssize_t ap_domain_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index); +	return sysfs_emit(buf, "%d\n", ap_domain_index);  } -static ssize_t ap_domain_store(struct bus_type *bus, +static ssize_t ap_domain_store(const struct bus_type *bus,  			       const char *buf, size_t count)  {  	int domain; @@ -1193,65 +1211,61 @@ static ssize_t ap_domain_store(struct bus_type *bus,  static BUS_ATTR_RW(ap_domain); -static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf) +static ssize_t ap_control_domain_mask_show(const struct bus_type *bus, char *buf)  {  	if (!ap_qci_info)	/* QCI not supported */ -		return scnprintf(buf, PAGE_SIZE, "not supported\n"); +		return sysfs_emit(buf, "not supported\n"); -	return scnprintf(buf, PAGE_SIZE, -			 "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", -			 ap_qci_info->adm[0], ap_qci_info->adm[1], -			 ap_qci_info->adm[2], ap_qci_info->adm[3], -			 ap_qci_info->adm[4], ap_qci_info->adm[5], -			 ap_qci_info->adm[6], ap_qci_info->adm[7]); +	return sysfs_emit(buf, "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", +			  ap_qci_info->adm[0], ap_qci_info->adm[1], +			  ap_qci_info->adm[2], ap_qci_info->adm[3], +			  ap_qci_info->adm[4], ap_qci_info->adm[5], +			  ap_qci_info->adm[6], ap_qci_info->adm[7]);  }  static BUS_ATTR_RO(ap_control_domain_mask); -static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf) +static ssize_t ap_usage_domain_mask_show(const struct bus_type *bus, char *buf)  {  	if (!ap_qci_info)	/* QCI not supported */ -		return scnprintf(buf, PAGE_SIZE, "not supported\n"); +		return sysfs_emit(buf, "not supported\n"); -	return scnprintf(buf, PAGE_SIZE, -			 "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", -			 ap_qci_info->aqm[0], ap_qci_info->aqm[1], -			 ap_qci_info->aqm[2], ap_qci_info->aqm[3], -			 ap_qci_info->aqm[4], ap_qci_info->aqm[5], -			 ap_qci_info->aqm[6], ap_qci_info->aqm[7]); +	return sysfs_emit(buf, "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", +			  ap_qci_info->aqm[0], ap_qci_info->aqm[1], +			  ap_qci_info->aqm[2], ap_qci_info->aqm[3], +			  ap_qci_info->aqm[4], ap_qci_info->aqm[5], +			  ap_qci_info->aqm[6], ap_qci_info->aqm[7]);  }  static BUS_ATTR_RO(ap_usage_domain_mask); -static ssize_t ap_adapter_mask_show(struct bus_type *bus, char *buf) +static ssize_t ap_adapter_mask_show(const struct bus_type *bus, char *buf)  {  	if (!ap_qci_info)	/* QCI not supported */ -		return scnprintf(buf, PAGE_SIZE, "not supported\n"); +		return sysfs_emit(buf, "not supported\n"); -	return scnprintf(buf, PAGE_SIZE, -			 "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", -			 ap_qci_info->apm[0], ap_qci_info->apm[1], -			 ap_qci_info->apm[2], ap_qci_info->apm[3], -			 ap_qci_info->apm[4], ap_qci_info->apm[5], -			 ap_qci_info->apm[6], ap_qci_info->apm[7]); +	return sysfs_emit(buf, "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", +			  ap_qci_info->apm[0], ap_qci_info->apm[1], +			  ap_qci_info->apm[2], ap_qci_info->apm[3], +			  ap_qci_info->apm[4], ap_qci_info->apm[5], +			  ap_qci_info->apm[6], ap_qci_info->apm[7]);  }  static BUS_ATTR_RO(ap_adapter_mask); -static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf) +static ssize_t ap_interrupts_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%d\n", -			 ap_irq_flag ? 1 : 0); +	return sysfs_emit(buf, "%d\n", ap_irq_flag ? 1 : 0);  }  static BUS_ATTR_RO(ap_interrupts); -static ssize_t config_time_show(struct bus_type *bus, char *buf) +static ssize_t config_time_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); +	return sysfs_emit(buf, "%d\n", ap_config_time);  } -static ssize_t config_time_store(struct bus_type *bus, +static ssize_t config_time_store(const struct bus_type *bus,  				 const char *buf, size_t count)  {  	int time; @@ -1265,19 +1279,22 @@ static ssize_t config_time_store(struct bus_type *bus,  static BUS_ATTR_RW(config_time); -static ssize_t poll_thread_show(struct bus_type *bus, char *buf) +static ssize_t poll_thread_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0); +	return sysfs_emit(buf, "%d\n", ap_poll_kthread ? 1 : 0);  } -static ssize_t poll_thread_store(struct bus_type *bus, +static ssize_t poll_thread_store(const struct bus_type *bus,  				 const char *buf, size_t count)  { -	int flag, rc; +	bool value; +	int rc; -	if (sscanf(buf, "%d\n", &flag) != 1) -		return -EINVAL; -	if (flag) { +	rc = kstrtobool(buf, &value); +	if (rc) +		return rc; + +	if (value) {  		rc = ap_poll_thread_start();  		if (rc)  			count = rc; @@ -1289,23 +1306,27 @@ static ssize_t poll_thread_store(struct bus_type *bus,  static BUS_ATTR_RW(poll_thread); -static ssize_t poll_timeout_show(struct bus_type *bus, char *buf) +static ssize_t poll_timeout_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout); +	return sysfs_emit(buf, "%lu\n", poll_high_timeout);  } -static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf, +static ssize_t poll_timeout_store(const struct bus_type *bus, const char *buf,  				  size_t count)  { -	unsigned long long time; +	unsigned long value;  	ktime_t hr_time; +	int rc; + +	rc = kstrtoul(buf, 0, &value); +	if (rc) +		return rc;  	/* 120 seconds = maximum poll interval */ -	if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 || -	    time > 120000000000ULL) +	if (value > 120000000000UL)  		return -EINVAL; -	poll_timeout = time; -	hr_time = poll_timeout; +	poll_high_timeout = value; +	hr_time = poll_high_timeout;  	spin_lock_bh(&ap_poll_timer_lock);  	hrtimer_cancel(&ap_poll_timer); @@ -1318,30 +1339,29 @@ static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,  static BUS_ATTR_RW(poll_timeout); -static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) +static ssize_t ap_max_domain_id_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_domain_id); +	return sysfs_emit(buf, "%d\n", ap_max_domain_id);  }  static BUS_ATTR_RO(ap_max_domain_id); -static ssize_t ap_max_adapter_id_show(struct bus_type *bus, char *buf) +static ssize_t ap_max_adapter_id_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_adapter_id); +	return sysfs_emit(buf, "%d\n", ap_max_adapter_id);  }  static BUS_ATTR_RO(ap_max_adapter_id); -static ssize_t apmask_show(struct bus_type *bus, char *buf) +static ssize_t apmask_show(const struct bus_type *bus, char *buf)  {  	int rc;  	if (mutex_lock_interruptible(&ap_perms_mutex))  		return -ERESTARTSYS; -	rc = scnprintf(buf, PAGE_SIZE, -		       "0x%016lx%016lx%016lx%016lx\n", -		       ap_perms.apm[0], ap_perms.apm[1], -		       ap_perms.apm[2], ap_perms.apm[3]); +	rc = sysfs_emit(buf, "0x%016lx%016lx%016lx%016lx\n", +			ap_perms.apm[0], ap_perms.apm[1], +			ap_perms.apm[2], ap_perms.apm[3]);  	mutex_unlock(&ap_perms_mutex);  	return rc; @@ -1393,7 +1413,7 @@ static int apmask_commit(unsigned long *newapm)  	return 0;  } -static ssize_t apmask_store(struct bus_type *bus, const char *buf, +static ssize_t apmask_store(const struct bus_type *bus, const char *buf,  			    size_t count)  {  	int rc, changes = 0; @@ -1425,16 +1445,15 @@ done:  static BUS_ATTR_RW(apmask); -static ssize_t aqmask_show(struct bus_type *bus, char *buf) +static ssize_t aqmask_show(const struct bus_type *bus, char *buf)  {  	int rc;  	if (mutex_lock_interruptible(&ap_perms_mutex))  		return -ERESTARTSYS; -	rc = scnprintf(buf, PAGE_SIZE, -		       "0x%016lx%016lx%016lx%016lx\n", -		       ap_perms.aqm[0], ap_perms.aqm[1], -		       ap_perms.aqm[2], ap_perms.aqm[3]); +	rc = sysfs_emit(buf, "0x%016lx%016lx%016lx%016lx\n", +			ap_perms.aqm[0], ap_perms.aqm[1], +			ap_perms.aqm[2], ap_perms.aqm[3]);  	mutex_unlock(&ap_perms_mutex);  	return rc; @@ -1486,7 +1505,7 @@ static int aqmask_commit(unsigned long *newaqm)  	return 0;  } -static ssize_t aqmask_store(struct bus_type *bus, const char *buf, +static ssize_t aqmask_store(const struct bus_type *bus, const char *buf,  			    size_t count)  {  	int rc, changes = 0; @@ -1518,13 +1537,12 @@ done:  static BUS_ATTR_RW(aqmask); -static ssize_t scans_show(struct bus_type *bus, char *buf) +static ssize_t scans_show(const struct bus_type *bus, char *buf)  { -	return scnprintf(buf, PAGE_SIZE, "%llu\n", -			 atomic64_read(&ap_scan_bus_count)); +	return sysfs_emit(buf, "%llu\n", atomic64_read(&ap_scan_bus_count));  } -static ssize_t scans_store(struct bus_type *bus, const char *buf, +static ssize_t scans_store(const struct bus_type *bus, const char *buf,  			   size_t count)  {  	AP_DBF_INFO("%s force AP bus rescan\n", __func__); @@ -1536,22 +1554,47 @@ static ssize_t scans_store(struct bus_type *bus, const char *buf,  static BUS_ATTR_RW(scans); -static ssize_t bindings_show(struct bus_type *bus, char *buf) +static ssize_t bindings_show(const struct bus_type *bus, char *buf)  {  	int rc;  	unsigned int apqns, n;  	ap_calc_bound_apqns(&apqns, &n);  	if (atomic64_read(&ap_scan_bus_count) >= 1 && n == apqns) -		rc = scnprintf(buf, PAGE_SIZE, "%u/%u (complete)\n", n, apqns); +		rc = sysfs_emit(buf, "%u/%u (complete)\n", n, apqns);  	else -		rc = scnprintf(buf, PAGE_SIZE, "%u/%u\n", n, apqns); +		rc = sysfs_emit(buf, "%u/%u\n", n, apqns);  	return rc;  }  static BUS_ATTR_RO(bindings); +static ssize_t features_show(const struct bus_type *bus, char *buf) +{ +	int n = 0; + +	if (!ap_qci_info)	/* QCI not supported */ +		return sysfs_emit(buf, "-\n"); + +	if (ap_qci_info->apsc) +		n += sysfs_emit_at(buf, n, "APSC "); +	if (ap_qci_info->apxa) +		n += sysfs_emit_at(buf, n, "APXA "); +	if (ap_qci_info->qact) +		n += sysfs_emit_at(buf, n, "QACT "); +	if (ap_qci_info->rc8a) +		n += sysfs_emit_at(buf, n, "RC8A "); +	if (ap_qci_info->apsb) +		n += sysfs_emit_at(buf, n, "APSB "); + +	sysfs_emit_at(buf, n == 0 ? 0 : n - 1, "\n"); + +	return n; +} + +static BUS_ATTR_RO(features); +  static struct attribute *ap_bus_attrs[] = {  	&bus_attr_ap_domain.attr,  	&bus_attr_ap_control_domain_mask.attr, @@ -1567,6 +1610,7 @@ static struct attribute *ap_bus_attrs[] = {  	&bus_attr_aqmask.attr,  	&bus_attr_scans.attr,  	&bus_attr_bindings.attr, +	&bus_attr_features.attr,  	NULL,  };  ATTRIBUTE_GROUPS(ap_bus); @@ -1762,12 +1806,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;  	bool decfg, chkstop; -	ap_qid_t qid; -	unsigned int func; -	struct device *dev;  	struct ap_queue *aq; -	int rc, dom, depth, type, ml; +	struct device *dev; +	unsigned int func; +	ap_qid_t qid;  	/*  	 * Go through the configuration for the domains and compare them @@ -1786,20 +1830,24 @@ static inline void ap_scan_domains(struct ap_card *ac)  				AP_DBF_INFO("%s(%d,%d) not in config anymore, rm queue dev\n",  					    __func__, ac->id, dom);  				device_unregister(dev); -				put_device(dev);  			} -			continue; +			goto put_dev_and_continue;  		}  		/* domain is valid, get info from this APQN */ -		if (!ap_queue_info(qid, &type, &func, &depth, -				   &ml, &decfg, &chkstop)) { -			if (aq) { +		rc = ap_queue_info(qid, &type, &func, &depth, +				   &ml, &decfg, &chkstop); +		switch (rc) { +		case -1: +			if (dev) {  				AP_DBF_INFO("%s(%d,%d) queue_info() failed, rm queue dev\n",  					    __func__, ac->id, dom);  				device_unregister(dev); -				put_device(dev);  			} -			continue; +			fallthrough; +		case 0: +			goto put_dev_and_continue; +		default: +			break;  		}  		/* if no queue device exists, create a new one */  		if (!aq) { @@ -1915,12 +1963,12 @@ put_dev_and_continue:   */  static inline void ap_scan_adapter(int ap)  { +	int rc, dom, depth, type, comp_type, ml;  	bool decfg, chkstop; -	ap_qid_t qid; -	unsigned int func; -	struct device *dev;  	struct ap_card *ac; -	int rc, dom, depth, type, comp_type, ml; +	struct device *dev; +	unsigned int func; +	ap_qid_t qid;  	/* Is there currently a card device for this adapter ? */  	dev = bus_find_device(&ap_bus_type, NULL, @@ -1950,11 +1998,11 @@ static inline void ap_scan_adapter(int ap)  		if (ap_test_config_usage_domain(dom)) {  			qid = AP_MKQID(ap, dom);  			if (ap_queue_info(qid, &type, &func, &depth, -					  &ml, &decfg, &chkstop)) +					  &ml, &decfg, &chkstop) > 0)  				break;  		}  	if (dom > ap_max_domain_id) { -		/* Could not find a valid APQN for this adapter */ +		/* Could not find one valid APQN for this adapter */  		if (ac) {  			AP_DBF_INFO("%s(%d) no type info (no APQN found), rm card and queue devs\n",  				    __func__, ap); @@ -1979,7 +2027,6 @@ static inline void ap_scan_adapter(int ap)  		}  		return;  	} -  	if (ac) {  		/* Check APQN against existing card device for changes */  		if (ac->raw_hwtype != type) { @@ -1988,9 +2035,10 @@ static inline void ap_scan_adapter(int ap)  			ap_scan_rm_card_dev_and_queue_devs(ac);  			put_device(dev);  			ac = NULL; -		} else if (ac->functions != func) { +		} else if ((ac->functions & TAPQ_CARD_FUNC_CMP_MASK) != +			   (func & TAPQ_CARD_FUNC_CMP_MASK)) {  			AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devs\n", -				    __func__, ap, type); +				    __func__, ap, func);  			ap_scan_rm_card_dev_and_queue_devs(ac);  			put_device(dev);  			ac = NULL; @@ -2245,7 +2293,7 @@ static int __init ap_module_init(void)  	 * If we are running under z/VM adjust polling to z/VM polling rate.  	 */  	if (MACHINE_IS_VM) -		poll_timeout = 1500000; +		poll_high_timeout = 1500000;  	hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);  	ap_poll_timer.function = ap_poll_timeout;  |