From c360181954c26c6311c1f791d23e574e203ae55f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:12:04 -0500 Subject: [PATCH] 2.0.36pre18 Fixes from pre17 o 5.1.4 aic7xxx driver (EISA 274x cards now work) o SMP debug message removed o TCP performance optimisation from Dave Miller (and I thought he was on honeymoon 8)) o Makefile fix for modules/versioning bug o A couple of very minor cleanups If this proves ok it goes to Linus Alan --- Rules.make | 2 + arch/i386/kernel/irq.c | 4 + crud | 236 ------------------------------- drivers/scsi/aic7xxx.c | 115 ++++++++------- drivers/scsi/aic7xxx/sequencer.h | 40 +++++- drivers/sound/local.h | 45 ++++++ net/ipv4/tcp_input.c | 7 +- 7 files changed, 159 insertions(+), 290 deletions(-) delete mode 100644 crud create mode 100644 drivers/sound/local.h diff --git a/Rules.make b/Rules.make index a32cb0b451f1..ad5819673f34 100644 --- a/Rules.make +++ b/Rules.make @@ -155,6 +155,8 @@ $(MODINCL)/%.ver: %.c $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h +.PHONY: $(TOPDIR)/include/linux/modversions.h + $(TOPDIR)/include/linux/modversions.h: $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)) @echo updating $(TOPDIR)/include/linux/modversions.h @(echo "#ifdef MODVERSIONS";\ diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index f29dd176598a..6db6115795ee 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -346,9 +346,11 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) struct irqaction * action = *(irq + irq_action); int do_random = 0; int c,intm,mask; +#ifdef IRQ_DEBUG static int count; if (smp_processor_id() != 0 && count++ < 1000) printk("IRQ %d: done by CPU %d\n",irq,smp_processor_id()); +#endif if (irq >= 8) { c = cache_A1; intm = inb(0xA1); @@ -359,7 +361,9 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) mask = 1 << irq; } if (!(c & mask) || !(intm & mask)) { +#ifdef IRQ_DEBUG printk("IRQ %d (proc %d):cache_x1=0x%x,INT mask=0x%x\n", irq, smp_processor_id(),c,intm); +#endif /* better to return because the interrupt may be asserted again, the bad thing is that we may loose some interrupts */ return; diff --git a/crud b/crud deleted file mode 100644 index f9ccc5a0e304..000000000000 --- a/crud +++ /dev/null @@ -1,236 +0,0 @@ -Date: Tue, 3 Nov 1998 17:53:44 -0300 -From: Juanjo Ciarlante -To: Linus Torvalds , "David S. Miller" , David Woodhouse -Cc: linux-kernel@vger.rutgers.edu -Subject: [PATCH] IP masq csum fix - - -On Tue, Nov 03, 1998 at 04:51:34PM +0000, David Woodhouse wrote: -> Thanks to Juanjo and Andi, I think this problem is now fixed. -> -> I think both of you simultaneously came up with the idea that the offset of -> the data payload (proto_doff) could be negative, causing csum_partial() to -> checksum the whole of physical memory before oopsing. -> -This patch fixes incorrect ip_masq csuming when faced with corrupted pkts. - -It have been succesfully tested by David "tortured-by-Oops" Woodhouse, -his Oops have stopped so apparently it did fix the problem -(_apart_ from the "apparent-fix" its a REAL code fix). - -Linus, could you please apply it? - --- --- Juanjo http://juanjox.home.ml.org/ - - == free collective power ==---. - Linux <------------' - - - -Basically, this patch does an ``anal-tappo'' protocol data size -check at ip_fw_*masq() entry path. - - ---- linux/net/ipv4/ip_masq.c.dist Fri Oct 23 10:39:57 1998 -+++ linux/net/ipv4/ip_masq.c Tue Nov 3 17:15:36 1998 -@@ -337,6 +337,9 @@ - #define PORT_MASQ_MUL 10 - #endif - -+/* -+ * At the moment, hardcore in sync with masq_proto_num -+ */ - atomic_t ip_masq_free_ports[3] = { - ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* UDP */ - ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* TCP */ -@@ -960,15 +963,40 @@ - return NULL; - } - --static __inline__ unsigned proto_doff(unsigned proto, char *th) -+/* -+ * Get transport protocol data offset, check against size -+ */ -+static __inline__ int proto_doff(unsigned proto, char *th, unsigned size) - { -+ unsigned ret = -1; - switch (proto) { -+ case IPPROTO_ICMP: -+ if (size >= sizeof(struct icmphdr)) -+ ret = sizeof(struct icmphdr); -+ break; - case IPPROTO_UDP: -- return sizeof(struct udphdr); -+ if (size >= sizeof(struct udphdr)) -+ ret = sizeof(struct udphdr); -+ break; - case IPPROTO_TCP: -- return ((struct tcphdr*)th)->doff << 2; -+ /* -+ * Is this case, this check _also_ avoids -+ * touching an invalid pointer if -+ * size is invalid -+ */ -+ if (size >= sizeof(struct tcphdr)) { -+ ret = ((struct tcphdr*)th)->doff << 2; -+ if (ret > size) { -+ ret = -1 ; -+ } -+ } -+ -+ break; - } -- return 0; -+ if (ret < 0) -+ IP_MASQ_DEBUG(0, "mess proto_doff for proto=%d, size =%d\n", -+ proto, size); -+ return ret; - } - - int ip_fw_masquerade(struct sk_buff **skb_p, __u32 maddr) -@@ -980,19 +1008,26 @@ - int size; - - /* -- * Magic "doff" csum semantics -- * !0: saved payload csum IS valid, doff is correct -- * 0: csum not valid -+ * doff holds transport protocol data offset -+ * csum holds its checksum -+ * csum_ok says if csum is valid - */ -- unsigned doff = 0; -+ int doff = 0; - int csum = 0; -+ int csum_ok = 0; - - /* - * We can only masquerade protocols with ports... and hack some ICMPs - */ - - h.raw = (char*) iph + iph->ihl * 4; -+ size = ntohs(iph->tot_len) - (iph->ihl * 4); - -+ doff = proto_doff(iph->protocol, h.raw, size); -+ if (doff < 0) { -+ IP_MASQ_DEBUG(0, "O-pkt invalid packet data size\n"); -+ return -1; -+ } - switch (iph->protocol) { - case IPPROTO_ICMP: - return(ip_fw_masq_icmp(skb_p, maddr)); -@@ -1002,7 +1037,6 @@ - break; - case IPPROTO_TCP: - /* Make sure packet is in the masq range */ -- size = ntohs(iph->tot_len) - (iph->ihl * 4); - IP_MASQ_DEBUG(3, "O-pkt: %s size=%d\n", - masq_proto_name(iph->protocol), - size); -@@ -1011,7 +1045,7 @@ - switch (skb->ip_summed) - { - case CHECKSUM_NONE: -- doff = proto_doff(iph->protocol, h.raw); -+ csum_ok++; - csum = csum_partial(h.raw + doff, size - doff, 0); - IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n", - masq_proto_name(iph->protocol), -@@ -1133,7 +1167,7 @@ - */ - - if (ms->app) -- doff = 0; -+ csum_ok = 0; - - /* - * Attempt ip_masq_app call. -@@ -1148,6 +1182,7 @@ - iph = skb->nh.iph; - h.raw = (char*) iph + iph->ihl *4; - size = skb->len - (h.raw - skb->nh.raw); -+ /* doff should have not changed */ - } - - /* -@@ -1158,8 +1193,7 @@ - * Transport's payload partial csum - */ - -- if (!doff) { -- doff = proto_doff(iph->protocol, h.raw); -+ if (!csum_ok) { - csum = csum_partial(h.raw + doff, size - doff, 0); - } - skb->csum = csum; -@@ -1710,8 +1744,9 @@ - union ip_masq_tphdr h; - struct ip_masq *ms; - unsigned short size; -- unsigned doff = 0; -+ int doff = 0; - int csum = 0; -+ int csum_ok = 0; - __u32 maddr; - - /* -@@ -1727,8 +1762,19 @@ - return 0; - } - -- maddr = iph->daddr; - h.raw = (char*) iph + iph->ihl * 4; -+ /* -+ * IP payload size -+ */ -+ size = ntohs(iph->tot_len) - (iph->ihl * 4); -+ -+ doff = proto_doff(iph->protocol, h.raw, size); -+ if (doff < 0) { -+ IP_MASQ_DEBUG(0, "I-pkt invalid packet data size\n"); -+ return -1; -+ } -+ -+ maddr = iph->daddr; - - switch (iph->protocol) { - case IPPROTO_ICMP: -@@ -1749,7 +1795,6 @@ - return 0; - - /* Check that the checksum is OK */ -- size = ntohs(iph->tot_len) - (iph->ihl * 4); - if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0)) - /* No UDP checksum */ - break; -@@ -1757,8 +1802,8 @@ - switch (skb->ip_summed) - { - case CHECKSUM_NONE: -- doff = proto_doff(iph->protocol, h.raw); - csum = csum_partial(h.raw + doff, size - doff, 0); -+ csum_ok++; - skb->csum = csum_partial(h.raw , doff, csum); - - case CHECKSUM_HW: -@@ -1846,7 +1891,7 @@ - */ - - if (ms->app) -- doff = 0; -+ csum_ok = 0; - - /* - * Attempt ip_masq_app call. -@@ -1873,8 +1918,7 @@ - * Transport's payload partial csum - */ - -- if (!doff) { -- doff = proto_doff(iph->protocol, h.raw); -+ if (!csum_ok) { - csum = csum_partial(h.raw + doff, size - doff, 0); - } - skb->csum = csum; - diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c index 4edef1bdc225..11d37d6174ff 100644 --- a/drivers/scsi/aic7xxx.c +++ b/drivers/scsi/aic7xxx.c @@ -304,13 +304,18 @@ * #define AIC7XXX_VERBOSE_DEBUGGING */ -#ifdef MODULE +#if defined(MODULE) || defined(PCMCIA) #include #endif +#if defined(PCMCIA) +# undef MODULE +#endif + #include #include #include +#include #include #include #include @@ -349,7 +354,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = { 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.3" +#define AIC7XXX_C_VERSION "5.1.4" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -683,12 +688,14 @@ struct seeprom_config { #define CFDISC 0x0010 /* enable disconnection */ #define CFWIDEB 0x0020 /* wide bus device (wide card) */ #define CFSYNCHISULTRA 0x0040 /* CFSYNC is an ultra offset */ -/* UNUSED 0x0080 */ +#define CFNEWULTRAFORMAT 0x0080 /* Use the Ultra2 SEEPROM format */ #define CFSTART 0x0100 /* send start unit SCSI command */ #define CFINCBIOS 0x0200 /* include in BIOS scan */ #define CFRNFOUND 0x0400 /* report even if not found */ #define CFMULTILUN 0x0800 /* probe mult luns in BIOS scan */ -/* UNUSED 0xF000 */ +#define CFWBCACHEYES 0x4000 /* Enable W-Behind Cache on drive */ +#define CFWBCACHENC 0xc000 /* Don't change W-Behind Cache */ +/* UNUSED 0x3000 */ unsigned short device_flags[16]; /* words 0-15 */ /* @@ -1481,8 +1488,8 @@ static int aic7xxx_verbose = VERBOSE_NORMAL | VERBOSE_NEGOTIATION | static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd); static void aic7xxx_print_card(struct aic7xxx_host *p); static void aic7xxx_print_scratch_ram(struct aic7xxx_host *p); -#ifdef AIC7XXX_VERBOSE_DEBUGGING static void aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded); +#ifdef AIC7XXX_VERBOSE_DEBUGGING static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer); #endif @@ -1544,26 +1551,6 @@ aic_outb(struct aic7xxx_host *p, unsigned char val, long port) #endif } -static void -aic_outsb(struct aic7xxx_host *p, long port, unsigned char *valp, size_t size) -{ -#ifdef MMAPIO - if(p->maddr) - { - int i; - for (i=0; i < size; i++) - { - p->maddr[port] = valp[i]; - } - mb(); - } - else - outsb(p->base + port, valp, size); -#else - outsb(p->base + port, valp, size); -#endif -} - /*+F************************************************************************* * Function: * aic7xxx_setup @@ -1752,7 +1739,9 @@ unpause_sequencer(struct aic7xxx_host *p, int unpause_always) static inline void restart_sequencer(struct aic7xxx_host *p) { - aic_outb(p, FASTMODE|SEQRESET, SEQCTL); + aic_outb(p, 0, SEQADDR0); + aic_outb(p, 0, SEQADDR1); + aic_outb(p, FASTMODE, SEQCTL); } /* @@ -1831,6 +1820,8 @@ aic7xxx_download_instr(struct aic7xxx_host *p, int instrptr, instr = *(union ins_formats*) &seqprog[instrptr * 4]; + instr.integer = le32_to_cpu(instr.integer); + fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -1926,7 +1917,10 @@ aic7xxx_download_instr(struct aic7xxx_host *p, int instrptr, (fmt1_ins->opcode << 25); } } - aic_outsb(p, SEQRAM, instr.bytes, 4); + aic_outb(p, (instr.integer & 0xff), SEQRAM); + aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM); + aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM); + aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM); break; default: @@ -1976,18 +1970,21 @@ aic7xxx_loadseq(struct aic7xxx_host *p) downloaded++; } - aic_outb(p, FASTMODE|SEQRESET, SEQCTL); + aic_outb(p, 0, SEQADDR0); + aic_outb(p, 0, SEQADDR1); + aic_outb(p, FASTMODE | FAILDIS, SEQCTL); + unpause_sequencer(p, TRUE); + mdelay(1); + pause_sequencer(p); + aic_outb(p, FASTMODE, SEQCTL); if (aic7xxx_verbose & VERBOSE_PROBE) { printk(" %d instructions downloaded\n", downloaded); } -#ifdef AIC7XXX_VERBOSE_DEBUGGING if (aic7xxx_dump_sequencer) aic7xxx_print_sequencer(p, downloaded); -#endif } -#ifdef AIC7XXX_VERBOSE_DEBUGGING /*+F************************************************************************* * Function: * aic7xxx_print_sequencer @@ -2022,10 +2019,15 @@ aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded) else printk(" "); } - aic_outb(p, FASTMODE|SEQRESET, SEQCTL); + aic_outb(p, 0, SEQADDR0); + aic_outb(p, 0, SEQADDR1); + aic_outb(p, FASTMODE | FAILDIS, SEQCTL); + unpause_sequencer(p, TRUE); + mdelay(1); + pause_sequencer(p); + aic_outb(p, FASTMODE, SEQCTL); printk("\n"); } -#endif /*+F************************************************************************* * Function: @@ -5512,7 +5514,7 @@ aic7xxx_handle_reqinit(struct aic7xxx_host *p, struct aic7xxx_scb *scb) { unsigned char lastbyte; unsigned char phasemis; - int done; + int done = FALSE; switch(p->msg_type) { @@ -7563,6 +7565,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, p->host_no, p->mbase, (unsigned long)p->maddr); } +#ifdef CONFIG_PCI /* * Now that we know our instance number, we can set the flags we need to * force termination if need be. @@ -7602,6 +7605,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, #endif } } +#endif /* * That took care of devconfig and stpwlev, now for the actual termination @@ -7652,19 +7656,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, } } - /* - * Load the sequencer program, then re-enable the board - - * resetting the AIC-7770 disables it, leaving the lights - * on with nobody home. - */ - aic7xxx_loadseq(p); - - if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 ) - { - aic_outb(p, ENABLE, BCTL); /* Enable the boards BUS drivers. */ - } - aic_outb(p, aic_inb(p, SBLKCTL) & ~AUTOFLUSHDIS, SBLKCTL); - /* * Clear out any possible pending interrupts. */ @@ -7867,6 +7858,18 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, */ aic7xxx_allocate_scb(p); + /* + * Load the sequencer program, then re-enable the board - + * resetting the AIC-7770 disables it, leaving the lights + * on with nobody home. + */ + aic7xxx_loadseq(p); + + if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 ) + { + aic_outb(p, ENABLE, BCTL); /* Enable the boards BUS drivers. */ + } + if ( !(aic7xxx_no_reset) ) { if (p->features & AHC_TWIN) @@ -8269,9 +8272,10 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1) { for (i = 0; i < max_targets; i++) { - if( (p->features & AHC_ULTRA) && - !(sc->adapter_control & CFULTRAEN) && - (sc->device_flags[i] & CFSYNCHISULTRA) ) + if( ((p->features & AHC_ULTRA) && + !(sc->adapter_control & CFULTRAEN) && + (sc->device_flags[i] & CFSYNCHISULTRA)) || + (sc->device_flags[i] & CFNEWULTRAFORMAT) ) { p->flags |= AHC_NEWEEPROM_FMT; break; @@ -8348,6 +8352,15 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1) { p->ultraenb |= mask; } + else if (sc->device_flags[i] & CFNEWULTRAFORMAT) + { + if ( (sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03 ) + { + sc->device_flags[i] &= ~CFXFER; + sc->device_flags[i] |= CFSYNCHISULTRA; + p->ultraenb |= mask; + } + } } else if (sc->adapter_control & CFULTRAEN) { @@ -8495,8 +8508,10 @@ aic7xxx_detect(Scsi_Host_Template *template) struct aic7xxx_host *current_p = NULL; struct aic7xxx_host *list_p = NULL; int found = 0; +#if defined(__i386__) || defined(__alpha__) ahc_flag_type flags = 0; int type; +#endif unsigned char sxfrctl1; #if defined(__i386__) || defined(__alpha__) unsigned char hcntrl, hostconf; diff --git a/drivers/scsi/aic7xxx/sequencer.h b/drivers/scsi/aic7xxx/sequencer.h index 669e1b88daf6..f55c002dcf2b 100644 --- a/drivers/scsi/aic7xxx/sequencer.h +++ b/drivers/scsi/aic7xxx/sequencer.h @@ -36,8 +36,10 @@ * $Id: sequencer.h,v 1.3 1997/09/27 19:37:31 gibbs Exp $ */ +#ifdef __LITTLE_ENDIAN_BITFIELD struct ins_format1 { - unsigned int immediate : 8, + unsigned int + immediate : 8, source : 9, destination : 9, ret : 1, @@ -46,7 +48,8 @@ struct ins_format1 { }; struct ins_format2 { - unsigned int shift_control : 8, + unsigned int + shift_control : 8, source : 9, destination : 9, ret : 1, @@ -55,12 +58,43 @@ struct ins_format2 { }; struct ins_format3 { - unsigned int immediate : 8, + unsigned int + immediate : 8, source : 9, address : 10, opcode : 4, parity : 1; }; +#elif defined(__BIG_ENDIAN_BITFIELD) +struct ins_format1 { + unsigned int + parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + immediate : 8; +}; + +struct ins_format2 { + unsigned int + parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + shift_control : 8; +}; + +struct ins_format3 { + unsigned int + parity : 1, + opcode : 4, + address : 10, + source : 9, + immediate : 8; +}; +#endif union ins_formats { struct ins_format1 format1; diff --git a/drivers/sound/local.h b/drivers/sound/local.h new file mode 100644 index 000000000000..84ad84259faf --- /dev/null +++ b/drivers/sound/local.h @@ -0,0 +1,45 @@ +/* Computer generated file. Please don't edit! */ + +#define KERNEL_COMPATIBLE_CONFIG + +#define SELECTED_SOUND_OPTIONS 0x00000000 + +#if \ + defined(CONFIG_PSS) || defined(CONFIG_SSCAPE) || \ + defined(CONFIG_CS4232) || defined(CONFIG_MAUI) +# define CONFIG_MPU_EMU +#endif + +#if \ + defined(CONFIG_PSS) || defined(CONFIG_GUS16) || \ + defined(CONFIG_GUSMAX) || defined(CONFIG_MSS) || \ + defined(CONFIG_SSCAPE) || defined(CONFIG_TRIX) || \ + defined(CONFIG_MAD16) || defined(CONFIG_CS4232) +# define CONFIG_AD1848 +#endif + +#if \ + defined(CONFIG_SB) || defined(CONFIG_TRIX) || \ + defined(CONFIG_MAD16) +# define CONFIG_SBDSP +#endif + +#if \ + defined(CONFIG_SB) || defined(CONFIG_TRIX) || \ + defined(CONFIG_MAD16) +# define CONFIG_UART401 +#endif + +#if \ + defined(CONFIG_PAS) || defined(CONFIG_SB) || \ + defined(CONFIG_ADLIB) || defined(CONFIG_GUS) || \ + defined(CONFIG_MPU401) || defined(CONFIG_PSS) || \ + defined(CONFIG_SSCAPE) || defined(CONFIG_TRIX) || \ + defined(CONFIG_MAD16) || defined(CONFIG_CS4232) || \ + defined(CONFIG_MAUI) +# define CONFIG_SEQUENCER +#endif + +#define SOUND_CONFIG_DATE "Tue Oct 20 22:34:11 BST 1998" +#define SOUND_CONFIG_BY "root" +#define SOUND_UNAME_A "Linux roadrunner.swansea.linux.org.uk 2.0.36 #13 Wed Oct 14 21:34:08 BST 1998 i686 unknown" diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e3d5268bcae8..976870855f3c 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1963,8 +1963,13 @@ static void tcp_queue(struct sk_buff * skb, struct sock * sk, struct tcphdr *th) * Delay the ack if possible. Send ack's to * fin frames immediately as there shouldn't be * anything more to come. + * + * ACK immediately if we still have any out of + * order data. This is because we desire "maximum + * feedback during loss". --DaveM */ - if (!sk->delay_acks || th->fin) { + if (!sk->delay_acks || th->fin || + (skb->next != (struct sk_buff *) &sk->receive_queue)) { tcp_send_ack(sk); } else { /* -- 2.39.5