dahdi: Allow dahdi_span_ops.[chan|span]config and startup to block.

This change ensures that the dahdi_span_ops callbacks are not called
with any spinlocks held, and that the module is pinned in memory, and
also passes the struct file * pointer to the callbacks.

Passing the file pointer to the callbacks allows the board drivers to
check any flags on the file descriptor used to configure the
span/channel. The intent here is to allow dahdi_config to open the
/dev/dahdi/ctl file in a non-blocking mode in case there is a lengthy
processes that needs to happen as part of configuration.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9940 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
Shaun Ruffell
2011-06-02 20:01:34 +00:00
parent 09eb417ec4
commit 76df5ab26b
13 changed files with 87 additions and 54 deletions

View File

@@ -4373,7 +4373,7 @@ static const struct net_device_ops dahdi_netdev_ops = {
};
#endif
static int dahdi_ioctl_chanconfig(unsigned long data)
static int dahdi_ioctl_chanconfig(struct file *file, unsigned long data)
{
int res = 0;
int y;
@@ -4507,8 +4507,13 @@ static int dahdi_ioctl_chanconfig(unsigned long data)
chan->flags &= ~DAHDI_FLAG_MTP2;
}
/* Chanconfig can block, do not call through the function pointer with
* the channel lock held. */
spin_unlock_irqrestore(&chan->lock, flags);
if (!res && chan->span->ops->chanconfig)
res = chan->span->ops->chanconfig(chan, ch.sigtype);
res = chan->span->ops->chanconfig(file, chan, ch.sigtype);
spin_lock_irqsave(&chan->lock, flags);
#ifdef CONFIG_DAHDI_NET
if (!res &&
@@ -4685,7 +4690,7 @@ static int dahdi_ioctl_indirect(struct file *file, unsigned long data)
return res;
}
static int dahdi_ioctl_spanconfig(unsigned long data)
static int dahdi_ioctl_spanconfig(struct file *file, unsigned long data)
{
int res = 0;
struct dahdi_lineconfig lc;
@@ -4708,13 +4713,13 @@ static int dahdi_ioctl_spanconfig(unsigned long data)
s->txlevel = lc.lbo;
s->rxlevel = 0;
res = s->ops->spanconfig(s, &lc);
res = s->ops->spanconfig(file, s, &lc);
}
put_span(s);
return res;
}
static int dahdi_ioctl_startup(unsigned long data)
static int dahdi_ioctl_startup(struct file *file, unsigned long data)
{
/* I/O CTL's for control interface */
int j;
@@ -4735,7 +4740,7 @@ static int dahdi_ioctl_startup(unsigned long data)
}
if (s->ops->startup)
res = s->ops->startup(s);
res = s->ops->startup(file, s);
if (!res) {
/* Mark as running and hangup any channels */
@@ -4986,15 +4991,15 @@ dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data)
case DAHDI_INDIRECT:
return dahdi_ioctl_indirect(file, data);
case DAHDI_SPANCONFIG:
return dahdi_ioctl_spanconfig(data);
return dahdi_ioctl_spanconfig(file, data);
case DAHDI_STARTUP:
return dahdi_ioctl_startup(data);
return dahdi_ioctl_startup(file, data);
case DAHDI_SHUTDOWN:
return dahdi_ioctl_shutdown(data);
case DAHDI_ATTACH_ECHOCAN:
return dahdi_ioctl_attach_echocan(data);
case DAHDI_CHANCONFIG:
return dahdi_ioctl_chanconfig(data);
return dahdi_ioctl_chanconfig(file, data);
case DAHDI_SFCONFIG:
return dahdi_ioctl_sfconfig(data);
case DAHDI_DEFAULTZONE:

View File

@@ -511,7 +511,8 @@ static int dahdi_dynamic_open(struct dahdi_chan *chan)
return 0;
}
static int dahdi_dynamic_chanconfig(struct dahdi_chan *chan, int sigtype)
static int dahdi_dynamic_chanconfig(struct file *file,
struct dahdi_chan *chan, int sigtype)
{
return 0;
}

View File

@@ -177,7 +177,7 @@ static int highestorder;
static int timingcable;
static void set_clear(struct tor2 *tor);
static int tor2_startup(struct dahdi_span *span);
static int tor2_startup(struct file *file, struct dahdi_span *span);
static int tor2_shutdown(struct dahdi_span *span);
static int tor2_rbsbits(struct dahdi_chan *chan, int bits);
static int tor2_maint(struct dahdi_span *span, int cmd);
@@ -193,7 +193,8 @@ static unsigned datxlt_e1[] = {
1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31 };
static int tor2_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int tor2_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
int i;
struct tor2_span *p = container_of(span, struct tor2_span, dahdi_span);
@@ -223,12 +224,13 @@ static int tor2_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
}
/* If we're already running, then go ahead and apply the changes */
if (span->flags & DAHDI_FLAG_RUNNING)
return tor2_startup(span);
return tor2_startup(file, span);
return 0;
}
static int tor2_chanconfig(struct dahdi_chan *chan, int sigtype)
static int tor2_chanconfig(struct file *file,
struct dahdi_chan *chan, int sigtype)
{
int alreadyrunning;
unsigned long flags;
@@ -811,7 +813,7 @@ static int tor2_shutdown(struct dahdi_span *span)
}
static int tor2_startup(struct dahdi_span *span)
static int tor2_startup(struct file *file, struct dahdi_span *span)
{
unsigned long endjif;
int i;

View File

@@ -2277,7 +2277,7 @@ static int b4xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long
return 0;
}
static int b4xxp_startup(struct dahdi_span *span)
static int b4xxp_startup(struct file *file, struct dahdi_span *span)
{
struct b4xxp_span *bspan = container_of(span, struct b4xxp_span, span);
struct b4xxp *b4 = bspan->parent;
@@ -2310,7 +2310,8 @@ static void b4xxp_reset_span(struct b4xxp_span *bspan)
}
/* spanconfig for us means to set up the HFC FIFO and channel mapping */
static int b4xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
int i;
struct b4xxp_span *bspan = container_of(span, struct b4xxp_span, span);
@@ -2347,7 +2348,7 @@ static int b4xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc
b4xxp_reset_span(bspan);
/* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */
b4xxp_startup(&bspan->span);
b4xxp_startup(file, &bspan->span);
span->flags |= DAHDI_FLAG_RUNNING;
@@ -2355,7 +2356,8 @@ static int b4xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc
}
/* chanconfig for us means to configure the HDLC controller, if appropriate */
static int b4xxp_chanconfig(struct dahdi_chan *chan, int sigtype)
static int
b4xxp_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
{
int alreadyrunning;
struct b4xxp *b4 = chan->pvt;
@@ -2820,7 +2822,7 @@ static int b4xxp_proc_read(char *buf, char **start, off_t offset, int count, int
static int b4xxp_startdefaultspan(struct b4xxp *b4)
{
struct dahdi_lineconfig lc = {0,};
return b4xxp_spanconfig(&b4->spans[0].span, &lc);
return b4xxp_spanconfig(NULL, &b4->spans[0].span, &lc);
}
static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

View File

@@ -608,7 +608,7 @@ static inline struct t1xxp *t1xxp_from_span(struct dahdi_span *span)
return container_of(span, struct t1xxp, span);
}
static int t1xxp_startup(struct dahdi_span *span)
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
{
struct t1xxp *wc = t1xxp_from_span(span);
@@ -714,7 +714,8 @@ static int t1xxp_maint(struct dahdi_span *span, int cmd)
return res;
}
static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype)
static int
t1xxp_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
{
struct t1xxp *wc = chan->pvt;
unsigned long flags;
@@ -729,7 +730,9 @@ static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype)
return 0;
}
static int t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int
t1xxp_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct t1xxp *wc = t1xxp_from_span(span);
@@ -737,7 +740,7 @@ static int t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc
wc->sync = (lc->sync) ? 1 : 0;
/* If already running, apply changes immediately */
if (span->flags & DAHDI_FLAG_RUNNING)
return t1xxp_startup(span);
return t1xxp_startup(file, span);
return 0;
}

View File

@@ -416,7 +416,7 @@ static const struct dahdi_echocan_ops vpm_ec_ops = {
#endif
static void __set_clear(struct t4 *wc, int span);
static int t4_startup(struct dahdi_span *span);
static int t4_startup(struct file *file, struct dahdi_span *span);
static int t4_shutdown(struct dahdi_span *span);
static int t4_rbsbits(struct dahdi_chan *chan, int bits);
static int t4_maint(struct dahdi_span *span, int cmd);
@@ -1901,7 +1901,9 @@ static void t4_chan_set_sigcap(struct dahdi_span *span, int x)
}
}
static int t4_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int
t4_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
int i;
struct t4_span *ts = container_of(span, struct t4_span, span);
@@ -1943,14 +1945,15 @@ static int t4_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
/* If we're already running, then go ahead and apply the changes */
if (span->flags & DAHDI_FLAG_RUNNING)
return t4_startup(span);
return t4_startup(file, span);
if (debug)
dev_info(&wc->dev->dev, "Done with spanconfig!\n");
return 0;
}
static int t4_chanconfig(struct dahdi_chan *chan, int sigtype)
static int
t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
{
int alreadyrunning;
unsigned long flags;
@@ -2671,7 +2674,7 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
wc->numspans, unit + 1, framing, line, crc4);
}
static int t4_startup(struct dahdi_span *span)
static int t4_startup(struct file *file, struct dahdi_span *span)
{
#ifdef SUPPORT_GEN1
int i;

View File

@@ -2175,7 +2175,8 @@ static int b400m_set_ntte(struct b400m_span *bspan, int te_mode, int term_on)
}
/* spanconfig for us means ...? */
int b400m_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
int b400m_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct b400m_span *bspan;
struct b400m *b4;
@@ -2250,7 +2251,7 @@ int b400m_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
* The solution to that is to simply increment the span's "restart" flag, and
* the driver's workqueue will do the dirty work on our behalf.
*/
int b400m_chanconfig(struct dahdi_chan *chan, int sigtype)
int b400m_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
{
int alreadyrunning;
struct b400m_span *bspan = bspan_from_dspan(chan->span);

View File

@@ -38,9 +38,10 @@ int wctdm_init_b400m(struct wctdm *wc, int card);
int wctdm_bri_checkisr(struct wctdm *wc, int card, int offset);
void wctdm_unload_b400m(struct wctdm *wc, int card);
void wctdm_hdlc_hard_xmit(struct dahdi_chan *chan);
int b400m_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc);
int b400m_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc);
int b400m_dchan(struct dahdi_span *span);
int b400m_chanconfig(struct dahdi_chan *chan, int sigtype);
int b400m_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype);
void b400m_post_init(struct b400m *b4);
void b400m_set_dahdi_span(struct b400m *b4, int spanno,
struct wctdm_span *wspan);

View File

@@ -878,7 +878,7 @@ static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
}
static int t1xxp_startup(struct dahdi_span *span)
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
{
struct t1 *wc = t1_from_span(span);
@@ -920,7 +920,8 @@ static int t1xxp_shutdown(struct dahdi_span *span)
}
static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype)
static int
t1xxp_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
{
struct t1 *wc = chan->pvt;
unsigned long flags;
@@ -935,7 +936,9 @@ static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype)
return 0;
}
static int t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int
t1xxp_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct t1 *wc = t1_from_span(span);
@@ -943,7 +946,7 @@ static int t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc
wc->sync = (lc->sync) ? 1 : 0;
/* If already running, apply changes immediately */
if (span->flags & DAHDI_FLAG_RUNNING)
return t1xxp_startup(span);
return t1xxp_startup(file, span);
return 0;
}

View File

@@ -929,7 +929,7 @@ static void set_span_devicetype(struct t1 *wc)
#endif
}
static int t1xxp_startup(struct dahdi_span *span)
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
{
struct t1 *wc = container_of(span, struct t1, span);
#ifndef CONFIG_VOICEBUS_ECREFERENCE
@@ -954,7 +954,8 @@ static int t1xxp_startup(struct dahdi_span *span)
return 0;
}
static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype)
static int t1xxp_chanconfig(struct file *file,
struct dahdi_chan *chan, int sigtype)
{
struct t1 *wc = chan->pvt;
if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) &&
@@ -1484,7 +1485,8 @@ static void t1_chan_set_sigcap(struct dahdi_span *span, int x)
}
static int
t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
t1xxp_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct t1 *wc = container_of(span, struct t1, span);
int i;
@@ -1504,7 +1506,7 @@ t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
/* If already running, apply changes immediately */
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags))
return t1xxp_startup(span);
return t1xxp_startup(file, span);
return 0;
}

View File

@@ -162,9 +162,11 @@ static void bri_packet_dump(const char *msg, xpacket_t *pack);
#ifdef CONFIG_PROC_FS
static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
#endif
static int bri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc);
static int bri_chanconfig(struct dahdi_chan *chan, int sigtype);
static int bri_startup(struct dahdi_span *span);
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc);
static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
int sigtype);
static int bri_startup(struct file *file, struct dahdi_span *span);
static int bri_shutdown(struct dahdi_span *span);
#define PROC_REGISTER_FNAME "slics"
@@ -1165,7 +1167,8 @@ static int BRI_card_close(xpd_t *xpd, lineno_t pos)
/*
* Called only for 'span' keyword in /etc/dahdi/system.conf
*/
static int bri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct phonedev *phonedev = container_of(span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
@@ -1210,7 +1213,8 @@ static int bri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
* Called from dahdi with spinlock held on chan. Must not call back
* dahdi functions.
*/
static int bri_chanconfig(struct dahdi_chan *chan, int sigtype)
static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
int sigtype)
{
DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype));
// FIXME: sanity checks:
@@ -1222,7 +1226,7 @@ static int bri_chanconfig(struct dahdi_chan *chan, int sigtype)
/*
* Called only for 'span' keyword in /etc/dahdi/system.conf
*/
static int bri_startup(struct dahdi_span *span)
static int bri_startup(struct file *file, struct dahdi_span *span)
{
struct phonedev *phonedev = container_of(span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);

View File

@@ -75,7 +75,7 @@ static bool is_sigtype_dchan(int sigtype)
static bool pri_packet_is_valid(xpacket_t *pack);
static void pri_packet_dump(const char *msg, xpacket_t *pack);
static int pri_startup(struct dahdi_span *span);
static int pri_startup(struct file *file, struct dahdi_span *span);
static int pri_shutdown(struct dahdi_span *span);
static int pri_rbsbits(struct dahdi_chan *chan, int bits);
static int pri_lineconfig(xpd_t *xpd, int lineconfig);
@@ -1033,7 +1033,8 @@ bad_lineconfig:
* Called only for 'span' keyword in /etc/dahdi/system.conf
*/
static int pri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
static int pri_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct phonedev *phonedev = container_of(span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
@@ -1068,7 +1069,8 @@ static int pri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
* Called from dahdi with spinlock held on chan. Must not call back
* dahdi functions.
*/
static int pri_chanconfig(struct dahdi_chan *chan, int sigtype)
static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
int sigtype)
{
struct phonedev *phonedev = container_of(chan->span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
@@ -1455,7 +1457,7 @@ static int PRI_card_close(xpd_t *xpd, lineno_t pos)
/*
* Called only for 'span' keyword in /etc/dahdi/system.conf
*/
static int pri_startup(struct dahdi_span *span)
static int pri_startup(struct file *file, struct dahdi_span *span)
{
struct phonedev *phonedev = container_of(span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);

View File

@@ -790,6 +790,8 @@ struct dahdi_count {
#define DAHDI_FLAG_TXUNDERRUN DAHDI_FLAG(TXUNDERRUN)
#define DAHDI_FLAG_RXOVERRUN DAHDI_FLAG(RXOVERRUN)
struct file;
struct dahdi_span_ops {
struct module *owner; /*!< Which module is exporting this span. */
@@ -799,10 +801,11 @@ struct dahdi_span_ops {
int (*setchunksize)(struct dahdi_span *span, int chunksize);
/*! Opt: Configure the span (if appropriate) */
int (*spanconfig)(struct dahdi_span *span, struct dahdi_lineconfig *lc);
int (*spanconfig)(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc);
/*! Opt: Start the span */
int (*startup)(struct dahdi_span *span);
int (*startup)(struct file *file, struct dahdi_span *span);
/*! Opt: Shutdown the span */
int (*shutdown)(struct dahdi_span *span);
@@ -817,7 +820,8 @@ struct dahdi_span_ops {
#endif
/* ==== Channel Callback Operations ==== */
/*! Opt: Set signalling type (if appropriate) */
int (*chanconfig)(struct dahdi_chan *chan, int sigtype);
int (*chanconfig)(struct file *file, struct dahdi_chan *chan,
int sigtype);
/*! Opt: Prepare a channel for I/O */
int (*open)(struct dahdi_chan *chan);