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
+++ ...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 --
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 --
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
--
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 ...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 --
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) --
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 --
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) --
OK, that makes sense then. Your latest patch looks good in that case. -- dwmw2 --
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) --
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 --
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) --
