mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Where did this patch come from?
@ 2001-04-27 16:07 peck, william
  0 siblings, 0 replies; only message in thread
From: peck, william @ 2001-04-27 16:07 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 314 bytes --]

I was wondering if anyone could tell me who is responsible for the patch I
have included?  It fixes some issues with scanning the scsi bus,
specifically it reports luns higher than 8.  I am just wondering if whoever
has created this if they have submitted it to be included in the mainstream
2.2.x kernel series.


[-- Attachment #2: patch-scsi-2.2.16-22.16 --]
[-- Type: application/octet-stream, Size: 13060 bytes --]

Index: drivers/scsi/scsi.c
===================================================================
RCS file: /home/cvs/em_rh/drivers/scsi/scsi.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 scsi.c
--- drivers/scsi/scsi.c	2001/02/26 01:30:44	1.1.1.1
+++ drivers/scsi/scsi.c	2001/02/28 02:20:52
@@ -186,9 +186,13 @@
 static void resize_dma_pool(void);
 static void print_inquiry(unsigned char *data);
 extern void scsi_times_out (Scsi_Cmnd * SCpnt);
-static int  scan_scsis_single (int channel,int dev,int lun,int * max_scsi_dev ,
-                 int * sparse_lun, Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt,
-                 struct Scsi_Host *shpnt, char * scsi_result);
+static int scan_scsis_single(unsigned int channel, unsigned int dev,
+		unsigned int lun, int lun0_scsi_level, 
+		unsigned int *max_scsi_dev, unsigned int *sparse_lun, 
+		Scsi_Device ** SDpnt, struct Scsi_Host *shpnt, 
+		char *scsi_result);
+static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,
+				struct Scsi_Host *shpnt);
 void        scsi_build_commandblocks(Scsi_Device * SDpnt);
 static int scsi_unregister_device(struct Scsi_Device_Template * tpnt);
 
@@ -440,8 +444,10 @@
     }
 }
 
+#define MAX_SCSI_LUNS 0x7FFFFFFF
+
 #ifdef CONFIG_SCSI_MULTI_LUN
-static int max_scsi_luns = 64;
+static int max_scsi_luns = MAX_SCSI_LUNS;
 #else
 static int max_scsi_luns = 1;
 #endif
@@ -449,7 +455,7 @@
 __initfunc(void scsi_luns_setup(char *str, int *ints))
 {
     if (ints[0] != 1)
-	printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 8)\n");
+	printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 2^32-1)\n");
     else
 	max_scsi_luns = ints[1];
 }
@@ -468,15 +474,16 @@
                         unchar hlun)
 {
   int             channel;
-  int             dev;
-  int             lun;
-  int             max_dev_lun;
+  unsigned int    dev;
+  unsigned int    lun;
+  unsigned int    max_dev_lun;
   Scsi_Cmnd     * SCpnt;
   unsigned char * scsi_result;
   unsigned char   scsi_result0[256];
   Scsi_Device   * SDpnt;
   Scsi_Device   * SDtail;
-  int             sparse_lun;
+  unsigned int    sparse_lun;
+  int lun0_sl;
 
   scsi_result = NULL;
   SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), 
@@ -539,8 +546,13 @@
     if(dev >= shpnt->max_id) goto leave;
     lun = hlun;
     if(lun >= shpnt->max_lun) goto leave;
-    scan_scsis_single (channel, dev, lun, &max_dev_lun, &sparse_lun,
-		       &SDpnt, SCpnt, shpnt, scsi_result);
+
+    if ((0 == lun) || (lun > 7))
+        lun0_sl = SCSI_3; /* actually don't care for 0 == lun */
+    else
+        lun0_sl = find_lun0_scsi_level(channel, dev, shpnt);
+    scan_scsis_single(channel, dev, lun, lun0_sl, &max_dev_lun, 
+                      &sparse_lun, &SDpnt, shpnt, scsi_result);
 
     /* See warning by (DB) in scsi_proc_info() towards end of
        'add-single-device' section. (dpg) */
@@ -596,14 +608,33 @@
            */
           max_dev_lun = (max_scsi_luns < shpnt->max_lun ?
                          max_scsi_luns : shpnt->max_lun);
-	  sparse_lun = 0;
-          for (lun = 0; lun < max_dev_lun; ++lun) {
-            if (!scan_scsis_single (channel, order_dev, lun, &max_dev_lun,
-				    &sparse_lun, &SDpnt, SCpnt, shpnt,
-				    scsi_result)
-		&& !sparse_lun)
-              break; /* break means don't probe further for luns!=0 */
-          }                     /* for lun ends */
+
+#ifdef CONFIG_SCSI_MULTI_LUN
+	  if ((shpnt->max_id > 16) && (shpnt->max_lun > 16)) {
+                /* This is the first step of supporting large numbers
+                 * of luns on a device.  By definition any SCSU host capable
+                 * of supporting more than 16 SCSI controlers with more than
+		 * 16 luns will probably be a fiber channel or similar device
+		 * and use a sparse lun setup.  If the future this is the
+                 * place to do a report lun call.
+                 */
+                sparse_lun = 1;
+          } else {
+                sparse_lun = 0;
+          }
+#else
+          sparse_lun = 0;
+#endif
+
+          for (lun = 0, lun0_sl = SCSI_2; lun < max_dev_lun; ++lun) {
+              if (!scan_scsis_single(channel, order_dev, lun, lun0_sl,
+                                     &max_dev_lun, &sparse_lun, &SDpnt, shpnt,
+                                     scsi_result)
+                      && !sparse_lun)
+                  break;	/* break means don't probe further for luns!=0 */
+              if (SDpnt && (0 == lun))
+                lun0_sl = SDpnt->scsi_level;
+          }             	/* for lun ends */
         }                       /* if this_id != id ends */
       }                         /* for dev ends */
     }                           /* for channel ends */
@@ -665,18 +696,43 @@
     }
 }
 
+Scsi_Cmnd *scsi_allocate_request(Scsi_Device * device)
+{
+  Scsi_Cmnd *SCpnt = NULL;
+
+  if (!device)
+    panic("No device passed to scsi_allocate_request().\n");
+
+  SCpnt = (Scsi_Cmnd *) kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
+
+  if (SCpnt == NULL)
+    return NULL;
+
+  memset(SCpnt, 0, sizeof(Scsi_Cmnd));
+  SCpnt->host = device->host;
+  SCpnt->device = device;
+  SCpnt->target = device->id;
+  SCpnt->lun = device->lun;
+  SCpnt->channel = device->channel;
+
+  return SCpnt;
+}
+
 /*
  * The worker for scan_scsis.
  * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
  * Global variables used : scsi_devices(linked list)
  */
-int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,
-    int *sparse_lun, Scsi_Device **SDpnt2, Scsi_Cmnd * SCpnt,
-    struct Scsi_Host * shpnt, char *scsi_result)
+static int scan_scsis_single(unsigned int channel, unsigned int dev,
+                             unsigned int lun, int lun0_scsi_level,
+                             unsigned int *max_dev_lun, unsigned int *sparse_lun, 
+                             Scsi_Device ** SDpnt2, struct Scsi_Host *shpnt, 
+                             char *scsi_result)
 {
   unsigned char scsi_cmd[12];
   struct Scsi_Device_Template *sdtpnt;
   Scsi_Device * SDtail, *SDpnt=*SDpnt2;
+  Scsi_Cmnd * SCpnt;
   int bflags, type=-1;
 
   SDpnt->host = shpnt;
@@ -695,46 +751,10 @@
   SDpnt->borken = 1;
   SDpnt->was_reset = 0;
   SDpnt->expecting_cc_ua = 0;
-
-  scsi_cmd[0] = TEST_UNIT_READY;
-  scsi_cmd[1] = lun << 5;
-  scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0;
-
-  SCpnt->host = SDpnt->host;
-  SCpnt->device = SDpnt;
-  SCpnt->target = SDpnt->id;
-  SCpnt->lun = SDpnt->lun;
-  SCpnt->channel = SDpnt->channel;
-  {
-    struct semaphore sem = MUTEX_LOCKED;
-    SCpnt->request.sem = &sem;
-    SCpnt->request.rq_status = RQ_SCSI_BUSY;
-    spin_lock_irq(&io_request_lock);
-    scsi_do_cmd (SCpnt, (void *) scsi_cmd,
-                 (void *) scsi_result,
-                 256, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
-    spin_unlock_irq(&io_request_lock);
-    down (&sem);
-    SCpnt->request.sem = NULL;
-  }
 
-  SCSI_LOG_SCAN_BUS(3,  printk ("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n",
-          dev, lun, SCpnt->result));
-  SCSI_LOG_SCAN_BUS(3,print_driverbyte(SCpnt->result));
-  SCSI_LOG_SCAN_BUS(3,print_hostbyte(SCpnt->result));
-  SCSI_LOG_SCAN_BUS(3,printk("\n"));
-
-  if (SCpnt->result && status_byte(SCpnt->result) != RESERVATION_CONFLICT) {
-    if (((driver_byte (SCpnt->result) & DRIVER_SENSE) ||
-         (status_byte (SCpnt->result) & CHECK_CONDITION)) &&
-        ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
-      if (((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) &&
-          ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION) &&
-          ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0))
-        return 1;
-    }
-    else
-      return 0;
+  if (NULL == (SCpnt = scsi_allocate_request(SDpnt))) {
+    printk("scan_scsis_single: no memory\n");
+    return 0;
   }
 
   SCSI_LOG_SCAN_BUS(3,printk ("scsi: performing INQUIRY\n"));
@@ -742,7 +762,11 @@
    * Build an INQUIRY command block.
    */
   scsi_cmd[0] = INQUIRY;
-  scsi_cmd[1] = (lun << 5) & 0xe0;
+  if ((lun > 0) && (lun0_scsi_level <= SCSI_2))
+    scsi_cmd[1] = (lun << 5) & 0xe0;
+  else	
+    scsi_cmd[1] = 0;	/* SCSI_3 and higher, don't touch */
+
   scsi_cmd[2] = 0;
   scsi_cmd[3] = 0;
   scsi_cmd[4] = 255;
@@ -764,15 +788,17 @@
   SCSI_LOG_SCAN_BUS(3,printk ("scsi: INQUIRY %s with code 0x%x\n",
                               SCpnt->result ? "failed" : "successful", SCpnt->result));
 
-  if (SCpnt->result)
+  if (SCpnt->result) {
+    kfree(SCpnt);
     return 0;     /* assume no peripheral if any sort of error */
-
+  }
   /*
    * Check the peripheral qualifier field - this tells us whether LUNS
    * are supported here or not.
    */
   if( (scsi_result[0] >> 5) == 3 )
     {
+      kfree(SCpnt);
       return 0;     /* assume no peripheral if any sort of error */
     }
 
@@ -896,7 +922,11 @@
     printk ("Unlocked floptical drive.\n");
     SDpnt->lockable = 0;
     scsi_cmd[0] = MODE_SENSE;
-    scsi_cmd[1] = (lun << 5) & 0xe0;
+    if (shpnt->max_lun <= 8)
+      scsi_cmd[1] = (lun << 5) & 0xe0;
+    else
+      scsi_cmd[1] = 0;	/* any other idea? */
+
     scsi_cmd[2] = 0x2e;
     scsi_cmd[3] = 0;
     scsi_cmd[4] = 0x2a;
@@ -932,6 +962,7 @@
   if (!SDpnt)
   {
       printk ("scsi: scan_scsis_single: Cannot malloc\n");
+      kfree(SCpnt);
       return 0;
   }
 
@@ -963,15 +994,30 @@
   /*
    * Some scsi devices cannot be polled for lun != 0 due to firmware bugs
    */
-  if (bflags & BLIST_NOLUN)
+  if (bflags & BLIST_NOLUN) {
+    kfree(SCpnt);
     return 0;                   /* break; */
+  }
 
   /*
    * If this device is known to support sparse multiple units, override the
    * other settings, and scan all of them.
    */
   if (bflags & BLIST_SPARSELUN) {
-    *max_dev_lun = 8;
+    /*
+     * Scanning MAX_SCSI_LUNS units would be a bad idea.
+     * Any better idea?
+     * I think we need REPORT LUNS in future to avoid scanning
+     * of unused LUNs. But, that is another item.
+     *
+     * FIXME(eric) - perhaps this should be a kernel configurable?
+     */
+    if (*max_dev_lun < shpnt->max_lun)
+      *max_dev_lun = shpnt->max_lun;
+    else if ((max_scsi_luns >> 1) >= *max_dev_lun)
+      *max_dev_lun += shpnt->max_lun;
+    else
+      *max_dev_lun = max_scsi_luns;
     *sparse_lun = 1;
     return 1;
   }
@@ -981,7 +1027,18 @@
    * settings, and scan all of them.
    */
   if (bflags & BLIST_FORCELUN) {
-    *max_dev_lun = 8;
+    /* 
+     * Scanning MAX_SCSI_LUNS units would be a bad idea.
+     * Any better idea?
+     * I think we need REPORT LUNS in future to avoid scanning
+     * of unused LUNs. But, that is another item.
+     */
+    if (*max_dev_lun < shpnt->max_lun)
+      *max_dev_lun = shpnt->max_lun;
+    else if ((max_scsi_luns >> 1) >= *max_dev_lun)
+      *max_dev_lun += shpnt->max_lun;
+    else
+      *max_dev_lun = max_scsi_luns;
     return 1;
   }
 
@@ -1001,9 +1058,32 @@
   if (((scsi_result[2] & 0x07) == 0)
       ||
       ((scsi_result[2] & 0x07) == 1 &&
-       (scsi_result[3] & 0x0f) == 0))
+       (scsi_result[3] & 0x0f) == 0)) {
+    kfree(SCpnt);
     return 0;
+  }
   return 1;
+}
+
+/*
+ * The worker for scan_scsis.
+ * Returns the scsi_level of lun0 on this host, channel and dev (if already
+ * known), otherwise returns SCSI_2.
+ */
+static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,
+				struct Scsi_Host *shpnt)
+{
+  int res = SCSI_2;
+  Scsi_Device *SDpnt;
+
+  for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next)
+    {
+      if ((0 == SDpnt->lun) && (dev == SDpnt->id) &&
+          (channel == SDpnt->channel))
+        return (int)SDpnt->scsi_level;
+    }
+  /* haven't found lun0, should send INQUIRY but take easy route */
+  return res;
 }
 
 /*
Index: drivers/scsi/scsi.h
===================================================================
RCS file: /home/cvs/em_rh/drivers/scsi/scsi.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 scsi.h
--- drivers/scsi/scsi.h	2001/02/26 01:30:44	1.1.1.1
+++ drivers/scsi/scsi.h	2001/02/28 01:54:05
@@ -431,7 +431,8 @@
     Scsi_Cmnd          * device_queue;    /* queue of SCSI Command structures */
 
 /* public: */
-    unsigned char id, lun, channel;
+    unsigned int lun;
+    unsigned char id, channel;
 
     unsigned int manufacturer;      /* Manufacturer of device, for using 
 				     * vendor-specific cmd's */
@@ -541,8 +542,8 @@
     
 /* public: */
 
+    unsigned int       lun;
     unsigned char      target;
-    unsigned char      lun;
     unsigned char      channel;
     unsigned char      cmd_len;
     unsigned char      old_cmd_len;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2001-04-27 16:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-04-27 16:07 Where did this patch come from? peck, william

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®