patch-2.4.23 linux-2.4.23/drivers/net/wan/dscc4.c
Next file: linux-2.4.23/drivers/net/wan/farsync.c
Previous file: linux-2.4.23/drivers/net/wan/c101.c
Back to the patch index
Back to the overall index
- Lines: 695
- Date:
2003-11-28 10:26:20.000000000 -0800
- Orig file:
linux-2.4.22/drivers/net/wan/dscc4.c
- Orig date:
2003-06-13 07:51:35.000000000 -0700
diff -urN linux-2.4.22/drivers/net/wan/dscc4.c linux-2.4.23/drivers/net/wan/dscc4.c
@@ -47,7 +47,7 @@
* Tx direction
* When the tx ring is full, the xmit routine issues a call to netdev_stop.
* The device is supposed to be enabled again during an ALLS irq (we could
- * use HI but as it's easy to loose events, it's fscked).
+ * use HI but as it's easy to lose events, it's fscked).
*
* Rx direction
* The received frames aren't supposed to span over multiple receiving areas.
@@ -80,7 +80,6 @@
* - misc crapectomy.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -108,10 +107,15 @@
#include <linux/hdlc.h>
/* Version */
-static const char version[] = "$Id: dscc4.c,v 1.159 2002/04/10 22:05:17 romieu Exp $ for Linux\n";
+static const char version[] = "$Id: dscc4.c,v 1.173 2003/09/20 23:55:34 romieu Exp $ for Linux\n";
static int debug;
static int quartz;
+#ifdef CONFIG_DSCC4_PCI_RST
+static DECLARE_MUTEX(dscc4_sem);
+static u32 dscc4_pci_config_store[16];
+#endif
+
#define DRV_NAME "dscc4"
#undef DSCC4_POLLING
@@ -164,8 +168,15 @@
#define SOURCE_ID(flags) (((flags) >> 28) & 0x03)
#define TO_SIZE(state) (((state) >> 16) & 0x1fff)
-#define TO_STATE(len) cpu_to_le32(((len) & TxSizeMax) << 16)
-#define RX_MAX(len) ((((len) >> 5) + 1) << 5)
+
+/*
+ * Given the operating range of Linux HDLC, the 2 defines below could be
+ * made simpler. However they are a fine reminder for the limitations of
+ * the driver: it's better to stay < TxSizeMax and < RxSizeMax.
+ */
+#define TO_STATE_TX(len) cpu_to_le32(((len) & TxSizeMax) << 16)
+#define TO_STATE_RX(len) cpu_to_le32((RX_MAX(len) % RxSizeMax) << 16)
+#define RX_MAX(len) ((((len) >> 5) + 1) << 5) /* Cf RLCR */
#define SCC_REG_START(dpriv) (SCC_START+(dpriv->dev_id)*SCC_OFFSET)
struct dscc4_pci_priv {
@@ -256,6 +267,10 @@
#define IMR 0x54
#define ISR 0x58
+#define GPDIR 0x0400
+#define GPDATA 0x0404
+#define GPIM 0x0408
+
/* Bit masks */
#define EncodingMask 0x00700000
#define CrcMask 0x00000003
@@ -272,7 +287,8 @@
#define Idt 0x00080000
#define TxSccRes 0x01000000
#define RxSccRes 0x00010000
-#define TxSizeMax 0x1fff
+#define TxSizeMax 0x1fff /* Datasheet DS1 - 11.1.1.1 */
+#define RxSizeMax 0x1ffc /* Datasheet DS1 - 11.1.2.1 */
#define Ccr0ClockMask 0x0000003f
#define Ccr1LoopMask 0x00000200
@@ -283,6 +299,7 @@
#define Hold 0x40000000
#define SccBusy 0x10000000
#define PowerUp 0x80000000
+#define Vis 0x00001000
#define FrameOk (FrameVfr | FrameCrc)
#define FrameVfr 0x80
#define FrameRdo 0x40
@@ -319,10 +336,19 @@
#define Arf 0x00000002
#define ArAck 0x00000001
-/* Misc */
+/* State flags */
+#define Ready 0x00000000
#define NeedIDR 0x00000001
#define NeedIDT 0x00000002
#define RdoSet 0x00000004
+#define FakeReset 0x00000008
+
+/* Don't mask RDO. Ever. */
+#ifdef DSCC4_POLLING
+#define EventsMask 0xfffeef7f
+#else
+#define EventsMask 0xfffa8f7a
+#endif
/* Functions prototypes */
static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
@@ -487,9 +513,9 @@
skb = dev_alloc_skb(len);
dpriv->rx_skbuff[dirty] = skb;
if (skb) {
- skb->dev = dev;
- skb->protocol = htons(ETH_P_HDLC);
- skb->mac.raw = skb->data;
+ skb->dev = dev;
+ skb->protocol = hdlc_type_trans(skb, dev);
+ skb->mac.raw = skb->data;
rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data,
len, PCI_DMA_FROMDEVICE);
} else {
@@ -566,15 +592,19 @@
return (i >= 0 ) ? i : -EAGAIN;
}
-/* Requires protection against interrupt */
+#if 0 /* dscc4_{rx/tx}_reset are both unreliable - more tweak needed */
static void dscc4_rx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dpriv->pci_priv->lock, flags);
/* Cf errata DS5 p.6 */
writel(0x00000000, dev->base_addr + CH0LRDA + dpriv->dev_id*4);
- scc_writel(~PowerUp & scc_readl(dpriv, CCR0), dpriv, dev, CCR0);
+ scc_patchl(PowerUp, 0, dpriv, dev, CCR0);
readl(dev->base_addr + CH0LRDA + dpriv->dev_id*4);
writel(MTFi|Rdr, dev->base_addr + dpriv->dev_id*0x0c + CH0CFG);
writel(Action, dev->base_addr + GCMDR);
+ spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags);
}
static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
@@ -582,7 +612,7 @@
u16 i = 0;
/* Cf errata DS5 p.7 */
- scc_writel(~PowerUp & scc_readl(dpriv, CCR0), dpriv, dev, CCR0);
+ scc_patchl(PowerUp, 0, dpriv, dev, CCR0);
scc_writel(0x00050000, dpriv, dev, CCR2);
/*
* Must be longer than the time required to fill the fifo.
@@ -596,6 +626,7 @@
if (dscc4_do_action(dev, "Rdt") < 0)
printk(KERN_ERR "%s: Tx reset failed\n", dev->name);
}
+#endif
/* TODO: (ab)use this function to refill a completely depleted RX ring. */
static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv,
@@ -619,6 +650,8 @@
stats->rx_packets++;
stats->rx_bytes += pkt_len;
skb_put(skb, pkt_len);
+ if (netif_running(dev))
+ skb->protocol = hdlc_type_trans(skb, dev);
skb->dev->last_rx = jiffies;
netif_rx(skb);
} else {
@@ -661,8 +694,8 @@
kfree(ppriv);
}
-static int __init dscc4_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit dscc4_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct dscc4_pci_priv *priv;
struct dscc4_dev_priv *dpriv;
@@ -805,7 +838,8 @@
static void dscc4_init_registers(struct dscc4_dev_priv *dpriv,
struct net_device *dev)
{
- scc_writel(0x80001000, dpriv, dev, CCR0);
+ /* No interrupts, SCC core disabled. Let's relax */
+ scc_writel(0x00000000, dpriv, dev, CCR0);
scc_writel(LengthCheck | (HDLC_MAX_MRU >> 5), dpriv, dev, RLCR);
@@ -813,29 +847,21 @@
* No address recognition/crc-CCITT/cts enabled
* Shared flags transmission disabled - cf errata DS5 p.11
* Carrier detect disabled - cf errata p.14
+ * FIXME: carrier detection/polarity may be handled more gracefully.
*/
- scc_writel(0x021c8000, dpriv, dev, CCR1);
+ scc_writel(0x02408000, dpriv, dev, CCR1);
/* crc not forwarded - Cf errata DS5 p.11 */
scc_writel(0x00050008 & ~RxActivate, dpriv, dev, CCR2);
// crc forwarded
//scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2);
-
- /* Don't mask RDO. Ever. */
-#ifdef DSCC4_POLLING
- scc_writel(0xfffeef7f, dpriv, dev, IMR); /* Interrupt mask */
-#else
- //scc_writel(0xfffaef7f, dpriv, dev, IMR); /* Interrupt mask */
- //scc_writel(0xfffaef7e, dpriv, dev, IMR); /* Interrupt mask */
- scc_writel(0xfffa8f7a, dpriv, dev, IMR); /* Interrupt mask */
-#endif
}
static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
{
struct dscc4_pci_priv *ppriv;
struct dscc4_dev_priv *root;
- int i = 0;
+ int i, ret = -ENOMEM;
root = (struct dscc4_dev_priv *)
kmalloc(dev_per_card*sizeof(*root), GFP_KERNEL);
@@ -867,6 +893,8 @@
d->tx_timeout = dscc4_tx_timeout;
d->watchdog_timeo = TX_TIMEOUT;
+ SET_MODULE_OWNER(d);
+
dpriv->dev_id = i;
dpriv->pci_priv = ppriv;
spin_lock_init(&dpriv->lock);
@@ -874,31 +902,40 @@
hdlc->xmit = dscc4_start_xmit;
hdlc->attach = dscc4_hdlc_attach;
- if (register_hdlc_device(hdlc)) {
+ ret = register_hdlc_device(hdlc);
+ if (ret < 0) {
printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
goto err_unregister;
}
- hdlc->proto = IF_PROTO_HDLC;
- SET_MODULE_OWNER(d);
+
dscc4_init_registers(dpriv, d);
dpriv->parity = PARITY_CRC16_PR0_CCITT;
dpriv->encoding = ENCODING_NRZ;
+
+ ret = dscc4_init_ring(d);
+ if (ret < 0) {
+ unregister_hdlc_device(hdlc);
+ goto err_unregister;
+ }
}
- if (dscc4_set_quartz(root, quartz) < 0)
+ ret = dscc4_set_quartz(root, quartz);
+ if (ret < 0)
goto err_unregister;
ppriv->root = root;
spin_lock_init(&ppriv->lock);
pci_set_drvdata(pdev, ppriv);
- return 0;
+ return ret;
err_unregister:
- while (--i >= 0)
+ while (--i >= 0) {
+ dscc4_release_ring(root + i);
unregister_hdlc_device(&root[i].hdlc);
+ }
kfree(ppriv);
err_free_dev:
kfree(root);
err_out:
- return -1;
+ return ret;
};
/* FIXME: get rid of the unneeded code */
@@ -932,6 +969,46 @@
return 0;
}
+#ifdef CONFIG_DSCC4_PCI_RST
+/*
+ * Some DSCC4-based cards wires the GPIO port and the PCI #RST pin together
+ * so as to provide a safe way to reset the asic while not the whole machine
+ * rebooting.
+ *
+ * This code doesn't need to be efficient. Keep It Simple
+ */
+static void dscc4_pci_reset(struct pci_dev *pdev, u32 ioaddr)
+{
+ int i;
+
+ down(&dscc4_sem);
+ for (i = 0; i < 16; i++)
+ pci_read_config_dword(pdev, i << 2, dscc4_pci_config_store + i);
+
+ /* Maximal LBI clock divider (who cares ?) and whole GPIO range. */
+ writel(0x001c0000, ioaddr + GMODE);
+ /* Configure GPIO port as output */
+ writel(0x0000ffff, ioaddr + GPDIR);
+ /* Disable interruption */
+ writel(0x0000ffff, ioaddr + GPIM);
+
+ writel(0x0000ffff, ioaddr + GPDATA);
+ writel(0x00000000, ioaddr + GPDATA);
+
+ /* Flush posted writes */
+ readl(ioaddr + GSTAR);
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10);
+
+ for (i = 0; i < 16; i++)
+ pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
+ up(&dscc4_sem);
+}
+#else
+#define dscc4_pci_reset(pdev,ioaddr) do {} while (0)
+#endif /* CONFIG_DSCC4_PCI_RST */
+
static int dscc4_open(struct net_device *dev)
{
struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
@@ -949,12 +1026,29 @@
ppriv = dpriv->pci_priv;
- if ((ret = dscc4_init_ring(dev)))
- goto err_out;
+ /*
+ * Due to various bugs, there is no way to reliably reset a
+ * specific port (manufacturer's dependant special PCI #RST wiring
+ * apart: it affects all ports). Thus the device goes in the best
+ * silent mode possible at dscc4_close() time and simply claims to
+ * be up if it's opened again. It still isn't possible to change
+ * the HDLC configuration without rebooting but at least the ports
+ * can be up/down ifconfig'ed without killing the host.
+ */
+ if (dpriv->flags & FakeReset) {
+ dpriv->flags &= ~FakeReset;
+ scc_patchl(0, PowerUp, dpriv, dev, CCR0);
+ scc_patchl(0, 0x00050000, dpriv, dev, CCR2);
+ scc_writel(EventsMask, dpriv, dev, IMR);
+ printk(KERN_INFO "%s: up again.\n", dev->name);
+ goto done;
+ }
/* IDT+IDR during XPR */
dpriv->flags = NeedIDR | NeedIDT;
+ scc_patchl(0, PowerUp | Vis, dpriv, dev, CCR0);
+
/*
* The following is a bit paranoid...
*
@@ -965,15 +1059,17 @@
if (scc_readl_star(dpriv, dev) & SccBusy) {
printk(KERN_ERR "%s busy. Try later\n", dev->name);
ret = -EAGAIN;
- goto err_free_ring;
+ goto err_out;
} else
printk(KERN_INFO "%s: available. Good\n", dev->name);
+ scc_writel(EventsMask, dpriv, dev, IMR);
+
/* Posted write is flushed in the wait_ack loop */
scc_writel(TxSccRes | RxSccRes, dpriv, dev, CMDR);
if ((ret = dscc4_wait_ack_cec(dpriv, dev, "Cec")) < 0)
- goto err_free_ring;
+ goto err_disable_scc_events;
/*
* I would expect XPR near CE completion (before ? after ?).
@@ -984,12 +1080,13 @@
*/
if ((ret = dscc4_xpr_ack(dpriv)) < 0) {
printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR");
- goto err_free_ring;
+ goto err_disable_scc_events;
}
if (debug > 2)
dscc4_tx_print(dev, dpriv, "Open");
+done:
netif_start_queue(dev);
init_timer(&dpriv->timer);
@@ -1001,8 +1098,9 @@
return 0;
-err_free_ring:
- dscc4_release_ring(dpriv);
+err_disable_scc_events:
+ scc_writel(0xffffffff, dpriv, dev, IMR);
+ scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
err_out:
hdlc_close(hdlc);
MOD_DEC_USE_COUNT;
@@ -1027,7 +1125,7 @@
next = dpriv->tx_current%TX_RING_SIZE;
dpriv->tx_skbuff[next] = skb;
tx_fd = dpriv->tx_fd + next;
- tx_fd->state = FrameEnd | TO_STATE(skb->len);
+ tx_fd->state = FrameEnd | TO_STATE_TX(skb->len);
tx_fd->data = pci_map_single(ppriv->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
tx_fd->complete = 0x00000000;
@@ -1058,19 +1156,17 @@
{
struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
hdlc_device *hdlc = dev_to_hdlc(dev);
- unsigned long flags;
del_timer_sync(&dpriv->timer);
netif_stop_queue(dev);
- spin_lock_irqsave(&dpriv->pci_priv->lock, flags);
- dscc4_rx_reset(dpriv, dev);
- spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags);
+ scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
+ scc_patchl(0x00050000, 0, dpriv, dev, CCR2);
+ scc_writel(0xffffffff, dpriv, dev, IMR);
- dscc4_tx_reset(dpriv, dev);
+ dpriv->flags |= FakeReset;
hdlc_close(hdlc);
- dscc4_release_ring(dpriv);
MOD_DEC_USE_COUNT;
return 0;
@@ -1080,13 +1176,56 @@
{
int ret = 0;
-#ifdef CONFIG_DSCC4_CLOCK_ON_TWO_PORTS_ONLY
+#ifdef CONFIG_DSCC4_PCISYNC
if (port >= 2)
ret = -1;
#endif
return ret;
}
+/*
+ * DS1 p.137: "There are a total of 13 different clocking modes..."
+ * ^^
+ * Design choices:
+ * - by default, assume a clock is provided on pin RxClk/TxClk (clock mode 0a).
+ * Clock mode 3b _should_ work but the testing seems to make this point
+ * dubious (DIY testing requires setting CCR0 at 0x00000033).
+ * This is supposed to provide least surprise "DTE like" behavior.
+ * - if line rate is specified, clocks are assumed to be locally generated.
+ * A quartz must be available (on pin XTAL1). Modes 6b/7b are used. Choosing
+ * between these it automagically done according on the required frequency
+ * scaling. Of course some rounding may take place.
+ * - no high speed mode (40Mb/s). May be trivial to do but I don't have an
+ * appropriate external clocking device for testing.
+ * - no time-slot/clock mode 5: shameless lazyness.
+ *
+ * The clock signals wiring can be (is ?) manufacturer dependant. Good luck.
+ *
+ * BIG FAT WARNING: if the device isn't provided enough clocking signal, it
+ * won't pass the init sequence. For example, straight back-to-back DTE without
+ * external clock will fail when dscc4_open() (<- 'ifconfig hdlcx xxx') is
+ * called.
+ *
+ * Typos lurk in datasheet (missing divier in clock mode 7a figure 51 p.153
+ * DS0 for example)
+ *
+ * Clock mode related bits of CCR0:
+ * +------------ TOE: output TxClk (0b/2b/3a/3b/6b/7a/7b only)
+ * | +---------- SSEL: sub-mode select 0 -> a, 1 -> b
+ * | | +-------- High Speed: say 0
+ * | | | +-+-+-- Clock Mode: 0..7
+ * | | | | | |
+ * -+-+-+-+-+-+-+-+
+ * x|x|5|4|3|2|1|0| lower bits
+ *
+ * Division factor of BRR: k = (N+1)x2^M (total divider = 16xk in mode 6b)
+ * +-+-+-+------------------ M (0..15)
+ * | | | | +-+-+-+-+-+-- N (0..63)
+ * 0 0 0 0 | | | | 0 0 | | | | | |
+ * ...-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * f|e|d|c|b|a|9|8|7|6|5|4|3|2|1|0| lower bits
+ *
+ */
static int dscc4_set_clock(struct net_device *dev, u32 *bps, u32 *state)
{
struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
@@ -1123,13 +1262,13 @@
}
brr = (m << 8) | n;
divider = n << m;
- if (!(*state & 0x00000001)) /* Clock mode 6b */
+ if (!(*state & 0x00000001)) /* ?b mode mask => clock mode 6b */
divider <<= 4;
*bps = xtal / divider;
} else {
/*
* External clock - DTE
- * "state" already reflects Clock mode 0a.
+ * "state" already reflects Clock mode 0a (CCR0 = 0xzzzzzz00).
* Nothing more to be done
*/
brr = 0;
@@ -1168,6 +1307,11 @@
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ if (dpriv->flags & FakeReset) {
+ printk(KERN_INFO "%s: please reset the device"
+ " before this command\n", dev->name);
+ return -EPERM;
+ }
if (copy_from_user(&dpriv->settings, line, size))
return -EFAULT;
ret = dscc4_set_iface(dpriv, dev);
@@ -1221,12 +1365,12 @@
if (bps) { /* DCE */
printk(KERN_DEBUG "%s: generated RxClk (DCE)\n", dev->name);
if (settings->clock_rate != bps) {
- settings->clock_rate = bps;
printk(KERN_DEBUG "%s: clock adjusted (%08d -> %08d)\n",
- dev->name, dpriv->settings.clock_rate, bps);
+ dev->name, settings->clock_rate, bps);
+ settings->clock_rate = bps;
}
} else { /* DTE */
- state = 0x80001000;
+ state |= PowerUp | Vis;
printk(KERN_DEBUG "%s: external RxClk (DTE)\n", dev->name);
}
scc_writel(state, dpriv, dev, CCR0);
@@ -1332,6 +1476,8 @@
state = readl(ioaddr + GSTAR);
if (!state)
goto out;
+ if (debug > 3)
+ printk(KERN_DEBUG "%s: GSTAR = 0x%08x\n", DRV_NAME, state);
writel(state, ioaddr + GSTAR);
if (state & Arf) {
@@ -1377,6 +1523,9 @@
cur = dpriv->iqtx_current%IRQ_RING_SIZE;
state = dpriv->iqtx[cur];
if (!state) {
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Tx ISR = 0x%08x\n", dev->name,
+ state);
if ((debug > 1) && (loop > 1))
printk(KERN_DEBUG "%s: Tx irq loop=%d\n", dev->name, loop);
if (loop && netif_queue_stopped(dev))
@@ -1431,7 +1580,7 @@
* random freeze induced by null sized tx frames.
*/
tx_fd->data = tx_fd->next;
- tx_fd->state = FrameEnd | TO_STATE(2*DUMMY_SKB_SIZE);
+ tx_fd->state = FrameEnd | TO_STATE_TX(2*DUMMY_SKB_SIZE);
tx_fd->complete = 0x00000000;
tx_fd->jiffies = 0;
@@ -1463,9 +1612,19 @@
}
if (state & Xpr) {
u32 scc_addr, ring;
+ int i;
+
+ /*
+ * - the busy condition happens (sometimes);
+ * - it doesn't seem to make the handler unreliable.
+ */
+ for (i = 1; i; i <<= 1) {
+ if (!(scc_readl_star(dpriv, dev) & SccBusy))
+ break;
+ }
+ if (!i)
+ printk(KERN_INFO "%s busy in irq\n", dev->name);
- if (scc_readl_star(dpriv, dev) & SccBusy)
- printk(KERN_ERR "%s busy. Fatal\n", dev->name);
scc_addr = dev->base_addr + 0x0c*dpriv->dev_id;
/* Keep this order: IDT before IDR */
if (dpriv->flags & NeedIDT) {
@@ -1500,7 +1659,8 @@
goto try;
}
if (state & Cd) {
- printk(KERN_INFO "%s: CD transition\n", dev->name);
+ if (debug > 0)
+ printk(KERN_INFO "%s: CD transition\n", dev->name);
if (!(state &= ~Cd)) /* DEBUG */
goto try;
}
@@ -1542,6 +1702,9 @@
if (!(state & SccEvt)){
struct RxFD *rx_fd;
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Rx ISR = 0x%08x\n", dev->name,
+ state);
state &= 0x00ffffff;
if (state & Err) { /* Hold or reset */
printk(KERN_DEBUG "%s: Rx ERR\n", dev->name);
@@ -1718,7 +1881,7 @@
skb->len = DUMMY_SKB_SIZE;
memcpy(skb->data, version, strlen(version)%DUMMY_SKB_SIZE);
- tx_fd->state = FrameEnd | TO_STATE(DUMMY_SKB_SIZE);
+ tx_fd->state = FrameEnd | TO_STATE_TX(DUMMY_SKB_SIZE);
tx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data,
DUMMY_SKB_SIZE, PCI_DMA_TODEVICE);
dpriv->tx_skbuff[last] = skb;
@@ -1749,7 +1912,7 @@
dpriv->tx_dirty = 0xffffffff;
i = dpriv->tx_current = 0;
do {
- tx_fd->state = FrameEnd | TO_STATE(2*DUMMY_SKB_SIZE);
+ tx_fd->state = FrameEnd | TO_STATE_TX(2*DUMMY_SKB_SIZE);
tx_fd->complete = 0x00000000;
/* FIXME: NULL should be ok - to be tried */
tx_fd->data = dpriv->tx_fd_dma;
@@ -1757,7 +1920,7 @@
(++i%TX_RING_SIZE)*sizeof(*tx_fd));
} while (i < TX_RING_SIZE);
- if (dscc4_init_dummy_skb(dpriv) < 0)
+ if (dscc4_init_dummy_skb(dpriv) == NULL)
goto err_free_dma_tx;
memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE);
@@ -1767,7 +1930,7 @@
rx_fd->state1 = HiDesc;
rx_fd->state2 = 0x00000000;
rx_fd->end = 0xbabeface;
- rx_fd->state1 |= TO_STATE(RX_MAX(HDLC_MAX_MRU));
+ rx_fd->state1 |= TO_STATE_RX(HDLC_MAX_MRU);
// FIXME: return value verifiee mais traitement suspect
if (try_get_rx_skb(dpriv, dev) >= 0)
dpriv->rx_dirty++;
@@ -1785,7 +1948,7 @@
return -ENOMEM;
}
-static void __exit dscc4_remove_one(struct pci_dev *pdev)
+static void __devexit dscc4_remove_one(struct pci_dev *pdev)
{
struct dscc4_pci_priv *ppriv;
struct dscc4_dev_priv *root;
@@ -1796,12 +1959,16 @@
root = ppriv->root;
ioaddr = hdlc_to_dev(&root->hdlc)->base_addr;
+
+ dscc4_pci_reset(pdev, ioaddr);
+
free_irq(pdev->irq, root);
pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), ppriv->iqcfg,
ppriv->iqcfg_dma);
for (i = 0; i < dev_per_card; i++) {
struct dscc4_dev_priv *dpriv = root + i;
+ dscc4_release_ring(dpriv);
pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32),
dpriv->iqrx, dpriv->iqrx_dma);
pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32),
@@ -1843,6 +2010,7 @@
return 0;
}
+#ifndef MODULE
static int __init dscc4_setup(char *str)
{
int *args[] = { &debug, &quartz, NULL }, **p = args;
@@ -1853,8 +2021,9 @@
}
__setup("dscc4.setup=", dscc4_setup);
+#endif /* MODULE */
-static struct pci_device_id dscc4_pci_tbl[] __devinitdata = {
+static struct pci_device_id dscc4_pci_tbl[] = {
{ PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0,}
@@ -1865,7 +2034,7 @@
.name = DRV_NAME,
.id_table = dscc4_pci_tbl,
.probe = dscc4_init_one,
- .remove = dscc4_remove_one,
+ .remove = __devexit_p(dscc4_remove_one),
};
static int __init dscc4_init_module(void)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)