summaryrefslogtreecommitdiff
path: root/drivers/dahdi
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2010-09-20 20:34:44 +0000
committerShaun Ruffell <sruffell@digium.com>2010-09-20 20:34:44 +0000
commitb9f4ee7e13cc59f6c69f8ff4751a99a5f1e5f390 (patch)
treed36734b4b09c553f6d71d50c479d187f74e55f9e /drivers/dahdi
parente0a34c3567368308e1c3d7689f3db8edd7fa1e25 (diff)
dahdi: Channels can have their own file_operations structure.
If we know that an open file is associated with a channel (pseudo or real) we can just update the file->f_ops pointer so that we can short circuit some of the checks in read/write/poll. Trades sizeof(file_operations) bytes for less function call overhead in the "hot" path. On a 2.4 GHz Xeon, saves around 150 ns on each read / write. Review: https://reviewboard.asterisk.org/r/905/ Signed-off-by: Shaun Ruffell <sruffell@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9386 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi')
-rw-r--r--drivers/dahdi/dahdi-base.c121
1 files changed, 31 insertions, 90 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 72a01ae..4fe9303 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -233,7 +233,6 @@ static sumtype *conf_sums;
static sumtype *conf_sums_prev;
static struct dahdi_span *master;
-static struct file_operations dahdi_fops;
struct file_operations *dahdi_transcode_fops = NULL;
static struct {
@@ -2122,7 +2121,7 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
}
static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf,
- size_t count)
+ size_t count, loff_t *ppos)
{
struct dahdi_chan *chan = file->private_data;
int amnt;
@@ -2241,7 +2240,7 @@ static int num_filled_bufs(struct dahdi_chan *chan)
}
static ssize_t dahdi_chan_write(struct file *file, const char __user *usrbuf,
- size_t count)
+ size_t count, loff_t *ppos)
{
unsigned long flags;
struct dahdi_chan *chan = file->private_data;
@@ -2805,6 +2804,8 @@ static int dahdi_timer_release(struct file *file)
return 0;
}
+static const struct file_operations dahdi_chan_fops;
+
static int dahdi_specchan_open(struct file *file)
{
int res = 0;
@@ -2838,6 +2839,10 @@ static int dahdi_specchan_open(struct file *file)
if (!res) {
chan->file = file;
file->private_data = chan;
+ /* Since we know we're a channel now, we can
+ * update the f_op pointer and bypass a few of
+ * the checks on the minor number. */
+ file->f_op = &dahdi_chan_fops;
spin_unlock_irqrestore(&chan->lock, flags);
} else {
spin_unlock_irqrestore(&chan->lock, flags);
@@ -3003,69 +3008,6 @@ static int dahdi_open(struct file *file)
}
#endif
-static ssize_t dahdi_read(struct file *file, char __user *usrbuf, size_t count, loff_t *ppos)
-{
- int unit = UNIT(file);
- struct dahdi_chan *chan;
-
- /* Can't read from control */
- if (!unit) {
- return -EINVAL;
- }
-
- if (unit == 253)
- return -EINVAL;
-
- if (unit == 254) {
- chan = file->private_data;
- if (!chan)
- return -EINVAL;
- return dahdi_chan_read(file, usrbuf, count);
- }
-
- if (unit == 255) {
- chan = file->private_data;
- if (!chan) {
- module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
- return -EINVAL;
- }
- return dahdi_chan_read(file, usrbuf, count);
- }
- if (count < 0)
- return -EINVAL;
-
- return dahdi_chan_read(file, usrbuf, count);
-}
-
-static ssize_t dahdi_write(struct file *file, const char __user *usrbuf, size_t count, loff_t *ppos)
-{
- int unit = UNIT(file);
- struct dahdi_chan *chan;
- /* Can't read from control */
- if (!unit)
- return -EINVAL;
- if (count < 0)
- return -EINVAL;
- if (unit == 253)
- return -EINVAL;
- if (unit == 254) {
- chan = file->private_data;
- if (!chan)
- return -EINVAL;
- return dahdi_chan_write(file, usrbuf, count);
- }
- if (unit == 255) {
- chan = file->private_data;
- if (!chan) {
- module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
- return -EINVAL;
- }
- return dahdi_chan_write(file, usrbuf, count);
- }
- return dahdi_chan_write(file, usrbuf, count);
-
-}
-
static int dahdi_set_default_zone(int defzone)
{
if ((defzone < 0) || (defzone >= DAHDI_TONE_ZONE_MAX))
@@ -8325,30 +8267,14 @@ dahdi_chan_poll(struct file *file, struct poll_table_struct *wait_table)
static unsigned int dahdi_poll(struct file *file, struct poll_table_struct *wait_table)
{
- int unit = UNIT(file);
-
- if (!unit)
- return -EINVAL;
-
- if (unit == 250)
- return dahdi_transcode_fops->poll(file, wait_table);
+ const int unit = UNIT(file);
- if (unit == 253)
+ if (likely(unit == 253))
return dahdi_timer_poll(file, wait_table);
- if (unit == 254) {
- if (!file->private_data)
- return -EINVAL;
- return dahdi_chan_poll(file, wait_table);
- }
- if (unit == 255) {
- if (!file->private_data) {
- module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
- return -EINVAL;
- }
- return dahdi_chan_poll(file, wait_table);
- }
- return dahdi_chan_poll(file, wait_table);
+ /* transcoders and channels should have updated their file_operations
+ * before poll is ever called. */
+ return -EINVAL;
}
static void __dahdi_transmit_chunk(struct dahdi_chan *chan, unsigned char *buf)
@@ -8868,7 +8794,7 @@ MODULE_VERSION(DAHDI_VERSION);
module_param(debug, int, 0644);
module_param(deftaps, int, 0644);
-static struct file_operations dahdi_fops = {
+static const struct file_operations dahdi_fops = {
.owner = THIS_MODULE,
.open = dahdi_open,
.release = dahdi_release,
@@ -8880,11 +8806,26 @@ static struct file_operations dahdi_fops = {
#else
.ioctl = dahdi_ioctl,
#endif
- .read = dahdi_read,
- .write = dahdi_write,
.poll = dahdi_poll,
};
+static const struct file_operations dahdi_chan_fops = {
+ .owner = THIS_MODULE,
+ .open = dahdi_open,
+ .release = dahdi_release,
+#ifdef HAVE_UNLOCKED_IOCTL
+ .unlocked_ioctl = dahdi_ioctl,
+#ifdef HAVE_COMPAT_IOCTL
+ .compat_ioctl = dahdi_ioctl_compat,
+#endif
+#else
+ .ioctl = dahdi_ioctl,
+#endif
+ .read = dahdi_chan_read,
+ .write = dahdi_chan_write,
+ .poll = dahdi_chan_poll,
+};
+
#ifdef CONFIG_DAHDI_WATCHDOG
static struct timer_list watchdogtimer;