Hi

Hopefully somebody on this list can give me a quick answer. The message
below has some details, but I was curious as to why the "new way" calls
scsi_detect routines with IRQs off and the "old way" leaves IRQs
enabled.
I would have thought the opposite and that leaving IRQs enabled
would be prefered.

thanks

larry

-------- Original Message --------
Subject: Re: NMI timeout too low for 3Ware controller
Date: Wed, 07 Feb 2001 10:11:05 -0500
From: Larry Sendlosky <[EMAIL PROTECTED]>
Organization: Storigen Systems
To: Alan Cox <[EMAIL PROTECTED]>
CC: [EMAIL PROTECTED]
References: <[EMAIL PROTECTED]>

Alan,

After doing some cleanup I shaved about 0.07 secs off the scsi detect
code, but it still takes longer than 1 second to do it, ~1.07 seconds.

So I think I cheated by initing 'use_new_eh_code' to 0 and then setting
it to 1 at the end of the driver's scsi detect code. However, I do have
a question regarding 'use_new_eh_code' because I'm not familiar with the
history. Wouldn't "new code" tend to be more sophisticated and be able
to
init the scsi controller with system IRQs enabled instead of disabled?

Anyway, attached are my changes which include the "make it more
efficient
stuff". I also left code enabled that printk's the start and end time of
the driver's scsi detect for use when debugging. If you accept the
changes, you may want to #if 0 them. They're not under TW_DEBUG because
TW_DEBUG is too verbose and affects timing.

Cheers and keep up the good work,

larry


PS: 3ware folks: New changes in Linux implement a "watchdog" timer of
1second.
    As you can see from above, the driver takes longer than 1 second to
    to do a "scsi detect" which causes the watchdog timer to halt
thesystem.
    The only change that "has to" be made concerns
scsi_template->use_new_eh_code.
     

Alan Cox wrote:
> 
> > I have a 3Ware controller that takes more than a second
> > to initialize at startup. New (2.4.0-ac5+ and tux2 kernels)
> 
> If it is holding off interrupts for over a second please fix the 3ware
> driver instead. Looking at the code I can see no difference in the code they
> run at insmod or built in boot time

-- 
--------------------------------------------------------------------------
  Larry Sendlosky                           
[EMAIL PROTECTED]
  Storigen Systems                                    (978) 323-4454
x261
--------------------------------------------------------------------------
--- 3w-xxxx.h.orig      Tue Feb  6 15:46:21 2001
+++ 3w-xxxx.h   Wed Feb  7 09:37:30 2001
@@ -52,11 +52,13 @@
 #ifndef _3W_XXXX_H
 #define _3W_XXXX_H
 
-
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 
+#define TW_ALLOCATE_VM
+#define TW_NEW_POLL_STATUS
+
 /* Control register bit definitions */
 #define TW_CONTROL_CLEAR_HOST_INTERRUPT               0x00080000
 #define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT   0x00040000
@@ -297,8 +299,11 @@
 int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id);
 int tw_aen_drain_queue(TW_Device_Extension *tw_dev);
 int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
+#ifndef TW_ALLOCATE_VM
 int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, int 
which);
-int tw_check_bits(u32 status_reg_value);
+#else
+int tw_allocate_vm(TW_Device_Extension *tw_dev);
+#endif
 int tw_check_errors(TW_Device_Extension *tw_dev);
 void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev);
 void tw_clear_host_interrupt(TW_Device_Extension *tw_dev);
@@ -368,7 +373,33 @@
        present : 0,                                    \
        unchecked_isa_dma : 0,                          \
        use_clustering : ENABLE_CLUSTERING,             \
-       use_new_eh_code : 1,                            \
+       use_new_eh_code : 0,                            \
        emulated : 1                                    \
 }
+
+
+/* This function will check the status register for unexpected bits */
+static __inline__ int tw_check_bits(u32 status_reg_value)
+{
+#ifdef TW_DEBUG
+       if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) { 
+ 
+               dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits 
+(0x%x).\n", status_reg_value);
+               return 1;
+       }
+       if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
+               dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits 
+(0x%x).\n", status_reg_value);
+               return 1;
+       }
+#else
+
+       if (((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) 
+||
+           ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0))
+               return 1;
+
+#endif
+       return 0;
+} /* End tw_check_bits() */
+
+
+
 #endif /* _3W_XXXX_H */
--- 3w-xxxx.c.orig      Tue Feb  6 15:46:13 2001
+++ 3w-xxxx.c   Wed Feb  7 09:01:23 2001
@@ -232,7 +232,9 @@
     
                /* Now poll for completion */
                for (i=0;i<imax;i++) {
-                       mdelay(10);
+
+                       udelay(10);
+
                        status_reg_value = inl(status_reg_addr);
                        if (tw_check_bits(status_reg_value)) {
                                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): 
Unexpected bits.\n");
@@ -410,7 +412,55 @@
        return 0;
 } /* End tw_aen_read_queue() */
 
+
+#ifdef TW_ALLOCATE_VM
+
+/* Allocate all necessary VM all at once */
+
+int tw_allocate_vm(TW_Device_Extension *tw_dev)
+{
+       int i;
+       char *cmd_virt_addr, *align_virt_addr;
+
+       int size = ((sizeof(TW_Sector) + (TW_ALIGNMENT - 1)) & ~(TW_ALIGNMENT - 1));
+
+       /* Make sure VM chunk can be handled by kmalloc (I know, a hack) */
+       if (size * TW_Q_LENGTH > 128 * 1024)
+               return -ENOMEM;
+
+       cmd_virt_addr = (char *)kmalloc(size * TW_Q_LENGTH, GFP_ATOMIC);
+       if (!cmd_virt_addr)
+               return -ENOMEM;
+
+       align_virt_addr = (char *)kmalloc(size * TW_Q_LENGTH, GFP_ATOMIC);
+       if (!align_virt_addr)
+               return -ENOMEM;
+
+       /* Zero chunks */
+       memset(cmd_virt_addr, 0, size * TW_Q_LENGTH);
+       memset(align_virt_addr, 0, size * TW_Q_LENGTH);
+
+
+       /* Carve chunk of VM into TW_Q_LENGTH packets */
+       for (i = 0; i < TW_Q_LENGTH; i++) {
+
+               tw_dev->command_packet_virtual_address[i] = (u32 *)cmd_virt_addr;
+               tw_dev->command_packet_physical_address[i] = 
+virt_to_bus(cmd_virt_addr);
+
+               tw_dev->alignment_virtual_address[i] = (u32 *)align_virt_addr;
+               tw_dev->alignment_physical_address[i] = virt_to_bus(align_virt_addr);
+
+               cmd_virt_addr = (char *)((long)cmd_virt_addr + (long)size);
+               align_virt_addr = (char *)((long)align_virt_addr + (long)size);
+       }
+
+       return 0;
+}
+
+#else
+
 /* This function will allocate memory and check if it is 16 d-word aligned */
+
 int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, int 
which)
 {
        u32 *virt_addr = kmalloc(size, GFP_ATOMIC);
@@ -439,21 +489,7 @@
        return 0;
 } /* End tw_allocate_memory() */
 
-/* This function will check the status register for unexpected bits */
-int tw_check_bits(u32 status_reg_value)
-{
-       if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) { 
 
-               printk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits 
(0x%x).\n", status_reg_value);
-               return 1;
-       }
-       if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits 
(0x%x).\n", status_reg_value);
-               return 1;
-       }
-
-       return 0;
-} /* End tw_check_bits() */
-
+#endif
 /* This function will report controller error status */
 int tw_check_errors(TW_Device_Extension *tw_dev) 
 {
@@ -592,7 +628,6 @@
                        printk(KERN_WARNING "3w-xxxx: tw_findcards(): kmalloc() failed 
for card %d.\n", numcards);
                        continue;
                }
-               memset(tw_dev, 0, sizeof(TW_Device_Extension));
 
                error = tw_initialize_device_extension(tw_dev);
                if (error) {
@@ -632,7 +667,6 @@
                                tries++;
                                continue;
                        }
-
                        /* Check for controller errors */
                        if (tw_check_errors(tw_dev)) {
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): 
Controller errors found, soft resetting card %d.\n", numcards);
@@ -727,8 +761,6 @@
                        continue;
                }
     
-               /* Re-enable interrupts on the card */
-               tw_enable_interrupts(tw_dev2);
 
                /* Now setup the interrupt handler */
                error = tw_setup_irq(tw_dev2);
@@ -749,6 +781,10 @@
 
                /* Tell the firmware we support shutdown notification*/
                tw_setfeature(tw_dev2, 2, 1, &c);
+
+               /* Re-enable interrupts on the card */
+               tw_enable_interrupts(tw_dev2);
+
        }
 
        if (numcards == 0) 
@@ -762,18 +798,32 @@
 /* This function will free up device extension resources */
 void tw_free_device_extension(TW_Device_Extension *tw_dev)
 {
-       int i, imax;
-       imax = TW_Q_LENGTH;
 
        dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
+
        /* Free command packet and generic buffer memory */
-       for (i=0;i<imax;i++) {
-               if (tw_dev->command_packet_virtual_address[i]) 
-                       kfree(tw_dev->command_packet_virtual_address[i]);
 
-               if (tw_dev->alignment_virtual_address[i])
-                       kfree(tw_dev->alignment_virtual_address[i]);
+#ifdef TW_ALLOCATE_VM
+
+       kfree(tw_dev->command_packet_virtual_address[0]);
+       kfree(tw_dev->alignment_virtual_address[0]);
+
+#else
+       {
+               int i, imax;
+               imax = TW_Q_LENGTH;
+
+               for (i=0;i<imax;i++) {
+                       if (tw_dev->command_packet_virtual_address[i]) 
+                               kfree(tw_dev->command_packet_virtual_address[i]);
+                       
+                       if (tw_dev->alignment_virtual_address[i])
+                               kfree(tw_dev->alignment_virtual_address[i]);
+               }
        }
+
+#endif
+
 } /* End tw_free_device_extension() */
 
 /* Clean shutdown routine */
@@ -838,7 +888,9 @@
        /* Poll for completion */
        imax = TW_POLL_MAX_RETRIES;
        for (i=0;i<imax;i++) {
-               mdelay(10);
+
+               udelay(10);
+
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
                        printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected 
bits.\n");
@@ -869,52 +921,26 @@
        int i, imax;
 
        dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");
+
+       memset(tw_dev, 0, sizeof(TW_Device_Extension));
+
        imax = TW_Q_LENGTH;
 
+       if ((i = tw_allocate_vm(tw_dev)) != 0) return i;
+
        for (i=0; i<imax; i++) {
                /* Initialize command packet buffers */
-               tw_allocate_memory(tw_dev, i, sizeof(TW_Sector), 0);
-               if (tw_dev->command_packet_virtual_address[i] == NULL) {
-                       printk(KERN_WARNING "3w-xxxx: 
tw_initialize_device_extension(): Bad command packet virtual address.\n");
-                       return 1;
-               }
-               memset(tw_dev->command_packet_virtual_address[i], 0, 
sizeof(TW_Sector));
-    
-               /* Initialize generic buffer */
-               tw_allocate_memory(tw_dev, i, sizeof(TW_Sector), 1);
-               if (tw_dev->alignment_virtual_address[i] == NULL) {
-                       printk(KERN_WARNING "3w-xxxx: 
tw_initialize_device_extension(): Bad alignment virtual address.\n");
-                       return 1;
-               }
-               memset(tw_dev->alignment_virtual_address[i], 0, sizeof(TW_Sector));
-
                tw_dev->free_queue[i] = i;
                tw_dev->state[i] = TW_S_INITIAL;
-               tw_dev->ioctl_size[i] = 0;
-               tw_dev->aen_queue[i] = 0;
        }
 
-       for (i=0;i<TW_MAX_UNITS;i++)
-               tw_dev->is_unit_present[i] = 0;
 
-       tw_dev->num_units = 0;
-       tw_dev->num_aborts = 0;
-       tw_dev->num_resets = 0;
        tw_dev->free_head = TW_Q_START;
        tw_dev->free_tail = TW_Q_LENGTH - 1;
-       tw_dev->posted_request_count = 0;
-       tw_dev->max_posted_request_count = 0;
-       tw_dev->max_sgl_entries = 0;
-       tw_dev->sgl_entries = 0;
-       tw_dev->host = NULL;
        tw_dev->pending_head = TW_Q_START;
        tw_dev->pending_tail = TW_Q_START;
-       tw_dev->aen_head = 0;
-       tw_dev->aen_tail = 0;
-       tw_dev->sector_count = 0;
-       tw_dev->max_sector_count = 0;
        spin_lock_init(&tw_dev->tw_lock);
-       tw_dev->flags = 0;
+
        return 0;
 } /* End tw_initialize_device_extension() */
 
@@ -986,7 +1012,9 @@
        /* Poll for completion */
        imax = TW_POLL_MAX_RETRIES;
        for(i=0; i<imax; i++) {
-               mdelay(10);
+
+               udelay(10);
+
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): 
Unexpected bits.\n");
@@ -1253,6 +1281,7 @@
        memset(param, 0, sizeof(TW_Sector));
 
        dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d 
parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id, 
ioctl->parameter_size_bytes);
+
        opcode = ioctl->opcode;
 
        switch (opcode) {
@@ -1380,14 +1409,44 @@
        outl(control_reg_value, control_reg_addr);
 } /* End tw_mask_command_interrupt() */
 
+#ifdef TW_NEW_POLL_STATUS
+
 /* This function will poll the status register for a flag */
 int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
 {
        u32 status_reg_addr, status_reg_value;
+
+       const ulong ucount = 1000/10 ;    /* 1/10th millisecond delay */
+       ulong count = seconds * 1000 * (1000 / ucount);
+
+       status_reg_addr = tw_dev->registers.status_reg_addr;
+
+        /* Check for flag set every "x" microseconds  until limit reached */
+       do {
+               status_reg_value = inl(status_reg_addr);
+               if ((status_reg_value & flag) == flag)
+                       return 0;
+
+               udelay(ucount);
+
+       } while (--count > 0);
+
+       printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
+       return 1;
+}
+
+#else
+
+/* This function will poll the status register for a flag */
+int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
+{
+       u32 status_reg_addr, status_reg_value;
+
        struct timeval before, timeout;
 
        status_reg_addr = tw_dev->registers.status_reg_addr;
        do_gettimeofday(&before);
+
        status_reg_value = inl(status_reg_addr);
 
        while ((status_reg_value & flag) != flag) {
@@ -1402,6 +1461,8 @@
        return 0;
 } /* End tw_poll_status() */
 
+#endif
+
 /* This function will attempt to post a command packet to the board */
 int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
 {
@@ -1573,9 +1634,9 @@
 /* This function will find and initialize any cards */
 int tw_scsi_detect(Scsi_Host_Template *tw_host)
 {
-
+       int num_cards;
 #if 1
-       int status;
+
        union {
                uint64_t ll;
                uint32_t low;
@@ -1591,7 +1652,6 @@
        printk(KERN_NOTICE "3w-xxxx: scsi_detect enter -> tv_sec:  %d tv_usec: %d\n",
               xlong1.low, xlong2.low);
 #endif
-
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n");
 
        /* Check if the kernel has PCI interface compiled in */
@@ -1600,19 +1660,19 @@
                return 0;
        }
 
+       num_cards = tw_findcards(tw_host);
+       if (num_cards != 0) tw_host->use_new_eh_code = 1;
+
 #if 1
-       status = tw_findcards(tw_host);
        do_gettimeofday(&after);
        xlong1.ll = after.tv_sec;
        xlong2.ll = after.tv_usec;
 
        printk(KERN_NOTICE "3w-xxxx: scsi_detect exit -> tv_sec:  %d tv_usec: %d\n",
               xlong1.low, xlong2.low);
-       return status;
-#else
-
-       return(tw_findcards(tw_host));
 #endif
+       return num_cards;
+
 } /* End tw_scsi_detect() */
 
 /* This is the new scsi eh abort function */
@@ -2272,7 +2332,9 @@
        /* Poll for completion */
        imax = TW_POLL_MAX_RETRIES;
        for (i=0;i<imax;i++) {
-               mdelay(10);
+
+               udelay(10);
+
                status_reg_value = inl(status_reg_addr);
                if (tw_check_bits(status_reg_value)) {
                        printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected 
bits.\n");

Reply via email to