Commit bb7b9e76 authored by Patrick Mansfield's avatar Patrick Mansfield Committed by James Bottomley

dynamic device info flag entries

This patch allows scsi device flags like those in the current scsi_scan.c
device_list to be added via the command line or via /proc/scsi/device_info.

It also allows a default flag to be set via the command line.

This should allow for the (eventual) removal of the current device_list.

Example boot command line arguments:

scsi_default_dev_flags=0x1 scsi_dev_flags="IBM:LN V1.2Rack:0x200"

The above means that a SCSI device with vendor "IBM     ", model
(product) "LN V1.2Rack     " will get a flag of 0x200 during scanning,
meaning it should be treated like a SCSI-3 device for scanning. All
other devices without an entry would get the default flag value of 1,
so they would not be scanned past LUN 0 (the same behaviour as 
max_scsi_luns = 1).

I left the old device list and BLIST defines in scsi_scan.c.

I could not get lilo to allow two spaces, so I could not use this
with my device that has model "ST318203LC    !#". I didn't try grub.
parent df860b3d
This diff is collapsed.
...@@ -475,6 +475,7 @@ extern int scsi_dev_init(void); ...@@ -475,6 +475,7 @@ extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int); extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
extern int scsi_attach_device(struct scsi_device *); extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *); extern void scsi_detach_device(struct scsi_device *);
extern int scsi_get_device_flags(unsigned char *vendor, unsigned char *model);
/* /*
* Newer request-based interfaces. * Newer request-based interfaces.
...@@ -513,6 +514,29 @@ extern int print_msg(const unsigned char *); ...@@ -513,6 +514,29 @@ extern int print_msg(const unsigned char *);
extern const char *scsi_sense_key_string(unsigned char); extern const char *scsi_sense_key_string(unsigned char);
extern const char *scsi_extd_sense_format(unsigned char, unsigned char); extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
/*
* dev_info: for the black/white list in the old scsi_static_device_list
*/
struct dev_info {
char *vendor;
char *model;
char *revision; /* revision known to be bad, unused */
unsigned flags;
};
extern struct dev_info scsi_static_device_list[] __initdata;
/*
* scsi_dev_info_list: structure to hold black/white listed devices.
*/
struct scsi_dev_info_list {
struct list_head dev_info_list;
char vendor[8];
char model[16];
unsigned flags;
unsigned compatible; /* for use with scsi_static_device_list entries */
};
/* /*
* The scsi_device struct contains what we know about each given scsi * The scsi_device struct contains what we know about each given scsi
* device. * device.
......
...@@ -54,18 +54,16 @@ ...@@ -54,18 +54,16 @@
#define BLIST_INQUIRY_36 0x400 /* override additional length field */ #define BLIST_INQUIRY_36 0x400 /* override additional length field */
#define BLIST_INQUIRY_58 0x800 /* ... for broken inquiry responses */ #define BLIST_INQUIRY_58 0x800 /* ... for broken inquiry responses */
struct dev_info {
const char *vendor;
const char *model;
const char *revision; /* revision known to be bad, unused */
unsigned flags;
};
/* /*
* device_list: devices that require settings that differ from the * scsi_static_device_list: deprecated list of devices that require
* default, includes black-listed (broken) devices. * settings that differ from the default, includes black-listed (broken)
* devices. The entries here are added to the tail of scsi_dev_info_list
* via scsi_dev_info_list_init.
*
* Do not add to this list, use the command line or proc interface to add
* to the scsi_dev_info_list. This table will eventually go away.
*/ */
static struct dev_info device_list[] = { struct dev_info scsi_static_device_list[] __initdata = {
/* /*
* The following devices are known not to tolerate a lun != 0 scan * The following devices are known not to tolerate a lun != 0 scan
* for one reason or another. Some will respond to all luns, * for one reason or another. Some will respond to all luns,
...@@ -183,6 +181,7 @@ static struct dev_info device_list[] = { ...@@ -183,6 +181,7 @@ static struct dev_info device_list[] = {
{"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN}, {"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN},
{"HP", "C1557A", NULL, BLIST_FORCELUN}, {"HP", "C1557A", NULL, BLIST_FORCELUN},
{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
{ NULL, NULL, NULL, 0 },
}; };
#define ALLOC_FAILURE_MSG KERN_ERR "%s: Allocation failure during" \ #define ALLOC_FAILURE_MSG KERN_ERR "%s: Allocation failure during" \
...@@ -426,62 +425,6 @@ static void print_inquiry(unsigned char *inq_result) ...@@ -426,62 +425,6 @@ static void print_inquiry(unsigned char *inq_result)
printk("\n"); printk("\n");
} }
/**
* get_device_flags - get device specific flags from the device_list
* @vendor: vendor name
* @model: model name
*
* Description:
* Search device_list for an entry matching @vendor and @model, if
* found, return the matching flags value, else return 0.
* Partial matches count as success - good for @model, but maybe not
* @vendor.
**/
static int get_device_flags(unsigned char *vendor, unsigned char *model)
{
int i;
size_t max;
for (i = 0; i < ARRAY_SIZE(device_list); i++) {
/*
* XXX why skip leading spaces? If an odd INQUIRY value,
* that should have been part of the device_list[] entry,
* such as " FOO" rather than "FOO". Since this code is
* already here, and we don't know what device it is
* trying to work with, leave it as-is.
*/
max = 8; /* max length of vendor */
while ((max > 0) && *vendor == ' ') {
max--;
vendor++;
}
/*
* XXX removing the following strlen() would be good,
* using it means that for a an entry not in the list, we
* scan every byte of every vendor listed in
* device_list[], and never match a single one (and still
* have to compare at least the first byte of each
* vendor).
*/
if (memcmp(device_list[i].vendor, vendor,
min(max, strlen(device_list[i].vendor))))
continue;
/*
* Skip spaces again.
*/
max = 16; /* max length of model */
while ((max > 0) && *model == ' ') {
max--;
model++;
}
if (memcmp(device_list[i].model, model,
min(max, strlen(device_list[i].model))))
continue;
return device_list[i].flags;
}
return 0;
}
/** /**
* scsi_initialize_merge_fn() -ƣinitialize merge function for a host * scsi_initialize_merge_fn() -ƣinitialize merge function for a host
* @sd: host descriptor * @sd: host descriptor
...@@ -1092,12 +1035,12 @@ int scsi_get_default_name(Scsi_Device *sdev) ...@@ -1092,12 +1035,12 @@ int scsi_get_default_name(Scsi_Device *sdev)
* Notes: * Notes:
* If a device returns the same serial number for different LUNs or * If a device returns the same serial number for different LUNs or
* even for different LUNs on different devices, special handling must * even for different LUNs on different devices, special handling must
* be added to get an id, or a new black list flag must to added and * be added to get an id, or a new black list flag must be added (so
* used in device_list[] (so we use the default name, or add a way to * we use the default name, or add a way to prefix the id/name with
* prefix the id/name with SCSI_UID_UNKNOWN - and change the define to * SCSI_UID_UNKNOWN - and change the define to something meaningful
* something meaningful like SCSI_UID_NOT_UNIQUE). Complete user level * like SCSI_UID_NOT_UNIQUE). Complete user level scanning would be
* scanning would be nice for such devices, so we do not need device * nice for such devices, so we do not need device specific code in
* specific code in the kernel. * the kernel.
**/ **/
static void scsi_load_identifier(Scsi_Device *sdev, Scsi_Request *sreq) static void scsi_load_identifier(Scsi_Device *sdev, Scsi_Request *sreq)
{ {
...@@ -1176,7 +1119,7 @@ static int scsi_find_scsi_level(unsigned int channel, unsigned int id, ...@@ -1176,7 +1119,7 @@ static int scsi_find_scsi_level(unsigned int channel, unsigned int id,
* If the INQUIRY is successful, sreq->sr_result is zero and: the * If the INQUIRY is successful, sreq->sr_result is zero and: the
* INQUIRY data is in @inq_result; the scsi_level and INQUIRY length * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length
* are copied to the Scsi_Device at @sreq->sr_device (sdev); * are copied to the Scsi_Device at @sreq->sr_device (sdev);
* any device_list flags value is stored in *@bflags. * any flags value is stored in *@bflags.
**/ **/
static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result, static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
int *bflags) int *bflags)
...@@ -1225,7 +1168,7 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result, ...@@ -1225,7 +1168,7 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
* argument. * argument.
*/ */
BUG_ON(bflags == NULL); BUG_ON(bflags == NULL);
*bflags = get_device_flags(&inq_result[8], &inq_result[16]); *bflags = scsi_get_device_flags(&inq_result[8], &inq_result[16]);
possible_inq_resp_len = (unsigned char) inq_result[4] + 5; possible_inq_resp_len = (unsigned char) inq_result[4] + 5;
if (BLIST_INQUIRY_36 & *bflags) if (BLIST_INQUIRY_36 & *bflags)
...@@ -1306,7 +1249,7 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result, ...@@ -1306,7 +1249,7 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
* @sdevnew: store the address of the newly allocated Scsi_Device * @sdevnew: store the address of the newly allocated Scsi_Device
* @sreq: scsi request used when getting an identifier * @sreq: scsi request used when getting an identifier
* @inq_result: holds the result of a previous INQUIRY to the LUN * @inq_result: holds the result of a previous INQUIRY to the LUN
* @bflags: flags value from device_list * @bflags: black/white list flag
* *
* Description: * Description:
* Allocate and initialize a Scsi_Device matching sdevscan. Optionally * Allocate and initialize a Scsi_Device matching sdevscan. Optionally
...@@ -1606,7 +1549,7 @@ static int scsi_probe_and_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew, ...@@ -1606,7 +1549,7 @@ static int scsi_probe_and_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
/** /**
* scsi_sequential_lun_scan - sequentially scan a SCSI target * scsi_sequential_lun_scan - sequentially scan a SCSI target
* @sdevscan: scan the host, channel, and id of this Scsi_Device * @sdevscan: scan the host, channel, and id of this Scsi_Device
* @bflags: flags from device_list for LUN 0 * @bflags: black/white list flag for LUN 0
* @lun0_res: result of scanning LUN 0 * @lun0_res: result of scanning LUN 0
* *
* Description: * Description:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment