2009-06-11 17:28:21

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 0/6] ISDN fixes

Some more fixes for ISDN.

You can pull it from
git://master.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6-net-next.git for_david

Andreas Mohr (1):
mISDN: Free hfcpci IRQ if init was not successful

Karsten Keil (4):
ISDN:Fix DMA alloc for hfcpci
mISDN: Fix overlapping data access
mISDN: Do not disable IRQ in ph_data_ind()
mISDN: cleanup mISDNhw.h

Roel Kluin (1):
drivers/isdn/i4l/isdn_tty.c: fix check for array overindexing

drivers/isdn/hardware/mISDN/hfcpci.c | 7 ++---
drivers/isdn/hisax/hfc_pci.c | 41 ++++++++++++++++++++++++---------
drivers/isdn/hisax/hisax.h | 2 +-
drivers/isdn/i4l/isdn_tty.c | 2 +-
drivers/isdn/mISDN/dsp_pipeline.c | 11 ++++-----
drivers/isdn/mISDN/tei.c | 7 +----
include/linux/mISDNhw.h | 10 --------
7 files changed, 42 insertions(+), 38 deletions(-)


2009-06-11 17:28:38

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 1/6] ISDN:Fix DMA alloc for hfcpci

Replace wrong code with correct DMA API functions.

Signed-off-by: Karsten Keil <[email protected]>
---
drivers/isdn/hisax/hfc_pci.c | 41 ++++++++++++++++++++++++++++++-----------
drivers/isdn/hisax/hisax.h | 2 +-
2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index f126566..3d337d9 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -82,8 +82,9 @@ release_io_hfcpci(struct IsdnCardState *cs)
Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */
del_timer(&cs->hw.hfcpci.timer);
- kfree(cs->hw.hfcpci.share_start);
- cs->hw.hfcpci.share_start = NULL;
+ pci_free_consistent(cs->hw.hfcpci.dev, 0x8000,
+ cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma);
+ cs->hw.hfcpci.fifos = NULL;
iounmap((void *)cs->hw.hfcpci.pci_io);
}

@@ -1663,8 +1664,19 @@ setup_hfcpci(struct IsdnCard *card)
dev_hfcpci);
i++;
if (tmp_hfcpci) {
+ dma_addr_t dma_mask = DMA_BIT_MASK(32) & ~0x7fffUL;
if (pci_enable_device(tmp_hfcpci))
continue;
+ if (pci_set_dma_mask(tmp_hfcpci, dma_mask)) {
+ printk(KERN_WARNING
+ "HiSax hfc_pci: No suitable DMA available.\n");
+ continue;
+ }
+ if (pci_set_consistent_dma_mask(tmp_hfcpci, dma_mask)) {
+ printk(KERN_WARNING
+ "HiSax hfc_pci: No suitable consistent DMA available.\n");
+ continue;
+ }
pci_set_master(tmp_hfcpci);
if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
continue;
@@ -1693,22 +1705,29 @@ setup_hfcpci(struct IsdnCard *card)
printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
return (0);
}
+
/* Allocate memory for FIFOS */
- /* Because the HFC-PCI needs a 32K physical alignment, we */
- /* need to allocate the double mem and align the address */
- if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
- printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+ cs->hw.hfcpci.fifos = pci_alloc_consistent(cs->hw.hfcpci.dev,
+ 0x8000, &cs->hw.hfcpci.dma);
+ if (!cs->hw.hfcpci.fifos) {
+ printk(KERN_WARNING "HFC-PCI: Error allocating FIFO memory!\n");
+ return 0;
+ }
+ if (cs->hw.hfcpci.dma & 0x7fff) {
+ printk(KERN_WARNING
+ "HFC-PCI: Error DMA memory not on 32K boundary (%lx)\n",
+ (u_long)cs->hw.hfcpci.dma);
+ pci_free_consistent(cs->hw.hfcpci.dev, 0x8000,
+ cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma);
return 0;
}
- cs->hw.hfcpci.fifos = (void *)
- (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
- pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+ pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u32)cs->hw.hfcpci.dma);
cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
printk(KERN_INFO
- "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
+ "HFC-PCI: defined at mem %p fifo %p(%lx) IRQ %d HZ %d\n",
cs->hw.hfcpci.pci_io,
cs->hw.hfcpci.fifos,
- (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
+ (u_long)cs->hw.hfcpci.dma,
cs->irq, HZ);

spin_lock_irqsave(&cs->lock, flags);
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index f852704..0685c19 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -703,7 +703,7 @@ struct hfcPCI_hw {
int nt_timer;
struct pci_dev *dev;
unsigned char *pci_io; /* start of PCI IO memory */
- void *share_start; /* shared memory for Fifos start */
+ dma_addr_t dma; /* dma handle for Fifos */
void *fifos; /* FIFO memory */
int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */
struct timer_list timer;
--
1.6.0.2

2009-06-11 17:28:55

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 2/6] mISDN: Fix overlapping data access

Remove code rewriting a buffer by itself.
This fix bug 12970 on bugzilla.kernel.org.

Signed-off-by: Karsten Keil <[email protected]>
---
drivers/isdn/mISDN/dsp_pipeline.c | 11 +++++------
1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
index ac61f19..e994167 100644
--- a/drivers/isdn/mISDN/dsp_pipeline.c
+++ b/drivers/isdn/mISDN/dsp_pipeline.c
@@ -55,20 +55,19 @@ static ssize_t
attr_show_args(struct device *dev, struct device_attribute *attr, char *buf)
{
struct mISDN_dsp_element *elem = dev_get_drvdata(dev);
- ssize_t len = 0;
- int i = 0;
+ int i;
+ char *p = buf;

*buf = 0;
- for (; i < elem->num_args; ++i)
- len = sprintf(buf, "%sName: %s\n%s%s%sDescription: %s\n"
- "\n", buf,
+ for (i = 0; i < elem->num_args; i++)
+ p += sprintf(p, "Name: %s\n%s%s%sDescription: %s\n\n",
elem->args[i].name,
elem->args[i].def ? "Default: " : "",
elem->args[i].def ? elem->args[i].def : "",
elem->args[i].def ? "\n" : "",
elem->args[i].desc);

- return len;
+ return p - buf;
}

static struct device_attribute element_attributes[] = {
--
1.6.0.2

2009-06-11 17:29:33

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 4/6] drivers/isdn/i4l/isdn_tty.c: fix check for array overindexing

From: Roel Kluin <[email protected]>

The check for overindexing of dev->mdm.info[] has an off-by-one.

Signed-off-by: Roel Kluin <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Acked-by: Karsten Keil <[email protected]>
---
drivers/isdn/i4l/isdn_tty.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 1a2222c..b4d4522 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1592,7 +1592,7 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
int retval, line;

line = tty->index;
- if (line < 0 || line > ISDN_MAX_CHANNELS)
+ if (line < 0 || line >= ISDN_MAX_CHANNELS)
return -ENODEV;
info = &dev->mdm.info[line];
if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
--
1.6.0.2

2009-06-11 17:29:15

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 3/6] mISDN: Free hfcpci IRQ if init was not successful

From: Andreas Mohr <[email protected]>

If we get no interrupts for after 3 resets we need to unregister
the interrupt function, which is already done outside the loop.

Signed-off-by: Andreas Mohr <[email protected]>
Signed-off-by: Karsten Keil <[email protected]>
---
drivers/isdn/hardware/mISDN/hfcpci.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 776afc8..228ffbe 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -1806,10 +1806,9 @@ init_card(struct hfc_pci *hc)
printk(KERN_WARNING
"HFC PCI: IRQ(%d) getting no interrupts "
"during init %d\n", hc->irq, 4 - cnt);
- if (cnt == 1) {
- spin_unlock_irqrestore(&hc->lock, flags);
- return -EIO;
- } else {
+ if (cnt == 1)
+ break;
+ else {
reset_hfcpci(hc);
cnt--;
}
--
1.6.0.2

2009-06-11 17:29:44

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 5/6] mISDN: Do not disable IRQ in ph_data_ind()

This fix triggering the WARN_ON_ONCE(in_irq() || irqs_disabled()); in
local_bh_enable().

Here is no need to grab this lock, this was wrong at all and may
cause a deadlock and access to freed memory, since on a TEI remove
the current listelement can be deleted under us. So this is clearly
a case for list_for_each_entry_safe.

Signed-off-by: Karsten Keil <[email protected]>
---
drivers/isdn/mISDN/tei.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index bfcdd97..e04bad6 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -862,8 +862,7 @@ static int
ph_data_ind(struct manager *mgr, struct sk_buff *skb)
{
int ret = -EINVAL;
- struct layer2 *l2;
- u_long flags;
+ struct layer2 *l2, *nl2;
u_char mt;

if (skb->len < 8) {
@@ -908,11 +907,9 @@ ph_data_ind(struct manager *mgr, struct sk_buff *skb)
new_tei_req(mgr, &skb->data[4]);
goto done;
}
- read_lock_irqsave(&mgr->lock, flags);
- list_for_each_entry(l2, &mgr->layer2, list) {
+ list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
tei_ph_data_ind(l2->tm, mt, &skb->data[4], skb->len - 4);
}
- read_unlock_irqrestore(&mgr->lock, flags);
done:
return ret;
}
--
1.6.0.2

2009-06-11 17:29:56

by Karsten Keil

[permalink] [raw]
Subject: [PATCH 6/6] mISDN: cleanup mISDNhw.h

Remove unused stuff.

Signed-off-by: Karsten Keil <[email protected]>
---
include/linux/mISDNhw.h | 10 ----------
1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index ce900f4..7f9831d 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -89,11 +89,6 @@ struct dchannel {
void (*phfunc) (struct dchannel *);
u_int state;
void *l1;
- /* HW access */
- u_char (*read_reg) (void *, u_char);
- void (*write_reg) (void *, u_char, u_char);
- void (*read_fifo) (void *, u_char *, int);
- void (*write_fifo) (void *, u_char *, int);
void *hw;
int slot; /* multiport card channel slot */
struct timer_list timer;
@@ -151,11 +146,6 @@ struct bchannel {
u_long Flags;
struct work_struct workq;
u_int state;
- /* HW access */
- u_char (*read_reg) (void *, u_char);
- void (*write_reg) (void *, u_char, u_char);
- void (*read_fifo) (void *, u_char *, int);
- void (*write_fifo) (void *, u_char *, int);
void *hw;
int slot; /* multiport card channel slot */
struct timer_list timer;
--
1.6.0.2

2009-06-11 23:53:17

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 0/6] ISDN fixes

From: Karsten Keil <[email protected]>
Date: Thu, 11 Jun 2009 19:06:34 +0200

> Some more fixes for ISDN.
>
> You can pull it from
> git://master.kernel.org/pub/scm/linux/kernel/git/kkeil/ISDN-2.6-net-next.git for_david

That URL won't work for anyone.

The GIT service only runs on git.kernel.org, master.kernel.org only
provides SSH based connections.

I've pulled and will do some sanity checks on this before pushing
back out, thanks!