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 <oron.peled@xorcom.com> Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10449 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
20c316ee21
commit
b8b7b86332
@ -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;
|
||||
|
@ -799,10 +799,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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user