Re: [PATCH] mISDN cleanup user interface

Previous thread: [PATCH] mISDN fix main ISDN Makefile by Karsten Keil on Tuesday, July 29, 2008 - 12:51 pm. (1 message)

Next thread: [patch 2.6.27-rc1] legacy rtc: remove needless/confusing HPET_RTC_IRQ option by David Brownell on Tuesday, July 29, 2008 - 12:35 pm. (1 message)
From: Karsten Keil
Date: Tuesday, July 29, 2008 - 12:56 pm

Please pull from git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6.git master

The channelmap should have the same size on 32 and 64 bit
systems. Thanks to David Woodhouse for spotting this.

Signed-off-by: Karsten Keil <kkeil@suse.de>
---
 drivers/isdn/hardware/mISDN/hfcmulti.c |    6 +++---
 drivers/isdn/hardware/mISDN/hfcpci.c   |    2 +-
 drivers/isdn/mISDN/l1oip_core.c        |    4 +++-
 drivers/isdn/mISDN/socket.c            |    4 ++--
 include/linux/mISDNif.h                |    7 ++++---
 5 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 2649ea5..6449ffa 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3971,7 +3971,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
 	struct bchannel	*bch;
 	int		ch;
 
-	if (!test_bit(rq->adr.channel, &dch->dev.channelmap[0]))
+	if (!test_bit(rq->adr.channel, (u_long *)&dch->dev.channelmap[0]))
 		return -EINVAL;
 	if (rq->protocol == ISDN_P_NONE)
 		return -EINVAL;
@@ -4587,7 +4587,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
 		list_add(&bch->ch.list, &dch->dev.bchannels);
 		hc->chan[ch].bch = bch;
 		hc->chan[ch].port = 0;
-		test_and_set_bit(bch->nr, &dch->dev.channelmap[0]);
+		test_and_set_bit(bch->nr, (u_long *)&dch->dev.channelmap[0]);
 	}
 	/* set optical line type */
 	if (port[Port_cnt] & 0x001) {
@@ -4755,7 +4755,7 @@ init_multi_port(struct hfc_multi *hc, int pt)
 		list_add(&bch->ch.list, &dch->dev.bchannels);
 		hc->chan[i + ch].bch = bch;
 		hc->chan[i + ch].port = pt;
-		test_and_set_bit(bch->nr, &dch->dev.channelmap[0]);
+		test_and_set_bit(bch->nr, (u_long *)&dch->dev.channelmap[0]);
 	}
 	/* set master clock */
 	if (port[Port_cnt] & 0x001) {
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 3231814..b111179 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ ...
From: David Woodhouse
Date: Tuesday, July 29, 2008 - 1:22 pm

Er, isn't that still broken? Consider 32-bit userspace on 64-bit kernel,
big-endian.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation



--

From: Marcel Holtmann
Date: Tuesday, July 29, 2008 - 2:02 pm

I agree with David here. Please lets not do these horribly things again.
Almost everybody has done their fair share of brokenness with the compat
layers. Especially 32-bit userspace on 64-bit kernels. Using __u32 and
alike is a way better choice and less headache.

Regards

Marcel


--

From: David Woodhouse
Date: Wednesday, July 30, 2008 - 2:13 am

Well, he's already switched to a 32-bit type, which is fine in that
respect -- at least the struct is the same _size_ on 32-bit and 64-bit
targets now. (OK, so inventing new types like 'u_int' instead of just
using the ones that the C language provides is a bit silly, but that's
the Linux norm so I wasn't complaining about that.)

But the channelmap field is still broken because it's using set_bit() on
int types, and they're defined to work on unsigned long. So in the
fairly common case where a BRI driver sets bits 1 and 2 (sic) in the
channel map, that will look like this on a 64-bit big-endian kernel:

 00 00 00 00 00 00 00 06   00 00 00 00 00 00 00 00
    (unsigned long #1)       (unsigned long #2)

When 32-bit userspace receives that, it'll see this:

 00 00 00 00   00 00 00 06   00 00 00 00   00 00 00 00
  (word #1)     (word #2)     (word #3)     (word #4)

.. in which it's bits 33 and 34 that are set. So the new version in the
patch to which I replied _still_ needs a compat routine.

You might get away with it if you use set_le_bit() though.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation



--

From: Karsten Keil
Date: Wednesday, July 30, 2008 - 9:33 am

What about this implementation ?

From a0969b4fd0bc88e155f3723bbc306a7b399c6112 Mon Sep 17 00:00:00 2001
From: Karsten Keil <kkeil@suse.de>
Date: Wed, 30 Jul 2008 18:26:58 +0200
Subject: [PATCH] mISDN cleanup user interface

The channelmap should have the same size on 32 and 64 bit systems
and should not depend on endianess.
Thanks to David Woodhouse for spotting this.

Signed-off-by: Karsten Keil <kkeil@suse.de>
---
 drivers/isdn/hardware/mISDN/hfcmulti.c |    6 +++---
 drivers/isdn/hardware/mISDN/hfcpci.c   |    2 +-
 drivers/isdn/mISDN/l1oip_core.c        |    6 ++----
 drivers/isdn/mISDN/socket.c            |    4 ++--
 include/linux/mISDNif.h                |   32 +++++++++++++++++++++++++++-----
 5 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 2649ea5..10144e8 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3971,7 +3971,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
 	struct bchannel	*bch;
 	int		ch;
 
-	if (!test_bit(rq->adr.channel, &dch->dev.channelmap[0]))
+	if (!test_channelmap(rq->adr.channel, dch->dev.channelmap))
 		return -EINVAL;
 	if (rq->protocol == ISDN_P_NONE)
 		return -EINVAL;
@@ -4587,7 +4587,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
 		list_add(&bch->ch.list, &dch->dev.bchannels);
 		hc->chan[ch].bch = bch;
 		hc->chan[ch].port = 0;
-		test_and_set_bit(bch->nr, &dch->dev.channelmap[0]);
+		set_channelmap(bch->nr, dch->dev.channelmap);
 	}
 	/* set optical line type */
 	if (port[Port_cnt] & 0x001) {
@@ -4755,7 +4755,7 @@ init_multi_port(struct hfc_multi *hc, int pt)
 		list_add(&bch->ch.list, &dch->dev.bchannels);
 		hc->chan[i + ch].bch = bch;
 		hc->chan[i + ch].port = pt;
-		test_and_set_bit(bch->nr, &dch->dev.channelmap[0]);
+		set_channelmap(bch->nr, dch->dev.channelmap);
 	}
 	/* set master clock */
 	if (port[Port_cnt] & 0x001) {
diff --git ...
From: David Woodhouse
Date: Wednesday, July 30, 2008 - 9:57 am

Looks a lot saner... although it does seem to confirm my earlier
suspicion that you're not even _using_ the fact that it's a bitmap at
all. You set the bits for the present channels at init time, which are
always contiguous, and you never seem to change them them later -- why
couldn't you do this with a simple 'number of channels' integer?

Are you later intending to use the bitmap to mark them as busy/free?

-- 
dwmw2

--

From: Karsten Keil
Date: Wednesday, July 30, 2008 - 10:51 am

No it is not contineous on different PRI line setups (E1,T1 ...)
e.g a E1 has the D-channel on channel 15 position, so this bit is not set
then. My idea was, that with such a bitmap, applictions do not need to know
anything about the different channel layouts, it can use the map as base to assign

Yes exactely, and this was the reason why the original code (which used one u_long
only as channelmap) already used the bit operators, since for a channel allocator
you should be atomic, but since we are now allow 127 channels we need proper
locking for the busy/free map anyways and so we do not need atomic operation
here.

-- 
Karsten Keil
SuSE Labs
ISDN and VOIP development
SUSE LINUX Products GmbH, Maxfeldstr.5 90409 Nuernberg, GF: Markus Rex, HRB 16746 (AG Nuernberg)
--

From: Sam Ravnborg
Date: Wednesday, July 30, 2008 - 11:37 am

timeslot 16 in my book actually - but maybe that your timeslot to
channel mapping.

Not that it has anything to do with the topic discussed!

	Sam
--

From: Karsten Keil
Date: Wednesday, July 30, 2008 - 11:46 am

You are correct of course.

-- 
Karsten Keil
SuSE Labs
ISDN and VOIP development
SUSE LINUX Products GmbH, Maxfeldstr.5 90409 Nuernberg, GF: Markus Rex, HRB 16746 (AG Nuernberg)
--

From: David Woodhouse
Date: Wednesday, July 30, 2008 - 12:08 pm

OK, that makes sense then. Your latest patch looks good in that case.

-- 
dwmw2

--

From: Karsten Keil
Date: Wednesday, July 30, 2008 - 8:08 am

URGH, you are right, using the bit operations here is not a good idea at
all and currently we also need not to be atomic for this map so we can use a
bytearray and simple operation here.

-- 
Karsten Keil
SuSE Labs
ISDN and VOIP development
SUSE LINUX Products GmbH, Maxfeldstr.5 90409 Nuernberg, GF: Markus Rex, HRB 16746 (AG Nuernberg)
--

From: Linus Torvalds
Date: Friday, August 1, 2008 - 10:21 am

Grr. What's the status of this now? That branch is unpullable - you've put 
pretty much the same patch in twice, reverted it once, and added some 
merge into it too. So of the five commits, less than half are actually 
useful and worthwhile.

		Linus
--

From: Karsten Keil
Date: Saturday, August 2, 2008 - 8:21 am

I created a new clean merge tree, it contain the last 4 patches I posted
some minutes ago.

git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6.git master


-- 
Karsten Keil
SuSE Labs
ISDN and VOIP development
SUSE LINUX Products GmbH, Maxfeldstr.5 90409 Nuernberg, GF: Markus Rex, HRB 16746 (AG Nuernberg)
--

Previous thread: [PATCH] mISDN fix main ISDN Makefile by Karsten Keil on Tuesday, July 29, 2008 - 12:51 pm. (1 message)

Next thread: [patch 2.6.27-rc1] legacy rtc: remove needless/confusing HPET_RTC_IRQ option by David Brownell on Tuesday, July 29, 2008 - 12:35 pm. (1 message)