2.1.38 Problems and some bugfixes

Alan Cox (alan@lxorguk.ukuu.org.uk)
Sun, 18 May 1997 22:58:15 +0100 (BST)


Well 2.1.38 is a big leap forward, not only does it compile but it boots
on my dual P90.

After an initial celebration of the login prompt I did a ctrl-alt-del
and it crashed 8(.

Anyway a bit of digging showed that it was killed by some of the parallelism
in the code now tickling a bug that goes back before 2.0 when dev_ifconf
is walking the device tree and the kernel downs a device. At this point
dev_ifconf takes a trip down a defunct linked list and goes kaboom. This
part of the diff should be applied to 2.0.pre31 as well I think.

Performance appears to be way down on I/O bound tasks such as patch
over NFS and it crashes at random with "Wrong blocksize on device 03:02"
continually scrolling when you diff two large source trees.

Anyway these diffs fix that bug and add some of the smaller queued items:

1. Recognition of the 450GXv2 chipset and the BT848 based TV cards
in the PCI tables
2. Some small bugs in the IBM token ring driver
3. Missing Documentation items for the ADE16 sound stuff
4. FDDI go faster stripes.
5. Multiple dummy devices load again.

Since 2.1.38 is at least sufficiently stable for me to work on will people
please resend any pending network device driver patches they have as diffs
against 2.1.38. I will be picking through the backlog of 2.1.3x diffs I
have queued but it makes things a lot simpler if people can provide unified
diffs against 2.1.38, and also means I won't miss as many. I don't want
to take protocol diffs yet as there are some definite memory funnies that
make protocol debugging still a little infeasible.

Alan

diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/Documentation/Configure.help linux/Documentation/Configure.help
--- linux.vanilla/Documentation/Configure.help Sun May 18 21:15:18 1997
+++ linux/Documentation/Configure.help Sun May 18 20:36:39 1997
@@ -4650,6 +4650,40 @@
also controls the radio tuner on this card, however this is not
yet supported in this software.

+Gallant's Audio Excel DSP 16 support (SC-6000 and SC-6600)
+CONFIG_AEDSP16
+ Answer Y if you have a Gallant's Audio Excel DSP 16 card. This card
+ emulate an SBPro or a Microsoft Sound System card.
+ You must select one of the Sound Blaster or Microsoft Sound System
+ drivers before select this menu item.
+ Read the drivers/sound/lowlevel/README.aedsp16 file and the head of
+ drivers/sound/lowlevel/aedsp16.c to have more informations about
+ this driver and its configuration.
+
+ If you are changing the card configuration, please, undefine all
+ the old Audio Excel parameters because leaving it defined while
+ selecting the alternate emulation, may screw up your .config file.
+
+ !!!NOTE!!!
+ The driver supports Audio Excel DSP 16 but not the III version of
+ this card. Read drivers/sound/lowlevel/Readme.aedsp16 if you want
+ to know something more on how to use the III version with this sound
+ driver.
+
+SC-6600 based audio cards (new Audio Excel DSP 16)
+CONFIG_SC6600
+ The SC6600 is the new version of DSP mounted on the Audio Excel DSP 16
+ cards. Check the FCC ID of your audio card and answer Y if you have an
+ SC6600 DSP.
+
+Audio Excel DSP 16 (MSS emulation)
+CONFIG_AEDSP16_MSS
+ Answer Y if you want your audio card emulate Microsoft Sound System.
+
+Audio Excel DSP 16 (SBPro emulation)
+CONFIG_AEDSP16_SBPRO
+ Answer Y if you want your audio card emulate Sound Blaster Pro.
+
Kernel profiling support
CONFIG_PROFILE
This is for kernel hackers who want to know how much time the kernel
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/Makefile linux/Makefile
--- linux.vanilla/Makefile Sun May 18 21:16:42 1997
+++ linux/Makefile Sun May 18 13:58:03 1997
@@ -38,7 +38,7 @@
AR =$(CROSS_COMPILE)ar
NM =$(CROSS_COMPILE)nm
STRIP =$(CROSS_COMPILE)strip
-MAKE =make
+MAKE =make -j3
GENKSYMS=/sbin/genksyms

all: do-it-all
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/drivers/net/defxx.c linux/drivers/net/defxx.c
--- linux.vanilla/drivers/net/defxx.c Sun May 18 21:12:39 1997
+++ linux/drivers/net/defxx.c Sun May 18 20:35:54 1997
@@ -226,6 +226,11 @@

#include "defxx.h"

+#define DYNAMIC_BUFFERS 1
+
+#define SKBUFF_RX_COPYBREAK 200
+#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX)
+
/* Define global routines */

int dfx_probe(struct device *dev);
@@ -1083,7 +1088,9 @@
alloc_size = sizeof(PI_DESCR_BLOCK) +
PI_CMD_REQ_K_SIZE_MAX +
PI_CMD_RSP_K_SIZE_MAX +
+#ifndef DYNAMIC_BUFFERS
(bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
+#endif
sizeof(PI_CONSUMER_BLOCK) +
(PI_ALIGN_K_DESC_BLK - 1);
top_v = (char *) kmalloc(alloc_size, GFP_KERNEL);
@@ -1135,8 +1142,11 @@

bp->rcv_block_virt = curr_v;
bp->rcv_block_phys = curr_p;
+
+#ifndef DYNAMIC_BUFFERS
curr_v += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
curr_p += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
+#endif

/* Reserve space for the consumer block */

@@ -2926,6 +2936,22 @@
* driver initialization when we allocated memory for the receive buffers.
*/

+#ifdef DYNAMIC_BUFFERS
+ for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
+ for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
+ {
+ struct sk_buff *newskb;
+ bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
+ ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
+ newskb = dev_alloc_skb(NEW_SKB_SIZE);
+ bp->descr_block_virt->rcv_data[i+j].long_1 = virt_to_bus(newskb->data);
+ /*
+ * p_rcv_buff_va is only used inside the
+ * kernel so we put the skb pointer here.
+ */
+ bp->p_rcv_buff_va[i+j] = (char *) newskb;
+ }
+#else
for (i=0; i < (int)(bp->rcv_bufs_to_post); i++)
for (j=0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
{
@@ -2934,6 +2960,7 @@
bp->descr_block_virt->rcv_data[i+j].long_1 = (u32) (bp->rcv_block_phys + (i * PI_RCV_DATA_K_SIZE_MAX));
bp->p_rcv_buff_va[i+j] = (char *) (bp->rcv_block_virt + (i * PI_RCV_DATA_K_SIZE_MAX));
}
+#endif

/* Update receive producer and Type 2 register */

@@ -2985,6 +3012,8 @@
u32 descr, pkt_len; /* FMC descriptor field and packet length */
struct sk_buff *skb; /* pointer to a sk_buff to hold incoming packet data */

+ static int testing_dyn;
+
/* Service all consumed LLC receive frames */

p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
@@ -2992,7 +3021,14 @@
{
/* Process any errors */

- p_buff = (char *) bp->p_rcv_buff_va[bp->rcv_xmt_reg.index.rcv_comp];
+ int entry;
+
+ entry = bp->rcv_xmt_reg.index.rcv_comp;
+#ifdef DYNAMIC_BUFFERS
+ p_buff = (char *) (((struct sk_buff *)bp->p_rcv_buff_va[entry])->data);
+#else
+ p_buff = (char *) bp->p_rcv_buff_va[entry];
+#endif
memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));

if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
@@ -3003,29 +3039,60 @@
bp->rcv_frame_status_errors++;
}
else
- {
+ {
+ int rx_in_place = 0;
+
/* The frame was received without errors - verify packet length */

pkt_len = (u32)((descr & PI_FMC_DESCR_M_LEN) >> PI_FMC_DESCR_V_LEN);
pkt_len -= 4; /* subtract 4 byte CRC */
if (!IN_RANGE(pkt_len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
bp->rcv_length_errors++;
- else
- {
- skb = dev_alloc_skb(pkt_len+3); /* alloc new buffer to pass up, add room for PRH */
+ else{
+#ifdef DYNAMIC_BUFFERS
+ if (pkt_len > SKBUFF_RX_COPYBREAK) {
+ struct sk_buff *newskb;
+
+ newskb = dev_alloc_skb(NEW_SKB_SIZE);
+ if (newskb){
+ rx_in_place = 1;
+#define JES_TESTING
+#ifdef JES_TESTING
+ if(testing_dyn++ < 5)
+ printk("Skipping a memcpy\n");
+ skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
+ skb->data += RCV_BUFF_K_PADDING;
+ bp->p_rcv_buff_va[entry] = (char *)newskb;
+ bp->descr_block_virt->rcv_data[entry].long_1 = virt_to_bus(newskb->data);
+#else
+ memcpy(newskb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
+ skb = newskb;
+#endif
+ } else
+ skb = 0;
+ } else
+#endif
+ skb = dev_alloc_skb(pkt_len+3); /* alloc new buffer to pass up, add room for PRH */
if (skb == NULL)
{
printk("%s: Could not allocate receive buffer. Dropping packet.\n", bp->dev->name);
bp->rcv_discards++;
+ break;
}
- else
+ else {
+#ifndef DYNAMIC_BUFFERS
+ if (! rx_in_place)
+#endif
{
- /* Receive buffer allocated, pass receive packet up */
+ /* Receive buffer allocated, pass receive packet up */
+
+ memcpy(skb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
+ }

- memcpy(skb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
skb->data += 3; /* adjust data field so that it points to FC byte */
skb->len = pkt_len; /* pass up packet length, NOT including CRC */
skb->dev = bp->dev; /* pass up device pointer */
+
skb->protocol = fddi_type_trans(skb, bp->dev);
netif_rx(skb);

@@ -3034,9 +3101,9 @@
bp->rcv_total_frames++;
if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
bp->rcv_multicast_frames++;
- }
}
}
+ }

/*
* Advance the producer (for recycling) and advance the completion
@@ -3140,6 +3207,7 @@
dev->name, skb->len);
bp->xmt_length_errors++; /* bump error counter */
dev_tint(dev); /* dequeue packets from xmt queue and send them */
+ dev_kfree_skb(skb, FREE_WRITE);
return(0); /* return "success" */
}
/*
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/drivers/net/dummy.c linux/drivers/net/dummy.c
--- linux.vanilla/drivers/net/dummy.c Sun May 18 21:12:40 1997
+++ linux/drivers/net/dummy.c Sun May 18 16:33:46 1997
@@ -134,7 +134,7 @@
{
/* Find a name for this unit */
int err=dev_alloc_name(&dev_dummy,"dummy%d");
- if(err)
+ if(err<0)
return err;
if (register_netdev(&dev_dummy) != 0)
return -EIO;
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- linux.vanilla/drivers/net/ibmtr.c Sun May 18 21:15:48 1997
+++ linux/drivers/net/ibmtr.c Sun May 18 20:30:55 1997
@@ -84,7 +84,7 @@
/* version and credits */
static char *version =
"ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n"
-" v2.1.29 3/15/97 Paul Norton <pnorton@cts.com>\n";
+" v2.1.35 5/ 1/97 Paul Norton <pnorton@cts.com>\n";

static char pcchannelid[] = {
0x05, 0x00, 0x04, 0x09,
@@ -1013,14 +1013,15 @@
} /* ARB response */

if (status & SSB_RESP_INT) { /* SSB response */
-
+ unsigned char retcode;
switch (readb(ti->ssb)) { /* SSB command check */
-
+
case XMIT_DIR_FRAME:
case XMIT_UI_FRAME:
- if (readb(ti->ssb+2)) /* checks ret_code */
+ retcode = readb(ti->ssb+2);
+ if (retcode && (retcode != 0x22)) /* checks ret_code */
DPRINTK("xmit ret_code: %02X xmit error code: %02X\n",
- (int)readb(ti->ssb+2), (int)readb(ti->ssb+6));
+ (int)retcode, (int)readb(ti->ssb+6));
else ti->tr_stats.tx_packets++;
break;

@@ -1321,12 +1322,12 @@
__u32 rbuffer, rbufdata;
__u32 llc;
unsigned char *data;
- unsigned int rbuffer_len, lan_hdr_len, hdr_len;
- unsigned int arb_frame_len;
+ unsigned int rbuffer_len, lan_hdr_len, hdr_len, ip_len, length;
struct sk_buff *skb;
unsigned int skb_size = 0;
int is8022 = 0;
unsigned int chksum = 0;
+ struct iphdr *iph;

rbuffer=(ti->sram
+ntohs(readw(ti->arb + offsetof(struct arb_rec_req, rec_buf_addr))))+2;
@@ -1400,8 +1401,8 @@
}
#endif

- arb_frame_len=ntohs(readw(ti->arb+offsetof(struct arb_rec_req, frame_len)));
- skb_size = arb_frame_len-lan_hdr_len+sizeof(struct trh_hdr);
+ length = ntohs(readw(ti->arb+offsetof(struct arb_rec_req, frame_len)));
+ skb_size = length-lan_hdr_len+sizeof(struct trh_hdr);
if (is8022) {
skb_size += sizeof(struct trllc);
}
@@ -1429,30 +1430,42 @@
rbuffer_len=ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)))-lan_hdr_len;

if (is8022) {
- /* create whitewashed LLC header in skb buffer (why not the real one?) */
+ /* create whitewashed LLC header in sk buffer */
struct trllc *local_llc = (struct trllc *)data;
memset(local_llc, 0, sizeof(*local_llc));
local_llc->ethertype = htons(ETH_P_TR_802_2);
hdr_len = sizeof(struct trllc);
+ /* copy the real LLC header to the sk buffer */
+ data += hdr_len;
+ memcpy_fromio(data, rbuffer+offsetof(struct rec_buf, data)+lan_hdr_len,hdr_len);
} else {
/* Copy the LLC header and the IPv4 header */
hdr_len = sizeof(struct trllc) + sizeof(struct iphdr);
memcpy_fromio(data, rbuffer+offsetof(struct rec_buf, data)+lan_hdr_len,hdr_len);
+
+ /* Watch for padded packets and bogons */
+ iph=(struct iphdr*)(data+sizeof(struct trllc));
+ ip_len = ntohs(iph->tot_len) - sizeof(struct iphdr);
+ length -= lan_hdr_len + hdr_len;
+ if ((ip_len <= length) && (ip_len > 7))
+ length = ip_len;
}
data += hdr_len;
- lan_hdr_len += hdr_len;
rbuffer_len -= hdr_len;
- rbufdata = rbuffer + offsetof(struct rec_buf,data) + lan_hdr_len;
+ rbufdata = rbuffer + offsetof(struct rec_buf,data) + lan_hdr_len + hdr_len;

/* Copy the payload... */
for (;;) {
if (is8022)
memcpy_fromio(data, rbufdata, rbuffer_len);
else
- chksum = csum_partial_copy(bus_to_virt(rbufdata), data, rbuffer_len, chksum);
+ chksum = csum_partial_copy(bus_to_virt(rbufdata), data,
+ length < rbuffer_len ? length : rbuffer_len,
+ chksum);
rbuffer = ntohs(readw(rbuffer));
if (!rbuffer)
break;
+ length -= rbuffer_len;
data += rbuffer_len;
rbuffer += ti->sram;
rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)));
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux.vanilla/drivers/pci/pci.c Sun May 18 21:15:53 1997
+++ linux/drivers/pci/pci.c Sun May 18 20:33:14 1997
@@ -150,6 +150,7 @@
DEVICE( CMD, CMD_646, "646"),
DEVICE( VISION, VISION_QD8500, "QD-8500"),
DEVICE( VISION, VISION_QD8580, "QD-8580"),
+ DEVICE( BROOKTREE, BT848, "Brooktree 848"),
DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64"),
DEVICE( ACC, ACC_2056, "2056"),
DEVICE( WINBOND, WINBOND_83769, "W83769F"),
@@ -264,6 +265,7 @@
DEVICE( INTEL, INTEL_82437VX, "82437VX Triton II"),
DEVICE( INTEL, INTEL_82371AB, "82371AB 430TX PIIX4"),
DEVICE( INTEL, INTEL_P6, "Orion P6"),
+ DEVICE( INTEL, INTEL_P6_2, "82450GX Orion P6"),
DEVICE( KTI, KTI_ET32P2, "ET32P2"),
DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"),
DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855"),
@@ -518,6 +520,7 @@
case PCI_VENDOR_ID_OLICOM: return "Olicom";
case PCI_VENDOR_ID_CMD: return "CMD";
case PCI_VENDOR_ID_VISION: return "Vision";
+ case PCI_VENDOR_ID_BROOKTREE: return "Brooktree";
case PCI_VENDOR_ID_SIERRA: return "Sierra";
case PCI_VENDOR_ID_ACC: return "ACC MICROELECTRONICS";
case PCI_VENDOR_ID_WINBOND: return "Winbond";
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/include/linux/pci.h linux/include/linux/pci.h
--- linux.vanilla/include/linux/pci.h Sun May 18 21:13:11 1997
+++ linux/include/linux/pci.h Sun May 18 20:32:30 1997
@@ -408,6 +408,9 @@
#define PCI_DEVICE_ID_VISION_QD8500 0x0001
#define PCI_DEVICE_ID_VISION_QD8580 0x0002

+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#define PCI_DEVICE_ID_BT848 0x0350 /* 0x350 = 848 */
+
#define PCI_VENDOR_ID_SIERRA 0x10a8
#define PCI_DEVICE_ID_SIERRA_STB 0x0000

@@ -595,6 +598,7 @@
#define PCI_DEVICE_ID_INTEL_82437VX 0x7030
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
#define PCI_DEVICE_ID_INTEL_P6 0x84c4
+#define PCI_DEVICE_ID_INTEL_P6_2 0x84c5

#define PCI_VENDOR_ID_KTI 0x8e2e
#define PCI_DEVICE_ID_KTI_ET32P2 0x3000
diff --new-file --unified --recursive --exclude-from exclude linux.vanilla/net/core/dev.c linux/net/core/dev.c
--- linux.vanilla/net/core/dev.c Sun May 18 21:13:15 1997
+++ linux/net/core/dev.c Sun May 18 13:57:43 1997
@@ -986,6 +986,9 @@
/*
* Loop over the interfaces, and write an info block for each.
*/
+
+ dev_lock_wait();
+ dev_lock_list();

for (dev = dev_base; dev != NULL; dev = dev->next)
{
@@ -1013,6 +1016,8 @@
len -= sizeof(struct ifreq);
}

+ dev_unlock_list();
+
/*
* All done. Write the updated control block back to the caller.
*/