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

Commit 7356a764 authored by Jiri Benc's avatar Jiri Benc Committed by David S. Miller
Browse files

ptp: dynamic allocation of PHC char devices



As network adapters supporting PTP are becoming more common, machines with
many NICs suddenly have many PHCs, too. The current limit of eight /dev/ptp*
char devices (and thus, 8 network interfaces with PHC) is insufficient. Let
the ptp driver allocate the char devices dynamically.

Tested with 28 PHCs, removing and re-adding some of them.

Thanks to Ben Hutchings for advice leading to simpler and cleaner patch.

Signed-off-by: default avatarJiri Benc <jbenc@redhat.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d6a4a104
Loading
Loading
Loading
Loading
+13 −25
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <linux/bitops.h>
#include <linux/idr.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -32,7 +32,6 @@
#include "ptp_private.h"

#define PTP_MAX_ALARMS 4
#define PTP_MAX_CLOCKS 8
#define PTP_PPS_DEFAULTS (PPS_CAPTUREASSERT | PPS_OFFSETASSERT)
#define PTP_PPS_EVENT PPS_CAPTUREASSERT
#define PTP_PPS_MODE (PTP_PPS_DEFAULTS | PPS_CANWAIT | PPS_TSFMT_TSPEC)
@@ -42,8 +41,7 @@
static dev_t ptp_devt;
static struct class *ptp_class;

static DECLARE_BITMAP(ptp_clocks_map, PTP_MAX_CLOCKS);
static DEFINE_MUTEX(ptp_clocks_mutex); /* protects 'ptp_clocks_map' */
static DEFINE_IDA(ptp_clocks_map);

/* time stamp event queue operations */

@@ -171,12 +169,7 @@ static void delete_ptp_clock(struct posix_clock *pc)
	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);

	mutex_destroy(&ptp->tsevq_mux);

	/* Remove the clock from the bit map. */
	mutex_lock(&ptp_clocks_mutex);
	clear_bit(ptp->index, ptp_clocks_map);
	mutex_unlock(&ptp_clocks_mutex);

	ida_simple_remove(&ptp_clocks_map, ptp->index);
	kfree(ptp);
}

@@ -191,21 +184,18 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
	if (info->n_alarm > PTP_MAX_ALARMS)
		return ERR_PTR(-EINVAL);

	/* Find a free clock slot and reserve it. */
	err = -EBUSY;
	mutex_lock(&ptp_clocks_mutex);
	index = find_first_zero_bit(ptp_clocks_map, PTP_MAX_CLOCKS);
	if (index < PTP_MAX_CLOCKS)
		set_bit(index, ptp_clocks_map);
	else
		goto no_slot;

	/* Initialize a clock structure. */
	err = -ENOMEM;
	ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL);
	if (ptp == NULL)
		goto no_memory;

	index = ida_simple_get(&ptp_clocks_map, 0, MINORMASK + 1, GFP_KERNEL);
	if (index < 0) {
		err = index;
		goto no_slot;
	}

	ptp->clock.ops = ptp_clock_ops;
	ptp->clock.release = delete_ptp_clock;
	ptp->info = info;
@@ -248,7 +238,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
		goto no_clock;
	}

	mutex_unlock(&ptp_clocks_mutex);
	return ptp;

no_clock:
@@ -260,11 +249,9 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
	device_destroy(ptp_class, ptp->devid);
no_device:
	mutex_destroy(&ptp->tsevq_mux);
no_slot:
	kfree(ptp);
no_memory:
	clear_bit(index, ptp_clocks_map);
no_slot:
	mutex_unlock(&ptp_clocks_mutex);
	return ERR_PTR(err);
}
EXPORT_SYMBOL(ptp_clock_register);
@@ -323,7 +310,8 @@ EXPORT_SYMBOL(ptp_clock_index);
static void __exit ptp_exit(void)
{
	class_destroy(ptp_class);
	unregister_chrdev_region(ptp_devt, PTP_MAX_CLOCKS);
	unregister_chrdev_region(ptp_devt, MINORMASK + 1);
	ida_destroy(&ptp_clocks_map);
}

static int __init ptp_init(void)
@@ -336,7 +324,7 @@ static int __init ptp_init(void)
		return PTR_ERR(ptp_class);
	}

	err = alloc_chrdev_region(&ptp_devt, 0, PTP_MAX_CLOCKS, "ptp");
	err = alloc_chrdev_region(&ptp_devt, 0, MINORMASK + 1, "ptp");
	if (err < 0) {
		pr_err("ptp: failed to allocate device region\n");
		goto no_region;