------_=_NextPart_000_01C0CF34.179629E0
Content-Type: text/plain;
charset="iso-8859-1"
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.
------_=_NextPart_000_01C0CF34.179629E0
Content-Type: application/octet-stream;
name="patch-scsi-2.2.16-22.16"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="patch-scsi-2.2.16-22.16"
Index: drivers/scsi/scsi.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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,=20
+ unsigned int *max_scsi_dev, unsigned int *sparse_lun,=20
+ Scsi_Device ** SDpnt, struct Scsi_Host *shpnt,=20
+ 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);
=20
@@ -440,8 +444,10 @@
}
}
=20
+#define MAX_SCSI_LUNS 0x7FFFFFFF
+
#ifdef CONFIG_SCSI_MULTI_LUN
-static int max_scsi_luns =3D 64;
+static int max_scsi_luns =3D MAX_SCSI_LUNS;
#else
static int max_scsi_luns =3D 1;
#endif
@@ -449,7 +455,7 @@
__initfunc(void scsi_luns_setup(char *str, int *ints))
{
if (ints[0] !=3D 1)
- printk("scsi_luns_setup : usage max_scsi_luns=3Dn (n should be =
between 1 and 8)\n");
+ printk("scsi_luns_setup : usage max_scsi_luns=3Dn (n should be =
between 1 and 2^32-1)\n");
else
max_scsi_luns =3D 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;
=20
scsi_result =3D NULL;
SCpnt =3D (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd),=20
@@ -539,8 +546,13 @@
if(dev >=3D shpnt->max_id) goto leave;
lun =3D hlun;
if(lun >=3D shpnt->max_lun) goto leave;
- scan_scsis_single (channel, dev, lun, &max_dev_lun, &sparse_lun,
- &SDpnt, SCpnt, shpnt, scsi_result);
+
+ if ((0 =3D=3D lun) || (lun > 7))
+ lun0_sl =3D SCSI_3; /* actually don't care for 0 =3D=3D lun */
+ else
+ lun0_sl =3D find_lun0_scsi_level(channel, dev, shpnt);
+ scan_scsis_single(channel, dev, lun, lun0_sl, &max_dev_lun,=20
+ &sparse_lun, &SDpnt, shpnt, scsi_result);
=20
/* See warning by (DB) in scsi_proc_info() towards end of
'add-single-device' section. (dpg) */
@@ -596,14 +608,33 @@
*/
max_dev_lun =3D (max_scsi_luns < shpnt->max_lun ?
max_scsi_luns : shpnt->max_lun);
- sparse_lun =3D 0;
- for (lun =3D 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!=3D0 =
*/
- } /* 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 =3D 1;
+ } else {
+ sparse_lun =3D 0;
+ }
+#else
+ sparse_lun =3D 0;
+#endif
+
+ for (lun =3D 0, lun0_sl =3D 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!=3D0 */
+ if (SDpnt && (0 =3D=3D lun))
+ lun0_sl =3D SDpnt->scsi_level;
+ } /* for lun ends */
} /* if this_id !=3D id ends */
} /* for dev ends */
} /* for channel ends */
@@ -665,18 +696,43 @@
}
}
=20
+Scsi_Cmnd *scsi_allocate_request(Scsi_Device * device)
+{
+ Scsi_Cmnd *SCpnt =3D NULL;
+
+ if (!device)
+ panic("No device passed to scsi_allocate_request().\n");
+
+ SCpnt =3D (Scsi_Cmnd *) kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
+
+ if (SCpnt =3D=3D NULL)
+ return NULL;
+
+ memset(SCpnt, 0, sizeof(Scsi_Cmnd));
+ SCpnt->host =3D device->host;
+ SCpnt->device =3D device;
+ SCpnt->target =3D device->id;
+ SCpnt->lun =3D device->lun;
+ SCpnt->channel =3D device->channel;
+
+ return SCpnt;
+}
+
/*
* The worker for scan_scsis.
* Returning 0 means Please don't ask further for lun!=3D0, 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,=20
+ Scsi_Device ** SDpnt2, struct Scsi_Host =
*shpnt,=20
+ char *scsi_result)
{
unsigned char scsi_cmd[12];
struct Scsi_Device_Template *sdtpnt;
Scsi_Device * SDtail, *SDpnt=3D*SDpnt2;
+ Scsi_Cmnd * SCpnt;
int bflags, type=3D-1;
=20
SDpnt->host =3D shpnt;
@@ -695,46 +751,10 @@
SDpnt->borken =3D 1;
SDpnt->was_reset =3D 0;
SDpnt->expecting_cc_ua =3D 0;
-
- scsi_cmd[0] =3D TEST_UNIT_READY;
- scsi_cmd[1] =3D lun << 5;
- scsi_cmd[2] =3D scsi_cmd[3] =3D scsi_cmd[4] =3D scsi_cmd[5] =3D 0;
-
- SCpnt->host =3D SDpnt->host;
- SCpnt->device =3D SDpnt;
- SCpnt->target =3D SDpnt->id;
- SCpnt->lun =3D SDpnt->lun;
- SCpnt->channel =3D SDpnt->channel;
- {
- struct semaphore sem =3D MUTEX_LOCKED;
- SCpnt->request.sem =3D &sem;
- SCpnt->request.rq_status =3D 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 =3D NULL;
- }
=20
- 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) !=3D =
RESERVATION_CONFLICT) {
- if (((driver_byte (SCpnt->result) & DRIVER_SENSE) ||
- (status_byte (SCpnt->result) & CHECK_CONDITION)) &&
- ((SCpnt->sense_buffer[0] & 0x70) >> 4) =3D=3D 7) {
- if (((SCpnt->sense_buffer[2] & 0xf) !=3D NOT_READY) &&
- ((SCpnt->sense_buffer[2] & 0xf) !=3D UNIT_ATTENTION) &&
- ((SCpnt->sense_buffer[2] & 0xf) !=3D ILLEGAL_REQUEST || lun =
> 0))
- return 1;
- }
- else
- return 0;
+ if (NULL =3D=3D (SCpnt =3D scsi_allocate_request(SDpnt))) {
+ printk("scan_scsis_single: no memory\n");
+ return 0;
}
=20
SCSI_LOG_SCAN_BUS(3,printk ("scsi: performing INQUIRY\n"));
@@ -742,7 +762,11 @@
* Build an INQUIRY command block.
*/
scsi_cmd[0] =3D INQUIRY;
- scsi_cmd[1] =3D (lun << 5) & 0xe0;
+ if ((lun > 0) && (lun0_scsi_level <=3D SCSI_2))
+ scsi_cmd[1] =3D (lun << 5) & 0xe0;
+ else=09
+ scsi_cmd[1] =3D 0; /* SCSI_3 and higher, don't touch */
+
scsi_cmd[2] =3D 0;
scsi_cmd[3] =3D 0;
scsi_cmd[4] =3D 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));
=20
- 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) =3D=3D 3 )
{
+ kfree(SCpnt);
return 0; /* assume no peripheral if any sort of error */
}
=20
@@ -896,7 +922,11 @@
printk ("Unlocked floptical drive.\n");
SDpnt->lockable =3D 0;
scsi_cmd[0] =3D MODE_SENSE;
- scsi_cmd[1] =3D (lun << 5) & 0xe0;
+ if (shpnt->max_lun <=3D 8)
+ scsi_cmd[1] =3D (lun << 5) & 0xe0;
+ else
+ scsi_cmd[1] =3D 0; /* any other idea? */
+
scsi_cmd[2] =3D 0x2e;
scsi_cmd[3] =3D 0;
scsi_cmd[4] =3D 0x2a;
@@ -932,6 +962,7 @@
if (!SDpnt)
{
printk ("scsi: scan_scsis_single: Cannot malloc\n");
+ kfree(SCpnt);
return 0;
}
=20
@@ -963,15 +994,30 @@
/*
* Some scsi devices cannot be polled for lun !=3D 0 due to firmware =
bugs
*/
- if (bflags & BLIST_NOLUN)
+ if (bflags & BLIST_NOLUN) {
+ kfree(SCpnt);
return 0; /* break; */
+ }
=20
/*
* 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 =3D 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 =3D shpnt->max_lun;
+ else if ((max_scsi_luns >> 1) >=3D *max_dev_lun)
+ *max_dev_lun +=3D shpnt->max_lun;
+ else
+ *max_dev_lun =3D max_scsi_luns;
*sparse_lun =3D 1;
return 1;
}
@@ -981,7 +1027,18 @@
* settings, and scan all of them.
*/
if (bflags & BLIST_FORCELUN) {
- *max_dev_lun =3D 8;
+ /*=20
+ * 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 =3D shpnt->max_lun;
+ else if ((max_scsi_luns >> 1) >=3D *max_dev_lun)
+ *max_dev_lun +=3D shpnt->max_lun;
+ else
+ *max_dev_lun =3D max_scsi_luns;
return 1;
}
=20
@@ -1001,9 +1058,32 @@
if (((scsi_result[2] & 0x07) =3D=3D 0)
||
((scsi_result[2] & 0x07) =3D=3D 1 &&
- (scsi_result[3] & 0x0f) =3D=3D 0))
+ (scsi_result[3] & 0x0f) =3D=3D 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 =3D SCSI_2;
+ Scsi_Device *SDpnt;
+
+ for (SDpnt =3D shpnt->host_queue; SDpnt; SDpnt =3D SDpnt->next)
+ {
+ if ((0 =3D=3D SDpnt->lun) && (dev =3D=3D SDpnt->id) &&
+ (channel =3D=3D SDpnt->channel))
+ return (int)SDpnt->scsi_level;
+ }
+ /* haven't found lun0, should send INQUIRY but take easy route */
+ return res;
}
=20
/*
Index: drivers/scsi/scsi.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
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 */
=20
/* public: */
- unsigned char id, lun, channel;
+ unsigned int lun;
+ unsigned char id, channel;
=20
unsigned int manufacturer; /* Manufacturer of device, for =
using=20
* vendor-specific cmd's */
@@ -541,8 +542,8 @@
=20
/* public: */
=20
+ unsigned int lun;
unsigned char target;
- unsigned char lun;
unsigned char channel;
unsigned char cmd_len;
unsigned char old_cmd_len;
------_=_NextPart_000_01C0CF34.179629E0--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/