Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4ccb132 authored by Eric Lapuyade's avatar Eric Lapuyade Committed by John W. Linville
Browse files

NFC: Specify usage for targets found and target lost events



It is now specified that nfc_target_found() and nfc_target_lost() core
functions must not be called from an atomic context. This allow us to
serialize calls and protect the targets table using the nfc device lock
instead of a spinlock.

Signed-off-by: default avatarEric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent addfabf9
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -97,7 +97,6 @@ struct nfc_dev {
	struct nfc_target *targets;
	struct nfc_target *targets;
	int n_targets;
	int n_targets;
	int targets_generation;
	int targets_generation;
	spinlock_t targets_lock;
	struct device dev;
	struct device dev;
	bool dev_up;
	bool dev_up;
	bool polling;
	bool polling;
+26 −9
Original line number Original line Diff line number Diff line
@@ -501,6 +501,9 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
 * The device driver must call this function when one or many nfc targets
 * The device driver must call this function when one or many nfc targets
 * are found. After calling this function, the device driver must stop
 * are found. After calling this function, the device driver must stop
 * polling for targets.
 * polling for targets.
 * IMPORTANT: this function must not be called from an atomic context.
 * In addition, it must also not be called from a context that would prevent
 * the NFC Core to call other nfc ops entry point concurrently.
 */
 */
int nfc_targets_found(struct nfc_dev *dev,
int nfc_targets_found(struct nfc_dev *dev,
		      struct nfc_target *targets, int n_targets)
		      struct nfc_target *targets, int n_targets)
@@ -514,7 +517,7 @@ int nfc_targets_found(struct nfc_dev *dev,
	for (i = 0; i < n_targets; i++)
	for (i = 0; i < n_targets; i++)
		targets[i].idx = dev->target_next_idx++;
		targets[i].idx = dev->target_next_idx++;


	spin_lock_bh(&dev->targets_lock);
	device_lock(&dev->dev);


	dev->targets_generation++;
	dev->targets_generation++;


@@ -524,12 +527,12 @@ int nfc_targets_found(struct nfc_dev *dev,


	if (!dev->targets) {
	if (!dev->targets) {
		dev->n_targets = 0;
		dev->n_targets = 0;
		spin_unlock_bh(&dev->targets_lock);
		device_unlock(&dev->dev);
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	dev->n_targets = n_targets;
	dev->n_targets = n_targets;
	spin_unlock_bh(&dev->targets_lock);
	device_unlock(&dev->dev);


	nfc_genl_targets_found(dev);
	nfc_genl_targets_found(dev);


@@ -537,6 +540,18 @@ int nfc_targets_found(struct nfc_dev *dev,
}
}
EXPORT_SYMBOL(nfc_targets_found);
EXPORT_SYMBOL(nfc_targets_found);


/**
 * nfc_target_lost - inform that an activated target went out of field
 *
 * @dev: The nfc device that had the activated target in field
 * @target_idx: the nfc index of the target
 *
 * The device driver must call this function when the activated target
 * goes out of the field.
 * IMPORTANT: this function must not be called from an atomic context.
 * In addition, it must also not be called from a context that would prevent
 * the NFC Core to call other nfc ops entry point concurrently.
 */
int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
{
{
	struct nfc_target *tg;
	struct nfc_target *tg;
@@ -544,7 +559,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)


	pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx);
	pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx);


	spin_lock_bh(&dev->targets_lock);
	device_lock(&dev->dev);


	for (i = 0; i < dev->n_targets; i++) {
	for (i = 0; i < dev->n_targets; i++) {
		tg = &dev->targets[i];
		tg = &dev->targets[i];
@@ -553,7 +568,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
	}
	}


	if (i == dev->n_targets) {
	if (i == dev->n_targets) {
		spin_unlock_bh(&dev->targets_lock);
		device_unlock(&dev->dev);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -569,7 +584,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
		dev->targets = NULL;
		dev->targets = NULL;
	}
	}


	spin_unlock_bh(&dev->targets_lock);
	device_unlock(&dev->dev);


	nfc_genl_target_lost(dev, target_idx);
	nfc_genl_target_lost(dev, target_idx);


@@ -607,8 +622,10 @@ static void nfc_check_pres_work(struct work_struct *work)
			mod_timer(&dev->check_pres_timer, jiffies +
			mod_timer(&dev->check_pres_timer, jiffies +
				  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
				  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
		} else {
		} else {
			nfc_target_lost(dev, dev->active_target->idx);
			u32 active_target_idx = dev->active_target->idx;
			dev->active_target = NULL;
			device_unlock(&dev->dev);
			nfc_target_lost(dev, active_target_idx);
			return;
		}
		}
	}
	}


@@ -681,9 +698,9 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
	dev->tx_headroom = tx_headroom;
	dev->tx_headroom = tx_headroom;
	dev->tx_tailroom = tx_tailroom;
	dev->tx_tailroom = tx_tailroom;


	spin_lock_init(&dev->targets_lock);
	nfc_genl_data_init(&dev->genl_data);
	nfc_genl_data_init(&dev->genl_data);



	/* first generation must not be 0 */
	/* first generation must not be 0 */
	dev->targets_generation = 1;
	dev->targets_generation = 1;


+2 −2
Original line number Original line Diff line number Diff line
@@ -128,7 +128,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb,
		cb->args[1] = (long) dev;
		cb->args[1] = (long) dev;
	}
	}


	spin_lock_bh(&dev->targets_lock);
	device_lock(&dev->dev);


	cb->seq = dev->targets_generation;
	cb->seq = dev->targets_generation;


@@ -141,7 +141,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb,
		i++;
		i++;
	}
	}


	spin_unlock_bh(&dev->targets_lock);
	device_unlock(&dev->dev);


	cb->args[0] = i;
	cb->args[0] = i;