* 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®