1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/apps/public/linux-atm/atm.patch
2024-07-22 01:58:46 -03:00

1127 lines
36 KiB
Diff
Executable File

--- ref/drivers/atm/ambassador.c Thu Jul 6 19:11:52 2000
+++ work/drivers/atm/ambassador.c Thu Jul 6 18:38:29 2000
@@ -373,15 +373,15 @@
static inline void dump_registers (const amb_dev * dev) {
#ifdef DEBUG_AMBASSADOR
if (debug & DBG_REGS) {
- u32 * i;
+ size_t i;
PRINTD (DBG_REGS, "reading PLX control: ");
- for (i = (u32 *) 0x00; i < (u32 *) 0x30; ++i)
+ for (i = 0x00; i < 0x30; i += sizeof(u32))
rd_mem (dev, i);
PRINTD (DBG_REGS, "reading mailboxes: ");
- for (i = (u32 *) 0x40; i < (u32 *) 0x60; ++i)
+ for (i = 0x40; i < 0x60; i += sizeof(u32))
rd_mem (dev, i);
PRINTD (DBG_REGS, "reading doorb irqev irqen reset:");
- for (i = (u32 *) 0x60; i < (u32 *) 0x70; ++i)
+ for (i = 0x60; i < 0x70; i += sizeof(u32))
rd_mem (dev, i);
}
#else
--- ref/drivers/atm/eni.c Thu Jul 6 19:11:52 2000
+++ work/drivers/atm/eni.c Thu Jul 6 18:38:51 2000
@@ -1187,14 +1187,12 @@
if (tx->send)
while ((skb = skb_dequeue(&tx->backlog))) {
res = do_tx(skb);
- if (res == enq_ok) atomic_dec(&tx->backlog_len);
- else {
- DPRINTK("re-queuing TX PDU\n");
- skb_queue_head(&tx->backlog,skb);
+ if (res == enq_ok) continue;
+ DPRINTK("re-queuing TX PDU\n");
+ skb_queue_head(&tx->backlog,skb);
requeued++;
- if (res == enq_jam) return;
- else break;
- }
+ if (res == enq_jam) return;
+ break;
}
}
}
@@ -1326,7 +1324,6 @@
tx->send = mem;
tx->words = size >> 2;
skb_queue_head_init(&tx->backlog);
- atomic_set(&tx->backlog_len,0);
for (order = 0; size > (1 << (order+10)); order++);
eni_out((order << MID_SIZE_SHIFT) |
((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
@@ -2064,6 +2061,8 @@
static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
{
+ enum enq_res res;
+
DPRINTK(">eni_send\n");
if (!ENI_VCC(vcc)->tx) {
if (vcc->pop) vcc->pop(vcc,skb);
@@ -2085,8 +2084,11 @@
}
submitted++;
ATM_SKB(skb)->vcc = vcc;
+ tasklet_disable(&ENI_DEV(vcc->dev)->task);
+ res = do_tx(skb);
+ tasklet_enable(&ENI_DEV(vcc->dev)->task);
+ if (res == enq_ok) return 0;
skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
- atomic_inc(&ENI_VCC(vcc)->tx->backlog_len);
backlogged++;
tasklet_schedule(&ENI_DEV(vcc->dev)->task);
return 0;
@@ -2186,8 +2188,8 @@
tx == eni_dev->ubr ? " (UBR)" : "");
}
if (--left) continue;
- return sprintf(page,"%10sbacklog %d bytes\n","",
- atomic_read(&tx->backlog_len));
+ return sprintf(page,"%10sbacklog %u packets\n","",
+ skb_queue_len(&tx->backlog));
}
for (vcc = dev->vccs; vcc; vcc = vcc->next) {
struct eni_vcc *eni_vcc = ENI_VCC(vcc);
--- ref/drivers/atm/eni.h Fri Apr 14 18:37:10 2000
+++ work/drivers/atm/eni.h Thu Jul 6 18:45:07 2000
@@ -47,7 +47,6 @@
int reserved; /* reserved peak cell rate */
int shaping; /* shaped peak cell rate */
struct sk_buff_head backlog; /* queue of waiting TX buffers */
- atomic_t backlog_len; /* length of backlog in bytes */
};
struct eni_vcc {
--- ref/drivers/atm/fore200e.c Thu Jul 6 19:12:43 2000
+++ work/drivers/atm/fore200e.c Thu Jul 6 18:38:29 2000
@@ -2599,9 +2599,7 @@
printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n");
-#if 0 /* XXX uncomment this to forbid module unloading */
MOD_INC_USE_COUNT;
-#endif
/* for each configured bus interface */
for (link = 0, bus = fore200e_bus; bus->model_name; bus++) {
@@ -2628,10 +2626,8 @@
}
}
-#if 0 /* XXX uncomment this to forbid module unloading */
if (link <= 0)
MOD_DEC_USE_COUNT;
-#endif
return link;
}
--- ref/drivers/atm/horizon.c Sat Apr 29 08:00:04 2000
+++ work/drivers/atm/horizon.c Thu Jul 6 18:38:29 2000
@@ -603,7 +603,8 @@
// note: rounding the rate down means rounding 'p' up
- const unsigned long br = test_bit (ultra, &dev->flags) ? BR_ULT : BR_HRZ;
+ const unsigned long br = test_bit (ultra, (hrz_flags *) &dev->flags) ?
+ BR_ULT : BR_HRZ;
u32 div = CR_MIND;
u32 pre;
--- ref/drivers/atm/idt77105.c Thu Jul 6 19:11:52 2000
+++ work/drivers/atm/idt77105.c Thu Jul 6 18:38:29 2000
@@ -48,10 +48,12 @@
static void idt77105_restart_timer_func(unsigned long);
-static struct timer_list stats_timer = { NULL, NULL, 0L, 0L,
- &idt77105_stats_timer_func };
-static struct timer_list restart_timer = { NULL, NULL, 0L, 0L,
- &idt77105_restart_timer_func };
+static struct timer_list stats_timer = {
+ function: &idt77105_stats_timer_func
+};
+static struct timer_list restart_timer = {
+ function: &idt77105_restart_timer_func
+};
static int start_timer = 1;
static struct idt77105_priv *idt77105_all = NULL;
--- ref/drivers/atm/iphase.c Thu Jul 6 19:11:52 2000
+++ work/drivers/atm/iphase.c Thu Jul 6 18:38:29 2000
@@ -2303,7 +2303,7 @@
dev->number,error);
return -EINVAL;
}
- IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%x,irq=%d\n",
+ IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n",
dev->number, revision, real_base, iadev->irq);)
/* find mapping size of board */
@@ -2342,7 +2342,7 @@
dev->number);
return error;
}
- IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=0x%x,irq=%d\n",
+ IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=0x%lx,irq=%d\n",
dev->number, revision, base, iadev->irq);)
/* filling the iphase dev structure */
--- ref/drivers/atm/nicstar.c Thu Jul 6 19:11:52 2000
+++ work/drivers/atm/nicstar.c Thu Jul 6 18:38:29 2000
@@ -21,6 +21,18 @@
******************************************************************************/
+/**** IMPORTANT INFORMATION ***************************************************
+ *
+ * There are currently three types of spinlocks:
+ *
+ * 1 - Per card interrupt spinlock (to protect structures and such)
+ * 2 - Per SCQ scq spinlock
+ * 3 - Per card resource spinlock (to access registers, etc.)
+ *
+ * These must NEVER be grabbed in reverse order.
+ *
+ ******************************************************************************/
+
/* Header files ***************************************************************/
#include <linux/module.h>
@@ -115,6 +127,85 @@
#define ATM_SKB(s) (&(s)->atm)
#endif
+ /* Spinlock debugging stuff */
+#ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */
+#define ns_grab_int_lock(card,flags) \
+ do { \
+ unsigned long nsdsf, nsdsf2; \
+ local_irq_save(flags); \
+ save_flags(nsdsf); cli();\
+ if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+ (flags)&(1<<9)?"en":"dis"); \
+ if (spin_is_locked(&(card)->int_lock) && \
+ (card)->cpu_int == smp_processor_id()) { \
+ printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \
+ __LINE__, smp_processor_id(), (card)->has_int_lock, \
+ (card)->cpu_int); \
+ printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+ } \
+ if (spin_is_locked(&(card)->res_lock) && \
+ (card)->cpu_res == smp_processor_id()) { \
+ printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \
+ __LINE__, smp_processor_id(), (card)->has_res_lock, \
+ (card)->cpu_res); \
+ printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+ } \
+ spin_lock_irq(&(card)->int_lock); \
+ (card)->has_int_lock = __LINE__; \
+ (card)->cpu_int = smp_processor_id(); \
+ restore_flags(nsdsf); } while (0)
+#define ns_grab_res_lock(card,flags) \
+ do { \
+ unsigned long nsdsf, nsdsf2; \
+ local_irq_save(flags); \
+ save_flags(nsdsf); cli();\
+ if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+ (flags)&(1<<9)?"en":"dis"); \
+ if (spin_is_locked(&(card)->res_lock) && \
+ (card)->cpu_res == smp_processor_id()) { \
+ printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \
+ __LINE__, smp_processor_id(), (card)->has_res_lock, \
+ (card)->cpu_res); \
+ printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+ } \
+ spin_lock_irq(&(card)->res_lock); \
+ (card)->has_res_lock = __LINE__; \
+ (card)->cpu_res = smp_processor_id(); \
+ restore_flags(nsdsf); } while (0)
+#define ns_grab_scq_lock(card,scq,flags) \
+ do { \
+ unsigned long nsdsf, nsdsf2; \
+ local_irq_save(flags); \
+ save_flags(nsdsf); cli();\
+ if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+ (flags)&(1<<9)?"en":"dis"); \
+ if (spin_is_locked(&(scq)->lock) && \
+ (scq)->cpu_lock == smp_processor_id()) { \
+ printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \
+ __LINE__, smp_processor_id(), (scq)->has_lock, \
+ (scq)->cpu_lock); \
+ printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+ } \
+ if (spin_is_locked(&(card)->res_lock) && \
+ (card)->cpu_res == smp_processor_id()) { \
+ printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \
+ __LINE__, smp_processor_id(), (card)->has_res_lock, \
+ (card)->cpu_res); \
+ printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+ } \
+ spin_lock_irq(&(scq)->lock); \
+ (scq)->has_lock = __LINE__; \
+ (scq)->cpu_lock = smp_processor_id(); \
+ restore_flags(nsdsf); } while (0)
+#else /* !NS_DEBUG_SPINLOCKS */
+#define ns_grab_int_lock(card,flags) \
+ spin_lock_irqsave(&(card)->int_lock,(flags))
+#define ns_grab_res_lock(card,flags) \
+ spin_lock_irqsave(&(card)->res_lock,(flags))
+#define ns_grab_scq_lock(card,scq,flags) \
+ spin_lock_irqsave(&(scq)->lock,flags)
+#endif /* NS_DEBUG_SPINLOCKS */
+
/* Version definition *********************************************************/
/*
@@ -406,12 +497,12 @@
sram_address <<= 2;
sram_address &= 0x0007FFFC; /* address must be dword aligned */
sram_address |= 0x50000000; /* SRAM read command */
- save_flags(flags); cli();
+ ns_grab_res_lock(card, flags);
while (CMD_BUSY(card));
writel(sram_address, card->membase + CMD);
while (CMD_BUSY(card));
data = readl(card->membase + DR0);
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->res_lock, flags);
return data;
}
@@ -424,7 +515,7 @@
count--; /* count range now is 0..3 instead of 1..4 */
c = count;
c <<= 2; /* to use increments of 4 */
- save_flags(flags); cli();
+ ns_grab_res_lock(card, flags);
while (CMD_BUSY(card));
for (i = 0; i <= c; i += 4)
writel(*(value++), card->membase + i);
@@ -434,14 +525,14 @@
sram_address &= 0x0007FFFC;
sram_address |= (0x40000000 | count);
writel(sram_address, card->membase + CMD);
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->res_lock, flags);
}
static int ns_init_card(int i, struct pci_dev *pcidev)
{
int j;
- struct ns_dev *card;
+ struct ns_dev *card = NULL;
unsigned short pci_command;
unsigned char pci_latency;
unsigned error;
@@ -468,6 +559,8 @@
return error;
}
cards[i] = card;
+ spin_lock_init(&card->int_lock);
+ spin_lock_init(&card->res_lock);
card->index = i;
card->atmdev = NULL;
@@ -853,9 +946,6 @@
card->iovpool.count++;
}
-
- card->in_handler = 0;
- card->in_poll = 0;
card->intcnt = 0;
/* Configure NICStAR */
@@ -1025,6 +1115,7 @@
scq->tbd_count = 0;
init_waitqueue_head(&scq->scqfull_waitq);
scq->full = 0;
+ spin_lock_init(&scq->lock);
for (i = 0; i < scq->num_entries; i++)
scq->skb[i] = NULL;
@@ -1161,7 +1252,7 @@
card->lbfqc += 2;
}
- save_flags(flags); cli();
+ ns_grab_res_lock(card, flags);
while (CMD_BUSY(card));
writel(addr2, card->membase + DR3);
@@ -1170,7 +1261,7 @@
writel(handle1, card->membase + DR0);
writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD);
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->res_lock, flags);
XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index,
(type == BUF_SM ? "small" : "large"), addr1, addr2);
@@ -1193,6 +1284,7 @@
u32 stat_r;
ns_dev *card;
struct atm_dev *dev;
+ unsigned long flags;
card = (ns_dev *) dev_id;
dev = card->atmdev;
@@ -1200,19 +1292,7 @@
PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
- if (card->in_handler)
- {
- printk("nicstar%d: Re-entering ns_irq_handler()???\n", card->index);
- return;
- }
- card->in_handler = 1;
- if (card->in_poll)
- {
- card->in_handler = 0;
- printk("nicstar%d: Called irq handler while in ns_poll()!?\n",
- card->index);
- return;
- }
+ ns_grab_int_lock(card, flags);
stat_r = readl(card->membase + STAT);
@@ -1377,7 +1457,7 @@
process_rsq(card);
}
- card->in_handler = 0;
+ spin_unlock_irqrestore(&card->int_lock, flags);
PRINTK("nicstar%d: end of interrupt service\n", card->index);
}
@@ -1595,10 +1675,10 @@
unsigned long flags;
addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE;
- save_flags(flags); cli();
+ ns_grab_res_lock(card, flags);
while(CMD_BUSY(card));
writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD);
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->res_lock, flags);
vc->rx = 0;
if (vc->rx_iov != NULL)
@@ -1617,9 +1697,9 @@
ATM_SKB(iovb)->iovcnt);
ATM_SKB(iovb)->iovcnt = 0;
ATM_SKB(iovb)->vcc = NULL;
- save_flags(flags); cli();
+ ns_grab_int_lock(card, flags);
recycle_iov_buf(card, iovb);
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->int_lock, flags);
vc->rx_iov = NULL;
}
}
@@ -1639,7 +1719,7 @@
for (;;)
{
- save_flags(flags); cli();
+ ns_grab_scq_lock(card, scq, flags);
scqep = scq->next;
if (scqep == scq->base)
scqep = scq->last;
@@ -1647,7 +1727,7 @@
scqep--;
if (scqep == scq->tail)
{
- restore_flags(flags);
+ spin_unlock_irqrestore(&scq->lock, flags);
break;
}
/* If the last entry is not a TSR, place one in the SCQ in order to
@@ -1675,8 +1755,8 @@
data = (u32) virt_to_bus(scq->next);
ns_write_sram(card, scq->scd, &data, 1);
}
+ spin_unlock_irqrestore(&scq->lock, flags);
schedule();
- restore_flags(flags);
}
/* Free all TST entries */
@@ -1884,19 +1964,22 @@
u32 data;
int index;
- if (scq->tail == scq->next)
+ ns_grab_scq_lock(card, scq, flags);
+ while (scq->tail == scq->next)
{
if (in_interrupt()) {
+ spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Error pushing TBD.\n", card->index);
return 1;
}
- save_flags(flags); cli();
scq->full = 1;
+ spin_unlock_irqrestore(&scq->lock, flags);
interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT);
- restore_flags(flags);
+ ns_grab_scq_lock(card, scq, flags);
if (scq->full) {
+ spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Timeout pushing TBD.\n", card->index);
return 1;
}
@@ -1926,19 +2009,23 @@
if (vc->tbd_count >= MAX_TBD_PER_VC || scq->tbd_count >= MAX_TBD_PER_SCQ)
{
- if (scq->tail == scq->next)
+ int has_run = 0;
+
+ while (scq->tail == scq->next)
{
if (in_interrupt()) {
data = (u32) virt_to_bus(scq->next);
ns_write_sram(card, scq->scd, &data, 1);
+ spin_unlock_irqrestore(&scq->lock, flags);
printk("nicstar%d: Error pushing TSR.\n", card->index);
return 0;
}
- save_flags(flags); cli();
scq->full = 1;
+ if (has_run++) break;
+ spin_unlock_irqrestore(&scq->lock, flags);
interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT);
- restore_flags(flags);
+ ns_grab_scq_lock(card, scq, flags);
}
if (!scq->full)
@@ -1970,10 +2057,11 @@
else
PRINTK("nicstar%d: Timeout pushing TSR.\n", card->index);
}
-
data = (u32) virt_to_bus(scq->next);
ns_write_sram(card, scq->scd, &data, 1);
+ spin_unlock_irqrestore(&scq->lock, flags);
+
return 0;
}
@@ -2064,6 +2152,7 @@
struct atm_vcc *vcc;
struct sk_buff *skb;
int i;
+ unsigned long flags;
XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n",
card->index, (u32) scq, pos);
@@ -2073,6 +2162,7 @@
return;
}
+ ns_grab_scq_lock(card, scq, flags);
i = (int) (scq->tail - scq->base);
if (++i == scq->num_entries)
i = 0;
@@ -2084,16 +2174,18 @@
if (skb != NULL)
{
vcc = ATM_SKB(skb)->vcc;
- if (vcc->pop != NULL)
+ if (vcc->pop != NULL) {
vcc->pop(vcc, skb);
- else
- dev_kfree_skb_any(skb);
+ } else {
+ dev_kfree_skb_irq(skb);
+ }
scq->skb[i] = NULL;
}
if (++i == scq->num_entries)
i = 0;
}
scq->tail = scq->base + pos;
+ spin_unlock_irqrestore(&scq->lock, flags);
}
@@ -2890,10 +2982,10 @@
{
struct sk_buff *hb;
- save_flags(flags); cli();
+ ns_grab_int_lock(card, flags);
hb = skb_dequeue(&card->hbpool.queue);
card->hbpool.count--;
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->int_lock, flags);
if (hb == NULL)
printk("nicstar%d: huge buffer count inconsistent.\n",
card->index);
@@ -2908,10 +3000,10 @@
hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
if (hb == NULL)
return -ENOMEM;
- save_flags(flags); cli();
+ ns_grab_int_lock(card, flags);
skb_queue_tail(&card->hbpool.queue, hb);
card->hbpool.count++;
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->int_lock, flags);
}
break;
@@ -2920,10 +3012,10 @@
{
struct sk_buff *iovb;
- save_flags(flags); cli();
+ ns_grab_int_lock(card, flags);
iovb = skb_dequeue(&card->iovpool.queue);
card->iovpool.count--;
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->int_lock, flags);
if (iovb == NULL)
printk("nicstar%d: iovec buffer count inconsistent.\n",
card->index);
@@ -2938,10 +3030,10 @@
iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);
if (iovb == NULL)
return -ENOMEM;
- save_flags(flags); cli();
+ ns_grab_int_lock(card, flags);
skb_queue_tail(&card->iovpool.queue, iovb);
card->iovpool.count++;
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->int_lock, flags);
}
break;
@@ -2986,22 +3078,11 @@
for (i = 0; i < num_cards; i++)
{
card = cards[i];
- save_flags(flags); cli();
- if (card->in_poll)
- {
- printk("nicstar: Re-entering ns_poll()???\n");
- restore_flags(flags);
- continue;
- }
- card->in_poll = 1;
- if (card->in_handler)
- {
- card->in_poll = 0;
- printk("nicstar%d: ns_poll called while in interrupt handler!?\n",
- card->index);
- restore_flags(flags);
+ if (spin_is_locked(&card->int_lock)) {
+ /* Probably it isn't worth spinning */
continue;
}
+ ns_grab_int_lock(card, flags);
stat_w = 0;
stat_r = readl(card->membase + STAT);
@@ -3014,8 +3095,7 @@
process_rsq(card);
writel(stat_w, card->membase + STAT);
- card->in_poll = 0;
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->int_lock, flags);
}
mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD);
PRINTK("nicstar: Leaving ns_poll().\n");
@@ -3069,12 +3149,12 @@
unsigned long flags;
card = dev->dev_data;
- save_flags(flags); cli();
+ ns_grab_res_lock(card, flags);
while(CMD_BUSY(card));
writel((unsigned long) value, card->membase + DR0);
writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF),
card->membase + CMD);
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->res_lock, flags);
}
@@ -3086,12 +3166,12 @@
unsigned long data;
card = dev->dev_data;
- save_flags(flags); cli();
+ ns_grab_res_lock(card, flags);
while(CMD_BUSY(card));
writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF),
card->membase + CMD);
while(CMD_BUSY(card));
data = readl(card->membase + DR0) & 0x000000FF;
- restore_flags(flags);
+ spin_unlock_irqrestore(&card->res_lock, flags);
return (unsigned char) data;
}
--- ref/drivers/atm/nicstar.h Wed Mar 22 08:38:26 2000
+++ work/drivers/atm/nicstar.h Thu Jul 6 18:45:17 2000
@@ -28,6 +28,8 @@
/* Options ********************************************************************/
+#undef NS_DEBUG_SPINLOCKS
+
#define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards
controlled by the device driver. Must
be <= 5 */
@@ -705,6 +707,11 @@
int tbd_count; /* Only meaningful on variable rate */
wait_queue_head_t scqfull_waitq;
volatile char full; /* SCQ full indicator */
+ spinlock_t lock; /* SCQ spinlock */
+#ifdef NS_DEBUG_SPINLOCKS
+ volatile long has_lock;
+ volatile int cpu_lock;
+#endif /* NS_DEBUG_SPINLOCKS */
} scq_info;
@@ -779,8 +786,14 @@
struct sk_buff *rcbuf; /* Current raw cell buffer */
u32 rawch; /* Raw cell queue head */
unsigned intcnt; /* Interrupt counter */
- volatile int in_handler: 1;
- volatile int in_poll: 1;
+ spinlock_t int_lock; /* Interrupt lock */
+ spinlock_t res_lock; /* Card resource lock */
+#ifdef NS_DEBUG_SPINLOCKS
+ volatile long has_int_lock;
+ volatile int cpu_int;
+ volatile long has_res_lock;
+ volatile int cpu_res;
+#endif /* NS_DEBUG_SPINLOCKS */
} ns_dev;
--- ref/net/atm/Makefile Wed Mar 22 08:38:26 2000
+++ work/net/atm/Makefile Thu Jul 6 18:38:29 2000
@@ -25,7 +25,7 @@
NEED_IPCOM = ipcommon.o
endif
-O_OBJS += $(NEED_IPCOM)
+OX_OBJS += $(NEED_IPCOM)
ifeq ($(CONFIG_PROC_FS),y)
OX_OBJS += proc.o
--- ref/net/atm/clip.c Tue May 2 21:41:00 2000
+++ work/net/atm/clip.c Thu Jul 6 18:38:29 2000
@@ -274,14 +274,14 @@
static struct neigh_ops clip_neigh_ops = {
- AF_INET, /* family */
- clip_neigh_destroy, /* destructor */
- clip_neigh_solicit, /* solicit */
- clip_neigh_error, /* error_report */
- dev_queue_xmit, /* output */
- dev_queue_xmit, /* connected_output */
- dev_queue_xmit, /* hh_output */
- dev_queue_xmit /* queue_xmit */
+ family: AF_INET,
+ destructor: clip_neigh_destroy,
+ solicit: clip_neigh_solicit,
+ error_report: clip_neigh_error,
+ output: dev_queue_xmit,
+ connected_output: dev_queue_xmit,
+ hh_output: dev_queue_xmit,
+ queue_xmit: dev_queue_xmit,
};
@@ -384,6 +384,7 @@
if (!skb->dst) {
printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
dev_kfree_skb(skb);
+ clip_priv->stats.tx_dropped++;
return 0;
}
if (!skb->dst->neighbour) {
@@ -395,8 +396,10 @@
return 0;
}
#endif
-printk("clip_start_xmit: NO NEIGHBOUR !\n");
-return 0;
+ printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n");
+ dev_kfree_skb(skb);
+ clip_priv->stats.tx_dropped++;
+ return 0;
}
entry = NEIGH2ENTRY(skb->dst->neighbour);
if (!entry->vccs) {
@@ -440,7 +443,6 @@
entry->vccs->xoff = 0;
return 0;
}
- if (old) return 0;
spin_lock_irqsave(&clip_priv->xoff_lock,flags);
netif_stop_queue(dev); /* XOFF -> throttle immediately */
barrier();
@@ -482,6 +484,7 @@
clip_vcc->old_pop = vcc->pop;
vcc->push = clip_push;
vcc->pop = clip_pop;
+ skb_queue_head_init(&copy);
skb_migrate(&vcc->recvq,&copy);
/* re-process everything received between connection setup and MKIP */
while ((skb = skb_dequeue(&copy)))
@@ -622,7 +625,7 @@
DPRINTK("clip_device_event NETDEV_UP\n");
(void) to_atmarpd(act_up,PRIV(dev)->number,0);
break;
- case NETDEV_DOWN:
+ case NETDEV_GOING_DOWN:
DPRINTK("clip_device_event NETDEV_DOWN\n");
(void) to_atmarpd(act_down,PRIV(dev)->number,0);
break;
@@ -633,6 +636,7 @@
break;
case NETDEV_REBOOT:
case NETDEV_REGISTER:
+ case NETDEV_DOWN:
DPRINTK("clip_device_event %ld\n",event);
/* ignore */
break;
--- ref/net/atm/common.c Fri Apr 14 18:37:20 2000
+++ work/net/atm/common.c Thu Jul 6 18:38:29 2000
@@ -105,6 +105,7 @@
vcc->callback = NULL;
memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
+ vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
atomic_set(&vcc->tx_inuse,0);
atomic_set(&vcc->rx_inuse,0);
vcc->push = NULL;
@@ -116,6 +117,7 @@
init_waitqueue_head(&vcc->sleep);
skb_queue_head_init(&vcc->recvq);
skb_queue_head_init(&vcc->listenq);
+ sk->sleep = &vcc->sleep;
sock->sk = sk;
return 0;
}
@@ -409,6 +411,7 @@
return vcc->reply;
if (!test_bit(ATM_VF_READY,&vcc->flags)) return -EPIPE;
if (!size) return 0;
+ if (size < 0 || size > vcc->qos.txtp.max_sdu) return -EMSGSIZE;
/* verify_area is done by net/socket.c */
eff = (size+3) & ~3; /* align to word boundary */
add_wait_queue(&vcc->sleep,&wait);
@@ -750,8 +753,10 @@
}
-int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
+static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
{
+ int error;
+
/*
* Don't let the QoS change the already connected AAL type nor the
* traffic class.
@@ -760,6 +765,9 @@
qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
return -EINVAL;
+ error = adjust_tp(&qos->txtp,qos->aal);
+ if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
+ if (error) return error;
if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
if (vcc->family == AF_ATMPVC)
return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
--- ref/net/atm/common.h Fri Apr 14 18:37:20 2000
+++ work/net/atm/common.h Thu Jul 6 18:52:02 2000
@@ -26,7 +26,6 @@
int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci);
void atm_release_vcc_sk(struct sock *sk,int free_sk);
-int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
void atm_shutdown_dev(struct atm_dev *dev);
int atm_proc_init(void);
--- ref/net/atm/ipcommon.c Wed Mar 22 08:38:26 2000
+++ work/net/atm/ipcommon.c Thu Jul 6 18:38:29 2000
@@ -3,6 +3,7 @@
/* Written 1996-2000 by Werner Almesberger, EPFL LRC/ICA */
+#include <linux/module.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -31,7 +32,11 @@
/*
- * skb_migrate moves the list at FROM to TO, emptying FROM in the process.
+ * skb_migrate appends the list at "from" to "to", emptying "from" in the
+ * process. skb_migrate is atomic with respect to all other skb operations on
+ * "from" and "to". Note that it locks both lists at the same time, so beware
+ * of potential deadlocks.
+ *
* This function should live in skbuff.c or skbuff.h.
*/
@@ -40,18 +45,26 @@
{
struct sk_buff *skb;
unsigned long flags;
+ struct sk_buff *skb_from = (struct sk_buff *) from;
+ struct sk_buff *skb_to = (struct sk_buff *) to;
+ struct sk_buff *prev;
spin_lock_irqsave(&from->lock,flags);
- *to = *from;
- from->prev = (struct sk_buff *) from;
- from->next = (struct sk_buff *) from;
+ spin_lock(&to->lock);
+ prev = from->prev;
+ from->next->prev = to->prev;
+ prev->next = skb_to;
+ to->prev->next = from->next;
+ to->prev = from->prev;
+ for (skb = from->next; skb != skb_to; skb = skb->next)
+ skb->list = to;
+ to->qlen += from->qlen;
+ spin_unlock(&to->lock);
+ from->prev = skb_from;
+ from->next = skb_from;
from->qlen = 0;
spin_unlock_irqrestore(&from->lock,flags);
- spin_lock_init(&to->lock);
- for (skb = ((struct sk_buff *) to)->next;
- skb != (struct sk_buff *) from; skb = skb->next) skb->list = to;
- if (to->next == (struct sk_buff *) from)
- to->next = (struct sk_buff *) to;
- to->next->prev = (struct sk_buff *) to;
- to->prev->next = (struct sk_buff *) to;
}
+
+
+EXPORT_SYMBOL(skb_migrate);
--- ref/net/atm/ipcommon.h Wed Mar 22 08:38:26 2000
+++ work/net/atm/ipcommon.h Thu Jul 6 18:52:10 2000
@@ -16,8 +16,8 @@
extern struct net_device *clip_devs;
/*
- * Moves all skbs from "from" to "to". The operation is atomic for "from", but
- * not for "to". "to" may only be accessed after skb_migrate finishes.
+ * Appends all skbs from "from" to "to". The operation is atomic with respect
+ * to all other skb operations on "from" or "to".
*/
void skb_migrate(struct sk_buff_head *from,struct sk_buff_head *to);
--- ref/net/atm/lec.c Wed May 3 10:48:03 2000
+++ work/net/atm/lec.c Thu Jul 6 18:38:29 2000
@@ -332,23 +332,33 @@
lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
ATM_SKB(skb2)->vcc = send_vcc;
- atomic_add(skb2->truesize, &send_vcc->tx_inuse);
ATM_SKB(skb2)->iovcnt = 0;
ATM_SKB(skb2)->atm_options = send_vcc->atm_options;
DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name,
send_vcc->vpi, send_vcc->vci);
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += skb2->len;
- send_vcc->send(send_vcc, skb2);
+ if (atm_may_send(send_vcc, skb2->len)) {
+ atomic_add(skb2->truesize, &send_vcc->tx_inuse);
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += skb2->len;
+ send_vcc->send(send_vcc, skb2);
+ } else {
+ priv->stats.tx_dropped++;
+ dev_kfree_skb(skb2);
+ }
}
ATM_SKB(skb)->vcc = send_vcc;
- atomic_add(skb->truesize, &send_vcc->tx_inuse);
ATM_SKB(skb)->iovcnt = 0;
ATM_SKB(skb)->atm_options = send_vcc->atm_options;
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += skb->len;
- send_vcc->send(send_vcc, skb);
+ if (atm_may_send(send_vcc, skb->len)) {
+ atomic_add(skb->truesize, &send_vcc->tx_inuse);
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += skb->len;
+ send_vcc->send(send_vcc, skb);
+ } else {
+ priv->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ }
#if 0
/* Should we wait for card's device driver to notify us? */
--- ref/net/atm/mpc.c Fri Apr 14 18:43:49 2000
+++ work/net/atm/mpc.c Thu Jul 6 18:38:29 2000
@@ -239,7 +239,7 @@
while (qos != NULL) {
ip = (unsigned char *)&qos->ipaddr;
sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip));
- *len += sprintf(page + *len, "%%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
+ *len += sprintf(page + *len, "%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
NIPQUAD(ipaddr),
qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
--- ref/net/atm/proc.c Wed Mar 22 08:38:26 2000
+++ work/net/atm/proc.c Thu Jul 6 18:38:29 2000
@@ -104,7 +104,7 @@
strcpy(buf,addr->sas_addr.pub);
len = strlen(addr->sas_addr.pub);
buf += len;
- if (*addr->sas_addr.pub) {
+ if (*addr->sas_addr.prv) {
*buf++ = '+';
len++;
}
@@ -233,9 +233,10 @@
int i;
if (!vcc->dev)
- sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%6s" : "N/A@%p%2s",
+ sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%10s" : "N/A@%p%2s",
vcc,"");
- else sprintf(buf,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,vcc->vci);
+ else sprintf(buf,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
+ vcc->vci);
here = strchr(buf,0);
here += sprintf(here,"%-10s ",vcc_state(vcc));
here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub,
@@ -376,7 +377,7 @@
int left;
if (!pos)
- return sprintf(buf,"Itf VPI VCI State Remote\n");
+ return sprintf(buf,"Itf VPI VCI State Remote\n");
left = pos-1;
for (dev = atm_devs; dev; dev = dev->next)
for (vcc = dev->vccs; vcc; vcc = vcc->next)
--- ref/net/atm/signaling.c Wed Mar 22 08:38:26 2000
+++ work/net/atm/signaling.c Thu Jul 6 18:38:29 2000
@@ -158,9 +158,9 @@
}
-void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
+void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
- const struct sockaddr_atmsvc *svc)
+ const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply)
{
struct sk_buff *skb;
struct atmsvc_msg *msg;
@@ -173,18 +173,23 @@
msg->type = type;
*(struct atm_vcc **) &msg->vcc = vcc;
*(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
- msg->reply = 0; /* other ISP applications may use this field */
- if (vcc) {
- msg->qos = vcc->qos;
- msg->sap = vcc->sap;
- }
- if (!svc) msg->svc.sas_family = 0;
- else msg->svc = *svc;
+ msg->reply = reply;
+ if (qos) msg->qos = *qos;
+ if (vcc) msg->sap = vcc->sap;
+ if (svc) msg->svc = *svc;
if (vcc) msg->local = vcc->local;
- if (!pvc) memset(&msg->pvc,0,sizeof(msg->pvc));
- else msg->pvc = *pvc;
+ if (pvc) msg->pvc = *pvc;
sigd_put_skb(skb);
if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags);
+}
+
+
+void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
+ struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
+ const struct sockaddr_atmsvc *svc)
+{
+ sigd_enq2(vcc,type,listen_vcc,pvc,svc,vcc ? &vcc->qos : NULL,0);
+ /* other ISP applications may use "reply" */
}
--- ref/net/atm/signaling.h Wed Mar 22 08:38:26 2000
+++ work/net/atm/signaling.h Thu Jul 6 18:52:02 2000
@@ -17,6 +17,14 @@
extern struct atm_vcc *sigd; /* needed in svc_release */
+/*
+ * sigd_enq is a wrapper for sigd_enq2, covering the more common cases, and
+ * avoiding huge lists of null values.
+ */
+
+void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
+ struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
+ const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply);
void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
const struct sockaddr_atmsvc *svc);
--- ref/net/atm/svc.c Mon Apr 24 22:43:04 2000
+++ work/net/atm/svc.c Thu Jul 6 18:38:29 2000
@@ -77,8 +77,7 @@
as_indicate has been answered */
while ((skb = skb_dequeue(&vcc->listenq))) {
DPRINTK("LISTEN REL\n");
- sigd_enq(NULL,as_reject,vcc,NULL,NULL); /* @@@ should include
- the reason */
+ sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
dev_kfree_skb(skb);
}
clear_bit(ATM_VF_REGIS,&vcc->flags);
@@ -310,8 +309,8 @@
dev_kfree_skb(skb);
old_vcc->backlog_quota++;
if (error) {
- sigd_enq(NULL,as_reject,old_vcc,NULL,NULL);
- /* @@@ should include the reason */
+ sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
+ &old_vcc->qos,error);
return error == -EAGAIN ? -EBUSY : error;
}
/* wait should be short, so we ignore the non-blocking flag */
@@ -348,13 +347,9 @@
int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
{
DECLARE_WAITQUEUE(wait,current);
- struct atm_qos save_qos;
vcc->reply = WAITING;
- save_qos = vcc->qos; /* @@@ really gross hack ... */
- vcc->qos = *qos;
- sigd_enq(vcc,as_modify,NULL,NULL,&vcc->local);
- vcc->qos = save_qos;
+ sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
add_wait_queue(&vcc->sleep,&wait);
while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags)
&& sigd) {