## Automatically generated incremental diff ## From: linux-2.4.21-bk23 ## To: linux-2.4.21-bk24 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.4.21-bk23/Documentation/networking/ifenslave.c linux-2.4.21-bk24/Documentation/networking/ifenslave.c --- linux-2.4.21-bk23/Documentation/networking/ifenslave.c 2003-08-01 02:53:16.000000000 -0700 +++ linux-2.4.21-bk24/Documentation/networking/ifenslave.c 2003-08-01 02:53:23.000000000 -0700 @@ -140,8 +140,7 @@ #include #include #include -#include -#include +#include #include #include #include diff -urN linux-2.4.21-bk23/Makefile linux-2.4.21-bk24/Makefile --- linux-2.4.21-bk23/Makefile 2003-08-01 02:53:17.000000000 -0700 +++ linux-2.4.21-bk24/Makefile 2003-08-01 02:53:23.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 -EXTRAVERSION = -bk23 +EXTRAVERSION = -bk24 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -urN linux-2.4.21-bk23/arch/i386/kernel/i387.c linux-2.4.21-bk24/arch/i386/kernel/i387.c --- linux-2.4.21-bk23/arch/i386/kernel/i387.c 2002-08-02 17:39:42.000000000 -0700 +++ linux-2.4.21-bk24/arch/i386/kernel/i387.c 2003-08-01 02:53:23.000000000 -0700 @@ -373,14 +373,14 @@ static inline int restore_i387_fxsave( struct _fpstate *buf ) { + int err; struct task_struct *tsk = current; clear_fpu( tsk ); - if ( __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0], - sizeof(struct i387_fxsave_struct) ) ) - return 1; + err = __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0], + sizeof(struct i387_fxsave_struct) ); /* mxcsr bit 6 and 31-16 must be zero for security reasons */ tsk->thread.i387.fxsave.mxcsr &= 0xffbf; - return convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf ); + return err ? 1 : convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf ); } int restore_i387( struct _fpstate *buf ) diff -urN linux-2.4.21-bk23/arch/i386/kernel/io_apic.c linux-2.4.21-bk24/arch/i386/kernel/io_apic.c --- linux-2.4.21-bk23/arch/i386/kernel/io_apic.c 2003-08-01 02:53:17.000000000 -0700 +++ linux-2.4.21-bk24/arch/i386/kernel/io_apic.c 2003-08-01 02:53:23.000000000 -0700 @@ -1343,6 +1343,25 @@ static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ } +#ifndef CONFIG_SMP + +void send_IPI_self(int vector) +{ + unsigned int cfg; + + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); +} + +#endif /* CONFIG_SMP */ + static void set_ioapic_affinity (unsigned int irq, unsigned long mask) { unsigned long flags; diff -urN linux-2.4.21-bk23/drivers/block/cciss.c linux-2.4.21-bk24/drivers/block/cciss.c --- linux-2.4.21-bk23/drivers/block/cciss.c 2003-08-01 02:53:19.000000000 -0700 +++ linux-2.4.21-bk24/drivers/block/cciss.c 2003-08-01 02:53:24.000000000 -0700 @@ -48,7 +48,7 @@ #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,47) /* Embedded module documentation macros - see modules.h */ -MODULE_AUTHOR("Charles M. White III - Hewlett-Packard Company"); +MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.47"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"); MODULE_LICENSE("GPL"); @@ -2341,7 +2341,7 @@ /* Is this interrupt for us? */ - if (h->access.intr_pending(h) == 0) + if ((h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0)) return; /* diff -urN linux-2.4.21-bk23/drivers/block/cciss.h linux-2.4.21-bk24/drivers/block/cciss.h --- linux-2.4.21-bk23/drivers/block/cciss.h 2003-08-01 02:53:19.000000000 -0700 +++ linux-2.4.21-bk24/drivers/block/cciss.h 2003-08-01 02:53:24.000000000 -0700 @@ -51,7 +51,7 @@ unsigned long io_mem_length; CfgTable_struct *cfgtable; int intr; - + int interrupts_enabled; int max_commands; int commands_outstanding; int max_outstanding; /* Debug */ @@ -139,9 +139,11 @@ { if (val) { /* Turn interrupts on */ + h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else /* Turn them off */ { + h->interrupts_enabled = 0; writel( SA5_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } @@ -155,9 +157,11 @@ { if (val) { /* Turn interrupts on */ + h->interrupts_enabled = 1; writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } else /* Turn them off */ { + h->interrupts_enabled = 0; writel( SA5B_INTR_OFF, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } diff -urN linux-2.4.21-bk23/drivers/char/agp/agpgart_be.c linux-2.4.21-bk24/drivers/char/agp/agpgart_be.c --- linux-2.4.21-bk23/drivers/char/agp/agpgart_be.c 2003-08-01 02:53:20.000000000 -0700 +++ linux-2.4.21-bk24/drivers/char/agp/agpgart_be.c 2003-08-01 02:53:25.000000000 -0700 @@ -5580,7 +5580,11 @@ { long memory, index, result; - memory = (num_physpages << PAGE_SHIFT) >> 20; +#if PAGE_SHIFT < 20 + memory = num_physpages >> (20 - PAGE_SHIFT); +#else + memory = num_physpages << (PAGE_SHIFT - 20); +#endif index = 1; while ((memory > maxes_table[index].mem) && diff -urN linux-2.4.21-bk23/drivers/net/bonding/bond_main.c linux-2.4.21-bk24/drivers/net/bonding/bond_main.c --- linux-2.4.21-bk23/drivers/net/bonding/bond_main.c 2003-08-01 02:53:20.000000000 -0700 +++ linux-2.4.21-bk24/drivers/net/bonding/bond_main.c 2003-08-01 02:53:25.000000000 -0700 @@ -524,7 +524,7 @@ MODULE_PARM(miimon, "i"); MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); MODULE_PARM(use_carrier, "i"); -MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 09 for off, 1 for on (default)"); +MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)"); MODULE_PARM(mode, "s"); MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor"); MODULE_PARM(arp_interval, "i"); @@ -1594,11 +1594,14 @@ #endif bond_set_slave_inactive_flags(new_slave); } - read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); - ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list); - ifa = *ifap; - my_ip = ifa->ifa_address; - read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); + if (((struct in_device *)slave_dev->ip_ptr) != NULL) { + read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); + ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list); + ifa = *ifap; + if (ifa != NULL) + my_ip = ifa->ifa_address; + read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); + } /* if there is a primary slave, remember it */ if (primary != NULL) { diff -urN linux-2.4.21-bk23/drivers/scsi/3w-xxxx.c linux-2.4.21-bk24/drivers/scsi/3w-xxxx.c --- linux-2.4.21-bk23/drivers/scsi/3w-xxxx.c 2003-06-13 07:51:36.000000000 -0700 +++ linux-2.4.21-bk24/drivers/scsi/3w-xxxx.c 2003-08-01 02:53:25.000000000 -0700 @@ -165,6 +165,14 @@ Add support for "twe" character device for ioctls. Clean up request_id queueing code. Fix tw_scsi_queue() spinlocks. + 1.02.00.033 - Fix tw_aen_complete() to not queue 'queue empty' AEN's. + Initialize queues correctly when loading with no valid units. + 1.02.00.034 - Fix tw_decode_bits() to handle multiple errors. + Add support for user configurable cmd_per_lun. + Add support for sht->select_queue_depths. + 1.02.00.035 - Improve tw_allocate_memory() memory allocation. + Fix tw_chrdev_ioctl() to sleep correctly. + 1.02.00.036 - Increase character ioctl timeout to 60 seconds. */ #include @@ -232,7 +240,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.032"; +char *tw_driver_version="1.02.00.036"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; static int twe_major = -1; @@ -271,25 +279,24 @@ printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen); } } - if (aen != 0x0) + if (aen != TW_AEN_QUEUE_EMPTY) { tw_dev->aen_count++; - /* Now queue the code */ - tw_dev->aen_queue[tw_dev->aen_tail] = aen; - if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { - tw_dev->aen_tail = TW_Q_START; - } else { - tw_dev->aen_tail = tw_dev->aen_tail + 1; - } - if (tw_dev->aen_head == tw_dev->aen_tail) { - if (tw_dev->aen_head == TW_Q_LENGTH - 1) { - tw_dev->aen_head = TW_Q_START; + /* Now queue the code */ + tw_dev->aen_queue[tw_dev->aen_tail] = aen; + if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { + tw_dev->aen_tail = TW_Q_START; } else { - tw_dev->aen_head = tw_dev->aen_head + 1; + tw_dev->aen_tail = tw_dev->aen_tail + 1; + } + if (tw_dev->aen_head == tw_dev->aen_tail) { + if (tw_dev->aen_head == TW_Q_LENGTH - 1) { + tw_dev->aen_head = TW_Q_START; + } else { + tw_dev->aen_head = tw_dev->aen_head + 1; + } } - } - if (aen != TW_AEN_QUEUE_EMPTY) { error = tw_aen_read_queue(tw_dev, request_id); if (error) { printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no); @@ -556,34 +563,33 @@ else imax = TW_Q_LENGTH; - for (i=0;itw_pci_dev, size, &dma_handle); - if (cpu_addr == NULL) { - printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n"); - return 1; - } + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*imax, &dma_handle); + if (cpu_addr == NULL) { + printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n"); + return 1; + } - if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) { - printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n"); - pci_free_consistent(tw_dev->tw_pci_dev, size, cpu_addr, dma_handle); - return 1; - } + if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) { + printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n"); + pci_free_consistent(tw_dev->tw_pci_dev, size*imax, cpu_addr, dma_handle); + return 1; + } + + memset(cpu_addr, 0, size*imax); + for (i=0;icommand_packet_virtual_address[i] = cpu_addr; - tw_dev->command_packet_physical_address[i] = dma_handle; - memset(tw_dev->command_packet_virtual_address[i], 0, size); + tw_dev->command_packet_physical_address[i] = dma_handle+(i*size); + tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); break; case 1: - tw_dev->alignment_virtual_address[i] = cpu_addr; - tw_dev->alignment_physical_address[i] = dma_handle; - memset(tw_dev->alignment_virtual_address[i], 0, size); + tw_dev->alignment_physical_address[i] = dma_handle+(i*size); + tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); break; case 2: - tw_dev->bounce_buffer[i] = cpu_addr; - tw_dev->bounce_buffer_phys[i] = dma_handle; - memset(tw_dev->bounce_buffer[i], 0, size); + tw_dev->bounce_buffer_phys[i] = dma_handle+(i*size); + tw_dev->bounce_buffer[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); break; default: printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n"); @@ -631,11 +637,11 @@ int error, request_id; dma_addr_t dma_handle; unsigned short tw_aen_code; - unsigned long before; unsigned long flags; unsigned int data_buffer_length = 0; unsigned long data_buffer_length_adjusted = 0; unsigned long *cpu_addr; + long timeout; TW_New_Ioctl *tw_ioctl; TW_Passthru *passthru; TW_Device_Extension *tw_dev = tw_device_extension_list[MINOR(inode->i_rdev)]; @@ -735,30 +741,30 @@ tw_post_command_packet(tw_dev, request_id); spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ; + /* Now wait for the command to complete */ - before = jiffies; + tw_wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); - while (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { - /* FIXME: we need to sleep here */ - udelay(10); - if (time_after(jiffies, before + HZ *TW_IOCTL_CHRDEV_TIMEOUT)) { - /* Now we need to reset the board */ + /* Check if we timed out, got a signal, or didn't get + an interrupt */ + if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) { + /* Now we need to reset the board */ + if (timeout == -ERESTARTSYS) { + retval = timeout; + } else { printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd); - spin_lock_irqsave(&tw_dev->tw_lock, flags); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); - tw_dev->posted_request_count--; - if (tw_reset_device_extension(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no); - } - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); - if (signal_pending(current)) - retval = -EINTR; - else - retval = -EIO; - goto out2; + retval = -EIO; + } + spin_lock_irqsave(&tw_dev->tw_lock, flags); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->posted_request_count--; + if (tw_reset_device_extension(tw_dev)) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no); } + spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + goto out2; } /* Now copy in the command packet response */ @@ -886,30 +892,33 @@ else host[0] = '\0'; - switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) { - case TW_STATUS_PCI_PARITY_ERROR: + if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) { printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host); outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr); - break; - case TW_STATUS_MICROCONTROLLER_ERROR: - if (tw_dev->reset_print == 0) { - printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host); - tw_dev->reset_print = 1; - } - return 1; - case TW_STATUS_PCI_ABORT: + } + + if (status_reg_value & TW_STATUS_PCI_ABORT) { printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host); outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr); pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT); - break; - case TW_STATUS_QUEUE_ERROR: + } + + if (status_reg_value & TW_STATUS_QUEUE_ERROR) { printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host); outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr); - break; - case TW_STATUS_SBUF_WRITE_ERROR: + } + + if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host); outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr); - break; + } + + if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { + if (tw_dev->reset_print == 0) { + printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host); + tw_dev->reset_print = 1; + } + return 1; } return 0; @@ -1143,19 +1152,24 @@ tw_dev->online = 1; /* Calculate max cmds per lun, and setup queues */ - if (tw_dev->num_units > 0) { - if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { - tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units; - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_START; - tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1; - } else { - /* Use SHT cmd_per_lun here */ + if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { + tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units; + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1; + } else { + /* Check for user configured cmd_per_lun */ +#ifdef CONFIG_3W_XXXX_CMD_PER_LUN + tw_host->cmd_per_lun = CONFIG_3W_XXXX_CMD_PER_LUN; + if (tw_host->cmd_per_lun > TW_MAX_CMDS_PER_LUN) tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN; - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_START; - tw_dev->free_wrap = TW_Q_LENGTH - 1; - } +#else + /* Use SHT cmd_per_lun default */ + tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN; +#endif + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->free_wrap = TW_Q_LENGTH - 1; } /* Register the card with the kernel SCSI layer */ @@ -1184,6 +1198,8 @@ host->max_sectors = TW_MAX_SECTORS; #endif + host->select_queue_depths = tw_select_queue_depths; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) scsi_set_pci_device(host, tw_pci_dev); #endif @@ -1198,6 +1214,10 @@ if (host->hostdata) { tw_dev2 = (TW_Device_Extension *)host->hostdata; memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension)); + /* Need to init the sem/wqueue after the copy */ + init_MUTEX(&tw_dev2->ioctl_sem); + init_waitqueue_head(&tw_dev2->ioctl_wqueue); + tw_device_extension_list[tw_device_extension_count] = tw_dev2; numcards++; tw_device_extension_count = numcards; @@ -1254,22 +1274,17 @@ /* This function will free up device extension resources */ void tw_free_device_extension(TW_Device_Extension *tw_dev) { - int i; - dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n"); + /* Free command packet and generic buffer memory */ - for (i=0;icommand_packet_virtual_address[i]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector), tw_dev->command_packet_virtual_address[i], tw_dev->command_packet_physical_address[i]); + if (tw_dev->command_packet_physical_address[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Command)*TW_Q_LENGTH, tw_dev->command_packet_virtual_address[0], tw_dev->command_packet_physical_address[0]); - if (tw_dev->alignment_virtual_address[i]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector), tw_dev->alignment_virtual_address[i], tw_dev->alignment_physical_address[i]); + if (tw_dev->alignment_physical_address[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_Q_LENGTH, tw_dev->alignment_virtual_address[0], tw_dev->alignment_physical_address[0]); - } - for (i=0;ibounce_buffer[i]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_MAX_BOUNCE_SECTORS, tw_dev->bounce_buffer[i], tw_dev->bounce_buffer_phys[i]); - } + if (tw_dev->bounce_buffer[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_MAX_BOUNCE_SECTORS*TW_MAX_BOUNCEBUF, tw_dev->bounce_buffer[0], tw_dev->bounce_buffer_phys[0]); } /* End tw_free_device_extension() */ /* Clean shutdown routine */ @@ -1379,8 +1394,6 @@ tw_dev->pending_tail = TW_Q_START; spin_lock_init(&tw_dev->tw_lock); tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - init_waitqueue_head(&tw_dev->ioctl_wqueue); - init_MUTEX(&tw_dev->ioctl_sem); return 0; } /* End tw_initialize_device_extension() */ @@ -1720,6 +1733,7 @@ } } else { tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + wake_up(&tw_dev->ioctl_wqueue); } } else { switch (tw_dev->srb[request_id]->cmnd[0]) { @@ -3395,6 +3409,31 @@ return 0; } /* End tw_scsiop_test_unit_ready_complete() */ +/* This function will select queue depths for a target */ +void tw_select_queue_depths(struct Scsi_Host *host, Scsi_Device *dev) +{ + Scsi_Device *ptr; + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + + dprintk(KERN_WARNING "3w-xxxx: tw_select_queue_depths()\n"); + + for (ptr = dev; ptr != NULL; ptr = ptr->next) { + if (ptr->host == host) { + if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { + ptr->queue_depth = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units; + } else { +#ifdef CONFIG_3W_XXXX_CMD_PER_LUN + ptr->queue_depth = CONFIG_3W_XXXX_CMD_PER_LUN; + if (ptr->queue_depth > TW_MAX_CMDS_PER_LUN) + ptr->queue_depth = TW_MAX_CMDS_PER_LUN; +#else + ptr->queue_depth = TW_MAX_CMDS_PER_LUN; +#endif + } + } + } +} /* End tw_select_queue_depths() */ + /* Set a value in the features table */ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val) diff -urN linux-2.4.21-bk23/drivers/scsi/3w-xxxx.h linux-2.4.21-bk24/drivers/scsi/3w-xxxx.h --- linux-2.4.21-bk23/drivers/scsi/3w-xxxx.h 2003-06-13 07:51:36.000000000 -0700 +++ linux-2.4.21-bk24/drivers/scsi/3w-xxxx.h 2003-08-01 02:53:25.000000000 -0700 @@ -115,10 +115,10 @@ {0xd0, 0x0b, 0x00, 0x00}, // Device busy Aborted command {0xd1, 0x0b, 0x00, 0x00}, // Device busy Aborted command {0x37, 0x02, 0x04, 0x00}, // Unit offline Not ready + {0x09, 0x02, 0x04, 0x00}, // Unrecovered disk error Not ready /* Codes for older firmware */ // 3ware Error SCSI Error - {0x09, 0x0b, 0x00, 0x00}, // Unrecovered disk error Aborted command {0x51, 0x0b, 0x00, 0x00} // Unspecified Aborted command }; @@ -238,7 +238,7 @@ #define TW_ISR_DONT_COMPLETE 2 #define TW_ISR_DONT_RESULT 3 #define TW_IOCTL_TIMEOUT 25 /* 25 seconds */ -#define TW_IOCTL_CHRDEV_TIMEOUT 25 /* 25 seconds */ +#define TW_IOCTL_CHRDEV_TIMEOUT 60 /* 60 seconds */ #define TW_IOCTL_CHRDEV_FREE -1 /* Macros */ @@ -249,6 +249,30 @@ (x & TW_STATUS_MICROCONTROLLER_ERROR)) && \ (x & TW_STATUS_MICROCONTROLLER_READY)) +/* This was taken from 2.5 kernel */ +#define tw_wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + #ifdef TW_DEBUG #define dprintk(msg...) printk(msg) #else @@ -498,6 +522,7 @@ int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id); +void tw_select_queue_depths(struct Scsi_Host *host, Scsi_Device *dev); int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val); int tw_setup_irq(TW_Device_Extension *tw_dev); diff -urN linux-2.4.21-bk23/fs/jfs/super.c linux-2.4.21-bk24/fs/jfs/super.c --- linux-2.4.21-bk23/fs/jfs/super.c 2003-06-13 07:51:37.000000000 -0700 +++ linux-2.4.21-bk24/fs/jfs/super.c 2003-08-01 02:53:26.000000000 -0700 @@ -337,6 +337,7 @@ if (!(sb->s_flags & MS_RDONLY)) { txQuiesce(sb); lmLogShutdown(log); + updateSuper(sb, FM_CLEAN); } } @@ -347,6 +348,7 @@ int rc = 0; if (!(sb->s_flags & MS_RDONLY)) { + updateSuper(sb, FM_MOUNT); if ((rc = lmLogInit(log))) jfs_err("jfs_unlock failed with return code %d", rc); else diff -urN linux-2.4.21-bk23/fs/nfs/nfsroot.c linux-2.4.21-bk24/fs/nfs/nfsroot.c --- linux-2.4.21-bk23/fs/nfs/nfsroot.c 2003-06-13 07:51:37.000000000 -0700 +++ linux-2.4.21-bk24/fs/nfs/nfsroot.c 2003-08-01 02:53:26.000000000 -0700 @@ -305,7 +305,7 @@ */ int __init nfs_root_setup(char *line) { - ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); + ROOT_DEV = MKDEV(NFS_MAJOR, NFS_MINOR); if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) { strncpy(nfs_root_name, line, sizeof(nfs_root_name)); nfs_root_name[sizeof(nfs_root_name)-1] = '\0'; diff -urN linux-2.4.21-bk23/fs/proc/base.c linux-2.4.21-bk24/fs/proc/base.c --- linux-2.4.21-bk23/fs/proc/base.c 2003-06-13 07:51:37.000000000 -0700 +++ linux-2.4.21-bk24/fs/proc/base.c 2003-08-01 02:53:26.000000000 -0700 @@ -124,20 +124,56 @@ return result; } +#define MAY_PTRACE(task) \ + (task == current || \ + (task->p_pptr == current && \ + (task->ptrace & PT_PTRACED) && task->state == TASK_STOPPED)) + +static int may_ptrace_attach(struct task_struct *task) +{ + int retval = 0; + + task_lock(task); + + if (((current->uid != task->euid) || + (current->uid != task->suid) || + (current->uid != task->uid) || + (current->gid != task->egid) || + (current->gid != task->sgid) || + (!cap_issubset(task->cap_permitted, current->cap_permitted)) || + (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) + goto out; + rmb(); + if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE)) + goto out; + + retval = 1; + +out: + task_unlock(task); + return retval; +} + static int proc_pid_environ(struct task_struct *task, char * buffer) { struct mm_struct *mm; int res = 0; + + if (!may_ptrace_attach(task)) + return -ESRCH; + task_lock(task); mm = task->mm; if (mm) atomic_inc(&mm->mm_users); task_unlock(task); if (mm) { - int len = mm->env_end - mm->env_start; + unsigned int len = mm->env_end - mm->env_start; if (len > PAGE_SIZE) len = PAGE_SIZE; res = access_process_vm(task, mm->env_start, buffer, len, 0); + if (!may_ptrace_attach(task)) + res = -ESRCH; mmput(mm); } return res; @@ -328,10 +364,6 @@ read: proc_info_read, }; -#define MAY_PTRACE(p) \ -(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED)) - - static int mem_open(struct inode* inode, struct file* file) { file->private_data = (void*)((long)current->self_exec_id); @@ -347,8 +379,7 @@ int copied = 0; struct mm_struct *mm; - - if (!MAY_PTRACE(task)) + if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) return -ESRCH; page = (char *)__get_free_page(GFP_USER); @@ -370,14 +401,13 @@ copied = -EIO; goto out_free; } - while (count > 0) { int this_len, retval; this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; retval = access_process_vm(task, src, page, this_len, 0); - if (!retval) { + if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) { if (!copied) copied = -EIO; break; @@ -411,7 +441,7 @@ struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; unsigned long dst = *ppos; - if (!MAY_PTRACE(task)) + if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) return -ESRCH; page = (char *)__get_free_page(GFP_USER); diff -urN linux-2.4.21-bk23/fs/proc/proc_misc.c linux-2.4.21-bk24/fs/proc/proc_misc.c --- linux-2.4.21-bk23/fs/proc/proc_misc.c 2003-06-13 07:51:37.000000000 -0700 +++ linux-2.4.21-bk24/fs/proc/proc_misc.c 2003-08-01 02:53:26.000000000 -0700 @@ -423,9 +423,9 @@ int count, int *eof, void *data) { extern char saved_command_line[]; - int len; + int len = 0; - len = snprintf(page, count, "%s\n", saved_command_line); + proc_sprintf(page, &off, &len, "%s\n", saved_command_line); return proc_calc_metrics(page, start, off, count, eof, len); } @@ -495,7 +495,8 @@ buf++; p++; count--; read++; } pnt = (char *)prof_buffer + p - sizeof(unsigned int); - copy_to_user(buf,(void *)pnt,count); + if (copy_to_user(buf,(void *)pnt,count)) + return -EFAULT; read += count; *ppos += read; return read; diff -urN linux-2.4.21-bk23/fs/reiserfs/super.c linux-2.4.21-bk24/fs/reiserfs/super.c --- linux-2.4.21-bk23/fs/reiserfs/super.c 2003-08-01 02:53:21.000000000 -0700 +++ linux-2.4.21-bk24/fs/reiserfs/super.c 2003-08-01 02:53:26.000000000 -0700 @@ -284,7 +284,7 @@ } /* body of "save" link */ - link = cpu_to_le32 (INODE_PKEY (inode)->k_dir_id); + link = INODE_PKEY (inode)->k_dir_id; /* put "save" link inot tree */ retval = reiserfs_insert_item (th, &path, &key, &ih, (char *)&link); diff -urN linux-2.4.21-bk23/include/asm-i386/hw_irq.h linux-2.4.21-bk24/include/asm-i386/hw_irq.h --- linux-2.4.21-bk23/include/asm-i386/hw_irq.h 2001-11-22 11:46:18.000000000 -0800 +++ linux-2.4.21-bk24/include/asm-i386/hw_irq.h 2003-08-01 02:53:26.000000000 -0700 @@ -13,8 +13,10 @@ */ #include +#include #include #include +#include /* * IDT vectors usable for external interrupt sources start @@ -213,7 +215,7 @@ atomic_inc((atomic_t *)&prof_buffer[eip]); } -#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */ +#if defined(CONFIG_X86_IO_APIC) static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { if (IO_APIC_IRQ(i)) send_IPI_self(IO_APIC_VECTOR(i)); diff -urN linux-2.4.21-bk23/include/linux/nfs.h linux-2.4.21-bk24/include/linux/nfs.h --- linux-2.4.21-bk23/include/linux/nfs.h 2000-04-01 08:04:27.000000000 -0800 +++ linux-2.4.21-bk24/include/linux/nfs.h 2003-08-01 02:53:26.000000000 -0700 @@ -30,6 +30,9 @@ #define NFS_MNT_PROGRAM 100005 #define NFS_MNT_PORT 627 +#define NFS_MAJOR UNNAMED_MAJOR +#define NFS_MINOR 0xff + /* * NFS stats. The good thing with these values is that NFSv3 errors are * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which diff -urN linux-2.4.21-bk23/include/linux/sunrpc/xprt.h linux-2.4.21-bk24/include/linux/sunrpc/xprt.h --- linux-2.4.21-bk23/include/linux/sunrpc/xprt.h 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/include/linux/sunrpc/xprt.h 2003-08-01 02:53:27.000000000 -0700 @@ -98,6 +98,10 @@ struct list_head rq_list; + struct xdr_buf rq_private_buf; /* The receive buffer + * used in the softirq. + */ + /* * For authentication (e.g. auth_des) */ diff -urN linux-2.4.21-bk23/init/do_mounts.c linux-2.4.21-bk24/init/do_mounts.c --- linux-2.4.21-bk23/init/do_mounts.c 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/init/do_mounts.c 2003-08-01 02:53:27.000000000 -0700 @@ -88,7 +88,7 @@ const char *name; const int num; } root_dev_names[] __initdata = { - { "nfs", 0x00ff }, + { "nfs", MKDEV(NFS_MAJOR, NFS_MINOR) }, { "hda", 0x0300 }, { "hdb", 0x0340 }, { "loop", 0x0700 }, @@ -759,7 +759,8 @@ static void __init mount_root(void) { #ifdef CONFIG_ROOT_NFS - if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { + if (MAJOR(ROOT_DEV) == NFS_MAJOR + && MINOR(ROOT_DEV) == NFS_MINOR) { if (mount_nfs_root()) { sys_chdir("/root"); ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; diff -urN linux-2.4.21-bk23/kernel/sysctl.c linux-2.4.21-bk24/kernel/sysctl.c --- linux-2.4.21-bk23/kernel/sysctl.c 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/kernel/sysctl.c 2003-08-01 02:53:27.000000000 -0700 @@ -474,7 +474,8 @@ * zero, proceed with automatic r/w */ if (table->data && table->maxlen) { if (oldval && oldlenp) { - get_user(len, oldlenp); + if (get_user(len, oldlenp)) + return -EFAULT; if (len) { if (len > table->maxlen) len = table->maxlen; @@ -765,7 +766,7 @@ len = 0; p = buffer; while (len < *lenp) { - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (c == 0 || c == '\n') break; @@ -848,7 +849,7 @@ if (write) { while (left) { char c; - if(get_user(c,(char *) buffer)) + if (get_user(c, (char *) buffer)) return -EFAULT; if (!isspace(c)) break; @@ -914,7 +915,7 @@ p = (char *) buffer; while (left) { char c; - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (!isspace(c)) break; @@ -1001,7 +1002,7 @@ if (write) { while (left) { char c; - if(get_user(c, (char *) buffer)) + if (get_user(c, (char *) buffer)) return -EFAULT; if (!isspace(c)) break; @@ -1060,7 +1061,7 @@ p = (char *) buffer; while (left) { char c; - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (!isspace(c)) break; @@ -1102,7 +1103,7 @@ if (write) { while (left) { char c; - if(get_user(c, (char *) buffer)) + if (get_user(c, (char *) buffer)) return -EFAULT; if (!isspace(c)) break; @@ -1165,7 +1166,7 @@ p = (char *) buffer; while (left) { char c; - if(get_user(c, p++)) + if (get_user(c, p++)) return -EFAULT; if (!isspace(c)) break; @@ -1319,7 +1320,7 @@ return -ENOTDIR; if (oldval && oldlenp) { - if(get_user(len, oldlenp)) + if (get_user(len, oldlenp)) return -EFAULT; if (len) { l = strlen(table->data); @@ -1376,7 +1377,8 @@ for (i = 0; i < length; i++) { int value; - get_user(value, vec + i); + if (get_user(value, vec + i)) + return -EFAULT; if (min && value < min[i]) return -EINVAL; if (max && value > max[i]) diff -urN linux-2.4.21-bk23/net/ipv4/ipconfig.c linux-2.4.21-bk24/net/ipv4/ipconfig.c --- linux-2.4.21-bk23/net/ipv4/ipconfig.c 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/net/ipv4/ipconfig.c 2003-08-01 02:53:27.000000000 -0700 @@ -1234,7 +1234,7 @@ * -- Chip */ #ifdef CONFIG_ROOT_NFS - if (ROOT_DEV == MKDEV(UNNAMED_MAJOR, 255)) { + if (ROOT_DEV == MKDEV(NFS_MAJOR, NFS_MINOR)) { printk(KERN_ERR "IP-Config: Retrying forever (NFS root)...\n"); goto try_try_again; diff -urN linux-2.4.21-bk23/net/sunrpc/clnt.c linux-2.4.21-bk24/net/sunrpc/clnt.c --- linux-2.4.21-bk23/net/sunrpc/clnt.c 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/net/sunrpc/clnt.c 2003-08-01 02:53:27.000000000 -0700 @@ -646,7 +646,8 @@ struct rpc_rqst *req = task->tk_rqstp; int status; - if (req->rq_received != 0) + smp_rmb(); + if (req->rq_received > 0 && !req->rq_bytes_sent) task->tk_status = req->rq_received; dprintk("RPC: %4d call_status (status %d)\n", @@ -754,17 +755,23 @@ if (!clnt->cl_softrtry) { task->tk_action = call_transmit; clnt->cl_stats->rpcretrans++; - } else { - printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n", - clnt->cl_protname, task->tk_status); - rpc_exit(task, -EIO); + goto out_retry; } + printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n", + clnt->cl_protname, task->tk_status); + rpc_exit(task, -EIO); return; } + /* Check that the softirq receive buffer is valid */ + if (unlikely(memcmp(&req->rq_rcv_buf, &req->rq_private_buf, + sizeof(req->rq_rcv_buf)) != 0)) + printk(KERN_WARNING "%s: receive buffer is inconsistent. Please contact maintainer.\n", + __FUNCTION__); + /* Verify the RPC header */ if (!(p = call_verify(task))) - return; + goto out_retry; /* * The following is an NFS-specific hack to cater for setuid @@ -777,7 +784,7 @@ task->tk_flags ^= RPC_CALL_REALUID; task->tk_action = call_encode; task->tk_suid_retry--; - return; + goto out_retry; } } @@ -787,6 +794,10 @@ task->tk_status = decode(req, p, task->tk_msg.rpc_resp); dprintk("RPC: %4d call_decode result %d\n", task->tk_pid, task->tk_status); + return; +out_retry: + req->rq_received = 0; + task->tk_status = 0; } /* diff -urN linux-2.4.21-bk23/net/sunrpc/xdr.c linux-2.4.21-bk24/net/sunrpc/xdr.c --- linux-2.4.21-bk23/net/sunrpc/xdr.c 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/net/sunrpc/xdr.c 2003-08-01 02:53:27.000000000 -0700 @@ -180,7 +180,8 @@ { struct iovec *iov = iov_base; struct page **ppage = xdr->pages; - unsigned int len, pglen = xdr->page_len, first_kmap; + struct page **first_kmap = NULL; + unsigned int len, pglen = xdr->page_len; len = xdr->head[0].iov_len; if (base < len) { @@ -203,16 +204,15 @@ ppage += base >> PAGE_CACHE_SHIFT; base &= ~PAGE_CACHE_MASK; } - first_kmap = 1; do { len = PAGE_CACHE_SIZE; - if (first_kmap) { - first_kmap = 0; + if (!first_kmap) { + first_kmap = ppage; iov->iov_base = kmap(*ppage); } else { iov->iov_base = kmap_nonblock(*ppage); if (!iov->iov_base) - goto out; + goto out_err; } if (base) { iov->iov_base += base; @@ -233,6 +233,10 @@ } out: return (iov - iov_base); +out_err: + for (; first_kmap != ppage; first_kmap++) + kunmap(*first_kmap); + return 0; } void xdr_kunmap(struct xdr_buf *xdr, unsigned int base, int niov) diff -urN linux-2.4.21-bk23/net/sunrpc/xprt.c linux-2.4.21-bk24/net/sunrpc/xprt.c --- linux-2.4.21-bk23/net/sunrpc/xprt.c 2003-08-01 02:53:22.000000000 -0700 +++ linux-2.4.21-bk24/net/sunrpc/xprt.c 2003-08-01 02:53:27.000000000 -0700 @@ -237,6 +237,10 @@ unsigned int slen_part, n; niov = xdr_kmap(niv, xdr, skip); + if (!niov) { + result = -EAGAIN; + break; + } msg.msg_flags = MSG_DONTWAIT|MSG_NOSIGNAL; msg.msg_iov = niv; @@ -726,11 +730,11 @@ xprt_pktdump("packet data:", (u32 *) (skb->h.raw+sizeof(struct udphdr)), repsize); - if ((copied = rovr->rq_rlen) > repsize) + if ((copied = rovr->rq_private_buf.len) > repsize) copied = repsize; /* Suck it into the iovec, verify checksum if not done by hw. */ - if (csum_partial_copy_to_xdr(&rovr->rq_rcv_buf, skb)) + if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb)) goto out_unlock; /* Something worked... */ @@ -852,7 +856,7 @@ return; } - rcvbuf = &req->rq_rcv_buf; + rcvbuf = &req->rq_private_buf; len = desc->count; if (len > xprt->tcp_reclen - xprt->tcp_offset) { skb_reader_t my_desc; @@ -870,7 +874,7 @@ xprt->tcp_copied += len; xprt->tcp_offset += len; - if (xprt->tcp_copied == req->rq_rlen) + if (xprt->tcp_copied == req->rq_private_buf.len) xprt->tcp_flags &= ~XPRT_COPY_DATA; else if (xprt->tcp_offset == xprt->tcp_reclen) { if (xprt->tcp_flags & XPRT_LAST_FRAG) @@ -1102,6 +1106,9 @@ } spin_lock_bh(&xprt->sock_lock); + if (req->rq_received != 0 && !req->rq_bytes_sent) + goto out_notrans; + if (!__xprt_lock_write(xprt, task)) goto out_notrans; @@ -1111,8 +1118,10 @@ } if (list_empty(&req->rq_list)) { + /* Update the softirq receive buffer */ + memcpy(&req->rq_private_buf, &req->rq_rcv_buf, + sizeof(req->rq_private_buf)); list_add_tail(&req->rq_list, &xprt->recv); - req->rq_received = 0; } spin_unlock_bh(&xprt->sock_lock); @@ -1145,8 +1154,12 @@ if (xprt->stream) { req->rq_bytes_sent += status; - if (req->rq_bytes_sent >= req->rq_slen) + /* If we've sent the entire packet, immediately + * reset the count of bytes sent. */ + if (req->rq_bytes_sent >= req->rq_slen) { + req->rq_bytes_sent = 0; goto out_receive; + } } else { if (status >= req->rq_slen) goto out_receive; @@ -1168,9 +1181,6 @@ * Note, though, that we can't do this if we've already started * resending down a TCP stream. */ - if (req->rq_received && !req->rq_bytes_sent) - goto out_release; - task->tk_status = status; switch (status) { @@ -1200,7 +1210,6 @@ if (xprt->stream) xprt_disconnect(xprt); } - out_release: xprt_release_write(xprt, task); return; out_receive: