From 4b40ea123289c9f785f0cd16184a34b2237dff15 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Wed, 21 Mar 2012 19:12:02 +0000 Subject: A parent-less device should not crash dahdi * A parent-less device should not crash dahdi: - Access span->parent->dev instead of span->parent-dev.parent in soem cases. - Access span->parent->dev via new inline span_device() - Use span_device() in all dahdi_dev_{dbg,info}() * Allow low-level drivers to set their device name. - Drivers that don't use this feature get the default name based on the parent device name - Parent-less devices which don't set their name, fails to register with -EINVAL Signed-off-by: Oron Peled Acked-by: Tzafrir Cohen Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10449 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.6@10568 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/dahdi-base.c | 27 ++++++++++++++++----------- drivers/dahdi/dahdi-sysfs.c | 9 ++++++++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 3137bde..bb01415 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -358,6 +358,11 @@ static DEFINE_SPINLOCK(zone_lock); /* The first zone on the list is the default zone. */ static LIST_HEAD(tone_zones); +static inline struct device *span_device(struct dahdi_span *span) +{ + return &span->parent->dev; +} + /* Protects the span_list and pseudo_chans lists from concurrent access in * process context. The spin_lock is needed to synchronize with the interrupt * handler. */ @@ -6649,7 +6654,7 @@ static void set_spanno_and_basechan(struct dahdi_span *span, u32 spanno, u32 basechan) { int i; - dahdi_dev_dbg(ASSIGN, span->parent->dev.parent, + dahdi_dev_dbg(ASSIGN, span_device(span), "set: spanno=%d, basechan=%d (span->channels=%d)\n", spanno, basechan, span->channels); span->spanno = spanno; @@ -6673,7 +6678,7 @@ static int _assign_spanno_and_basechan(struct dahdi_span *span) unsigned int spanno = 1; unsigned int basechan = 1; - dahdi_dev_dbg(ASSIGN, span->parent->dev.parent, + dahdi_dev_dbg(ASSIGN, span_device(span), "assign: channels=%d\n", span->channels); list_for_each_entry(pos, &span_list, spans_node) { @@ -6693,7 +6698,7 @@ static int _assign_spanno_and_basechan(struct dahdi_span *span) basechan = pos->chans[0]->channo + pos->channels; } - dahdi_dev_dbg(ASSIGN, span->parent->dev.parent, + dahdi_dev_dbg(ASSIGN, span_device(span), "good: spanno=%d, basechan=%d (span->channels=%d)\n", spanno, basechan, span->channels); set_spanno_and_basechan(span, spanno, basechan); @@ -6743,20 +6748,20 @@ _check_spanno_and_basechan(struct dahdi_span *span, u32 spanno, u32 basechan) struct dahdi_span *pos; unsigned int next_channo; - dahdi_dev_dbg(ASSIGN, span->parent->dev.parent, + dahdi_dev_dbg(ASSIGN, span_device(span), "check: spanno=%d, basechan=%d (span->channels=%d)\n", spanno, basechan, span->channels); list_for_each_entry(pos, &span_list, spans_node) { next_channo = _get_next_channo(pos); - dahdi_dev_dbg(ASSIGN, span->parent->dev.parent, + dahdi_dev_dbg(ASSIGN, span_device(span), "pos: spanno=%d channels=%d (next_channo=%d)\n", pos->spanno, pos->channels, next_channo); if (pos->spanno <= spanno) { if (basechan < next_channo + pos->channels) { /* Requested basechan breaks channel sorting */ - dev_notice(span->parent->dev.parent, + dev_notice(span_device(span), "[%d] basechan (%d) is too low for wanted span %d\n", local_spanno(span), basechan, spanno); return -EINVAL; @@ -6771,13 +6776,13 @@ _check_spanno_and_basechan(struct dahdi_span *span, u32 spanno, u32 basechan) break; /* Cannot fit the span into the requested location. Abort. */ - dev_notice(span->parent->dev.parent, + dev_notice(span_device(span), "cannot fit span %d (basechan=%d) into requested location\n", spanno, basechan); return -EINVAL; } - dahdi_dev_dbg(ASSIGN, span->parent->dev.parent, + dahdi_dev_dbg(ASSIGN, span_device(span), "good: spanno=%d, basechan=%d (span->channels=%d)\n", spanno, basechan, span->channels); set_spanno_and_basechan(span, spanno, basechan); @@ -6876,7 +6881,7 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno, return -EFAULT; if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) { - dev_notice(span->parent->dev.parent, + dev_notice(span_device(span), "local span %d is already assigned span %d " "with base channel %d\n", local_spanno(span), span->spanno, span->chans[0]->channo); @@ -6887,7 +6892,7 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno, span->ops->disable_hw_preechocan) { if ((NULL == span->ops->enable_hw_preechocan) || (NULL == span->ops->disable_hw_preechocan)) { - dev_notice(span->parent->dev.parent, + dev_notice(span_device(span), "span with inconsistent enable/disable hw_preechocan"); return -EFAULT; } @@ -7091,7 +7096,7 @@ static int _dahdi_unassign_span(struct dahdi_span *span) unsigned long flags; if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) { - dev_info(span->parent->dev.parent, + dev_info(span_device(span), "local span %d is already unassigned\n", local_spanno(span)); return -EINVAL; diff --git a/drivers/dahdi/dahdi-sysfs.c b/drivers/dahdi/dahdi-sysfs.c index a03aba8..3e6d157 100644 --- a/drivers/dahdi/dahdi-sysfs.c +++ b/drivers/dahdi/dahdi-sysfs.c @@ -796,10 +796,17 @@ int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent) { int ret; struct device *const dev = &ddev->dev; + const char *dn; dev->parent = parent; dev->bus = &dahdi_device_bus; - dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent)); + dn = dev_name(dev); + if (!dn || !*dn) { + /* Invent default name based on parent */ + if (!parent) + return -EINVAL; + dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent)); + } ret = device_add(dev); return ret; } -- cgit v1.2.3