static inline void ap_scan_domains()

in crypto/ap_bus.c [1525:1641]


static inline void ap_scan_domains(struct ap_card *ac)
{
	bool decfg;
	ap_qid_t qid;
	unsigned int func;
	struct device *dev;
	struct ap_queue *aq;
	int rc, dom, depth, type, ml;

	/*
	 * Go through the configuration for the domains and compare them
	 * to the existing queue devices. Also take care of the config
	 * and error state for the queue devices.
	 */

	for (dom = 0; dom <= ap_max_domain_id; dom++) {
		qid = AP_MKQID(ac->id, dom);
		dev = bus_find_device(&ap_bus_type, NULL,
				      (void *)(long) qid,
				      __match_queue_device_with_qid);
		aq = dev ? to_ap_queue(dev) : NULL;
		if (!ap_test_config_usage_domain(dom)) {
			if (dev) {
				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;
		}
		/* domain is valid, get info from this APQN */
		if (!ap_queue_info(qid, &type, &func, &depth, &ml, &decfg)) {
			if (aq) {
				AP_DBF_INFO("%s(%d,%d) queue_info() failed, rm queue dev\n",
					    __func__, ac->id, dom);
				device_unregister(dev);
				put_device(dev);
			}
			continue;
		}
		/* if no queue device exists, create a new one */
		if (!aq) {
			aq = ap_queue_create(qid, ac->ap_dev.device_type);
			if (!aq) {
				AP_DBF_WARN("%s(%d,%d) ap_queue_create() failed\n",
					    __func__, ac->id, dom);
				continue;
			}
			aq->card = ac;
			aq->config = !decfg;
			dev = &aq->ap_dev.device;
			dev->bus = &ap_bus_type;
			dev->parent = &ac->ap_dev.device;
			dev_set_name(dev, "%02x.%04x", ac->id, dom);
			/* register queue device */
			rc = device_register(dev);
			if (rc) {
				AP_DBF_WARN("%s(%d,%d) device_register() failed\n",
					    __func__, ac->id, dom);
				goto put_dev_and_continue;
			}
			/* get it and thus adjust reference counter */
			get_device(dev);
			if (decfg)
				AP_DBF_INFO("%s(%d,%d) new (decfg) queue dev created\n",
					    __func__, ac->id, dom);
			else
				AP_DBF_INFO("%s(%d,%d) new queue dev created\n",
					    __func__, ac->id, dom);
			goto put_dev_and_continue;
		}
		/* Check config state on the already existing queue device */
		spin_lock_bh(&aq->lock);
		if (decfg && aq->config) {
			/* config off this queue device */
			aq->config = false;
			if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
				aq->dev_state = AP_DEV_STATE_ERROR;
				aq->last_err_rc = AP_RESPONSE_DECONFIGURED;
			}
			spin_unlock_bh(&aq->lock);
			AP_DBF_INFO("%s(%d,%d) queue dev config off\n",
				    __func__, ac->id, dom);
			ap_send_config_uevent(&aq->ap_dev, aq->config);
			/* 'receive' pending messages with -EAGAIN */
			ap_flush_queue(aq);
			goto put_dev_and_continue;
		}
		if (!decfg && !aq->config) {
			/* config on this queue device */
			aq->config = true;
			if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
				aq->dev_state = AP_DEV_STATE_OPERATING;
				aq->sm_state = AP_SM_STATE_RESET_START;
			}
			spin_unlock_bh(&aq->lock);
			AP_DBF_INFO("%s(%d,%d) queue dev config on\n",
				    __func__, ac->id, dom);
			ap_send_config_uevent(&aq->ap_dev, aq->config);
			goto put_dev_and_continue;
		}
		/* handle other error states */
		if (!decfg && aq->dev_state == AP_DEV_STATE_ERROR) {
			spin_unlock_bh(&aq->lock);
			/* 'receive' pending messages with -EAGAIN */
			ap_flush_queue(aq);
			/* re-init (with reset) the queue device */
			ap_queue_init_state(aq);
			AP_DBF_INFO("%s(%d,%d) queue dev reinit enforced\n",
				    __func__, ac->id, dom);
			goto put_dev_and_continue;
		}
		spin_unlock_bh(&aq->lock);
put_dev_and_continue:
		put_device(dev);
	}
}