Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <linux/blkdev.h>
0004 #include <linux/init.h>
0005 #include <linux/kernel.h>
0006 #include <linux/module.h>
0007 #include <linux/moduleparam.h>
0008 #include <linux/proc_fs.h>
0009 #include <linux/seq_file.h>
0010 #include <linux/slab.h>
0011 
0012 #include <scsi/scsi_device.h>
0013 #include <scsi/scsi_devinfo.h>
0014 
0015 #include "scsi_priv.h"
0016 
0017 
0018 /*
0019  * scsi_dev_info_list: structure to hold black/white listed devices.
0020  */
0021 struct scsi_dev_info_list {
0022     struct list_head dev_info_list;
0023     char vendor[8];
0024     char model[16];
0025     blist_flags_t flags;
0026     unsigned compatible; /* for use with scsi_static_device_list entries */
0027 };
0028 
0029 struct scsi_dev_info_list_table {
0030     struct list_head node;  /* our node for being on the master list */
0031     struct list_head scsi_dev_info_list; /* head of dev info list */
0032     const char *name;   /* name of list for /proc (NULL for global) */
0033     int key;        /* unique numeric identifier */
0034 };
0035 
0036 
0037 static blist_flags_t scsi_default_dev_flags;
0038 static LIST_HEAD(scsi_dev_info_list);
0039 static char scsi_dev_flags[256];
0040 
0041 /*
0042  * scsi_static_device_list: deprecated list of devices that require
0043  * settings that differ from the default, includes black-listed (broken)
0044  * devices. The entries here are added to the tail of scsi_dev_info_list
0045  * via scsi_dev_info_list_init.
0046  *
0047  * Do not add to this list, use the command line or proc interface to add
0048  * to the scsi_dev_info_list. This table will eventually go away.
0049  */
0050 static struct {
0051     char *vendor;
0052     char *model;
0053     char *revision; /* revision known to be bad, unused */
0054     blist_flags_t flags;
0055 } scsi_static_device_list[] __initdata = {
0056     /*
0057      * The following devices are known not to tolerate a lun != 0 scan
0058      * for one reason or another. Some will respond to all luns,
0059      * others will lock up.
0060      */
0061     {"Aashima", "IMAGERY 2400SP", "1.03", BLIST_NOLUN}, /* locks up */
0062     {"CHINON", "CD-ROM CDS-431", "H42", BLIST_NOLUN},   /* locks up */
0063     {"CHINON", "CD-ROM CDS-535", "Q14", BLIST_NOLUN},   /* locks up */
0064     {"DENON", "DRD-25X", "V", BLIST_NOLUN},         /* locks up */
0065     {"HITACHI", "DK312C", "CM81", BLIST_NOLUN}, /* responds to all lun */
0066     {"HITACHI", "DK314C", "CR21", BLIST_NOLUN}, /* responds to all lun */
0067     {"IBM", "2104-DU3", NULL, BLIST_NOLUN},     /* locks up */
0068     {"IBM", "2104-TU3", NULL, BLIST_NOLUN},     /* locks up */
0069     {"IMS", "CDD521/10", "2.06", BLIST_NOLUN},  /* locks up */
0070     {"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN}, /* locks up */
0071     {"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN}, /* locks up */
0072     {"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN},   /* locks up */
0073     {"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* locks up */
0074     {"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* locks up */
0075     {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN},    /* responds to all lun */
0076     {"MICROTEK", "ScanMakerIII", "2.30", BLIST_NOLUN},  /* responds to all lun */
0077     {"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN},/* locks up */
0078     {"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN},    /* responds to all lun */
0079     {"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* locks up */
0080     {"SUN", "SENA", NULL, BLIST_NOLUN},     /* responds to all luns */
0081     /*
0082      * The following causes a failed REQUEST SENSE on lun 1 for
0083      * aha152x controller, which causes SCSI code to reset bus.
0084      */
0085     {"SANYO", "CRD-250S", "1.20", BLIST_NOLUN},
0086     /*
0087      * The following causes a failed REQUEST SENSE on lun 1 for
0088      * aha152x controller, which causes SCSI code to reset bus.
0089      */
0090     {"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN},
0091     {"SEAGATE", "ST296", "921", BLIST_NOLUN},   /* responds to all lun */
0092     {"SEAGATE", "ST1581", "6538", BLIST_NOLUN}, /* responds to all lun */
0093     {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN},
0094     {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN},
0095     {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN},
0096     {"SONY", "CD-ROM CDU-8012", NULL, BLIST_NOLUN},
0097     {"SONY", "SDT-5000", "3.17", BLIST_SELECT_NO_ATN},
0098     {"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN},   /* locks up */
0099     {"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN},   /* locks up */
0100     /*
0101      * The following causes a failed REQUEST SENSE on lun 1 for
0102      * seagate controller, which causes SCSI code to reset bus.
0103      */
0104     {"TEAC", "CD-ROM", "1.06", BLIST_NOLUN},
0105     {"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN},    /* responds to all lun */
0106     /*
0107      * The following causes a failed REQUEST SENSE on lun 1 for
0108      * seagate controller, which causes SCSI code to reset bus.
0109      */
0110     {"HP", "C1750A", "3226", BLIST_NOLUN},      /* scanjet iic */
0111     {"HP", "C1790A", NULL, BLIST_NOLUN},        /* scanjet iip */
0112     {"HP", "C2500A", NULL, BLIST_NOLUN},        /* scanjet iicx */
0113     {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* locks up */
0114     {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN},  /* responds to all lun */
0115     {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */
0116     {"NEC", "D3856", "0009", BLIST_NOLUN},
0117     {"QUANTUM", "LPS525S", "3110", BLIST_NOLUN},    /* locks up */
0118     {"QUANTUM", "PD1225S", "3110", BLIST_NOLUN},    /* locks up */
0119     {"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN},    /* locks up */
0120     {"RELISYS", "Scorpio", NULL, BLIST_NOLUN},  /* responds to all lun */
0121     {"SANKYO", "CP525", "6.64", BLIST_NOLUN},   /* causes failed REQ SENSE, extra reset */
0122     {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN | BLIST_BORKEN},
0123     {"transtec", "T5008", "0001", BLIST_NOREPORTLUN },
0124     {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN},  /* locks up */
0125     {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},  /* locks up */
0126     {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */
0127     {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN},    /* locks up */
0128     {"", "Scanner", "1.80", BLIST_NOLUN},   /* responds to all lun */
0129 
0130     /*
0131      * Other types of devices that have special flags.
0132      * Note that all USB devices should have the BLIST_INQUIRY_36 flag.
0133      */
0134     {"3PARdata", "VV", NULL, BLIST_REPORTLUN2},
0135     {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN},
0136     {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN},
0137     {"AIX", "VDASD", NULL, BLIST_TRY_VPD_PAGES},
0138     {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
0139     {"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN | BLIST_INQUIRY_36},
0140     {"BROWNIE", "1200U3P", NULL, BLIST_NOREPORTLUN},
0141     {"BROWNIE", "1600U3P", NULL, BLIST_NOREPORTLUN},
0142     {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN},
0143     {"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN | BLIST_INQUIRY_36},
0144     {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */
0145     {"CNSI", "G7324", NULL, BLIST_SPARSELUN},   /* Chaparral G7324 RAID */
0146     {"CNSi", "G8324", NULL, BLIST_SPARSELUN},   /* Chaparral G8324 RAID */
0147     {"COMPAQ", "ARRAY CONTROLLER", NULL, BLIST_SPARSELUN | BLIST_LARGELUN |
0148         BLIST_MAX_512 | BLIST_REPORTLUN2},  /* Compaq RA4x00 */
0149     {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN | BLIST_MAX_512}, /* Compaq RA4x00 */
0150     {"COMPAQ", "CR3500", NULL, BLIST_FORCELUN},
0151     {"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
0152     {"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
0153     {"COMPAQ", "HSV110", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
0154     {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
0155     {"DEC", "HSG80", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
0156     {"DELL", "PV660F", NULL, BLIST_SPARSELUN},
0157     {"DELL", "PV660F   PSEUDO", NULL, BLIST_SPARSELUN},
0158     {"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */
0159     {"DELL", "PV530F", NULL, BLIST_SPARSELUN},
0160     {"DELL", "PERCRAID", NULL, BLIST_FORCELUN},
0161     {"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* EMC CLARiiON, storage on LUN 0 */
0162     {"DGC", "DISK", NULL, BLIST_SPARSELUN}, /* EMC CLARiiON, no storage on LUN 0 */
0163     {"EMC",  "Invista", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
0164     {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN |
0165      BLIST_REPORTLUN2 | BLIST_RETRY_ITF},
0166     {"EMULEX", "MD21/S2     ESDI", NULL, BLIST_SINGLELUN},
0167     {"easyRAID", "16P", NULL, BLIST_NOREPORTLUN},
0168     {"easyRAID", "X6P", NULL, BLIST_NOREPORTLUN},
0169     {"easyRAID", "F8", NULL, BLIST_NOREPORTLUN},
0170     {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
0171     {"FUJITSU", "ETERNUS_DXM", "*", BLIST_RETRY_ASC_C1},
0172     {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36},
0173     {"Generic", "USB Storage-SMC", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36}, /* FW: 0180 and 0207 */
0174     {"Generic", "Ultra HS-SD/MMC", "2.09", BLIST_IGN_MEDIA_CHANGE | BLIST_INQUIRY_36},
0175     {"HITACHI", "DF400", "*", BLIST_REPORTLUN2},
0176     {"HITACHI", "DF500", "*", BLIST_REPORTLUN2},
0177     {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2},
0178     {"HITACHI", "HUS1530", "*", BLIST_NO_DIF},
0179     {"HITACHI", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES},
0180     {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},   /* HP VA7400 */
0181     {"HP", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES}, /* HP XP Arrays */
0182     {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN},
0183     {"HP", "HSV100", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
0184     {"HP", "C1557A", NULL, BLIST_FORCELUN},
0185     {"HP", "C3323-300", "4269", BLIST_NOTQ},
0186     {"HP", "C5713A", NULL, BLIST_NOREPORTLUN},
0187     {"HP", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2},
0188     {"HPE", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES},
0189     {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
0190     {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
0191     {"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
0192     {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
0193     {"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN},
0194     {"IOMEGA", "Io20S         *F", NULL, BLIST_KEY},
0195     {"INSITE", "Floptical   F*8I", NULL, BLIST_KEY},
0196     {"INSITE", "I325VM", NULL, BLIST_KEY},
0197     {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC},
0198     {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
0199     {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
0200     {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
0201     {"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES},
0202     {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0203     {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
0204     {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
0205     {"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
0206     {"MegaRAID", "LD", NULL, BLIST_FORCELUN},
0207     {"MICROP", "4110", NULL, BLIST_NOTQ},
0208     {"MSFT", "Virtual HD", NULL, BLIST_MAX_1024 | BLIST_NO_RSOC},
0209     {"MYLEX", "DACARMRB", "*", BLIST_REPORTLUN2},
0210     {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN},
0211     {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0212     {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0213     {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0214     {"NEC", "iStorage", NULL, BLIST_REPORTLUN2},
0215     {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0216     {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0217     {"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0218     {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0219     {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0220     {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
0221     {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
0222     {"Promise", "", NULL, BLIST_SPARSELUN},
0223     {"QEMU", "QEMU CD-ROM", NULL, BLIST_SKIP_VPD_PAGES},
0224     {"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
0225     {"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
0226     {"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
0227     {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
0228     {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
0229     {"SEAGATE", "ST34555N", "0930", BLIST_NOTQ},    /* Chokes on tagged INQUIRY */
0230     {"SEAGATE", "ST3390N", "9546", BLIST_NOTQ},
0231     {"SEAGATE", "ST900MM0006", NULL, BLIST_SKIP_VPD_PAGES},
0232     {"SGI", "RAID3", "*", BLIST_SPARSELUN},
0233     {"SGI", "RAID5", "*", BLIST_SPARSELUN},
0234     {"SGI", "TP9100", "*", BLIST_REPORTLUN2},
0235     {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0236     {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0237     {"SUN", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0238     {"DELL", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0239     {"STK", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0240     {"NETAPP", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0241     {"LSI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0242     {"ENGENIO", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0243     {"LENOVO", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0244     {"FUJITSU", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
0245     {"SanDisk", "Cruzer Blade", NULL, BLIST_TRY_VPD_PAGES |
0246         BLIST_INQUIRY_36},
0247     {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
0248     {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
0249     {"SONY", "TSL", NULL, BLIST_FORCELUN},      /* DDS3 & DDS4 autoloaders */
0250     {"ST650211", "CF", NULL, BLIST_RETRY_HWERROR},
0251     {"SUN", "T300", "*", BLIST_SPARSELUN},
0252     {"SUN", "T4", "*", BLIST_SPARSELUN},
0253     {"Tornado-", "F4", "*", BLIST_NOREPORTLUN},
0254     {"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
0255     {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
0256     {"Traxdata", "CDR4120", NULL, BLIST_NOLUN}, /* locks up */
0257     {"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36},
0258     {"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN},
0259     {"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN},
0260     {"WangDAT", "Model 1300", "02.4", BLIST_SELECT_NO_ATN},
0261     {"WDC WD25", "00JB-00FUA0", NULL, BLIST_NOREPORTLUN},
0262     {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
0263     {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN},
0264     {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN},
0265     { NULL, NULL, NULL, 0 },
0266 };
0267 
0268 static struct scsi_dev_info_list_table *scsi_devinfo_lookup_by_key(int key)
0269 {
0270     struct scsi_dev_info_list_table *devinfo_table;
0271     int found = 0;
0272 
0273     list_for_each_entry(devinfo_table, &scsi_dev_info_list, node)
0274         if (devinfo_table->key == key) {
0275             found = 1;
0276             break;
0277         }
0278     if (!found)
0279         return ERR_PTR(-EINVAL);
0280 
0281     return devinfo_table;
0282 }
0283 
0284 /*
0285  * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into
0286  * devinfo vendor and model strings.
0287  */
0288 static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length,
0289                 char *from, int compatible)
0290 {
0291     size_t from_length;
0292 
0293     from_length = strlen(from);
0294     /* This zero-pads the destination */
0295     strncpy(to, from, to_length);
0296     if (from_length < to_length && !compatible) {
0297         /*
0298          * space pad the string if it is short.
0299          */
0300         memset(&to[from_length], ' ', to_length - from_length);
0301     }
0302     if (from_length > to_length)
0303          printk(KERN_WARNING "%s: %s string '%s' is too long\n",
0304             __func__, name, from);
0305 }
0306 
0307 /**
0308  * scsi_dev_info_list_add - add one dev_info list entry.
0309  * @compatible: if true, null terminate short strings.  Otherwise space pad.
0310  * @vendor: vendor string
0311  * @model:  model (product) string
0312  * @strflags:   integer string
0313  * @flags:  if strflags NULL, use this flag value
0314  *
0315  * Description:
0316  *  Create and add one dev_info entry for @vendor, @model, @strflags or
0317  *  @flag. If @compatible, add to the tail of the list, do not space
0318  *  pad, and set devinfo->compatible. The scsi_static_device_list entries
0319  *  are added with @compatible 1 and @clfags NULL.
0320  *
0321  * Returns: 0 OK, -error on failure.
0322  **/
0323 static int scsi_dev_info_list_add(int compatible, char *vendor, char *model,
0324                 char *strflags, blist_flags_t flags)
0325 {
0326     return scsi_dev_info_list_add_keyed(compatible, vendor, model,
0327                         strflags, flags,
0328                         SCSI_DEVINFO_GLOBAL);
0329 }
0330 
0331 /**
0332  * scsi_dev_info_list_add_keyed - add one dev_info list entry.
0333  * @compatible: if true, null terminate short strings.  Otherwise space pad.
0334  * @vendor: vendor string
0335  * @model:  model (product) string
0336  * @strflags:   integer string
0337  * @flags:  if strflags NULL, use this flag value
0338  * @key:    specify list to use
0339  *
0340  * Description:
0341  *  Create and add one dev_info entry for @vendor, @model,
0342  *  @strflags or @flag in list specified by @key. If @compatible,
0343  *  add to the tail of the list, do not space pad, and set
0344  *  devinfo->compatible. The scsi_static_device_list entries are
0345  *  added with @compatible 1 and @clfags NULL.
0346  *
0347  * Returns: 0 OK, -error on failure.
0348  **/
0349 int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
0350                  char *strflags, blist_flags_t flags,
0351                  enum scsi_devinfo_key key)
0352 {
0353     struct scsi_dev_info_list *devinfo;
0354     struct scsi_dev_info_list_table *devinfo_table =
0355         scsi_devinfo_lookup_by_key(key);
0356 
0357     if (IS_ERR(devinfo_table))
0358         return PTR_ERR(devinfo_table);
0359 
0360     devinfo = kmalloc(sizeof(*devinfo), GFP_KERNEL);
0361     if (!devinfo) {
0362         printk(KERN_ERR "%s: no memory\n", __func__);
0363         return -ENOMEM;
0364     }
0365 
0366     scsi_strcpy_devinfo("vendor", devinfo->vendor, sizeof(devinfo->vendor),
0367                 vendor, compatible);
0368     scsi_strcpy_devinfo("model", devinfo->model, sizeof(devinfo->model),
0369                 model, compatible);
0370 
0371     if (strflags) {
0372         unsigned long long val;
0373         int ret = kstrtoull(strflags, 0, &val);
0374 
0375         if (ret != 0) {
0376             kfree(devinfo);
0377             return ret;
0378         }
0379         flags = (__force blist_flags_t)val;
0380     }
0381     if (flags & __BLIST_UNUSED_MASK) {
0382         pr_err("scsi_devinfo (%s:%s): unsupported flags 0x%llx",
0383                vendor, model, flags & __BLIST_UNUSED_MASK);
0384         kfree(devinfo);
0385         return -EINVAL;
0386     }
0387     devinfo->flags = flags;
0388     devinfo->compatible = compatible;
0389 
0390     if (compatible)
0391         list_add_tail(&devinfo->dev_info_list,
0392                   &devinfo_table->scsi_dev_info_list);
0393     else
0394         list_add(&devinfo->dev_info_list,
0395              &devinfo_table->scsi_dev_info_list);
0396 
0397     return 0;
0398 }
0399 EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
0400 
0401 /**
0402  * scsi_dev_info_list_find - find a matching dev_info list entry.
0403  * @vendor: full vendor string
0404  * @model:  full model (product) string
0405  * @key:    specify list to use
0406  *
0407  * Description:
0408  *  Finds the first dev_info entry matching @vendor, @model
0409  *  in list specified by @key.
0410  *
0411  * Returns: pointer to matching entry, or ERR_PTR on failure.
0412  **/
0413 static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
0414         const char *model, enum scsi_devinfo_key key)
0415 {
0416     struct scsi_dev_info_list *devinfo;
0417     struct scsi_dev_info_list_table *devinfo_table =
0418         scsi_devinfo_lookup_by_key(key);
0419     size_t vmax, mmax, mlen;
0420     const char *vskip, *mskip;
0421 
0422     if (IS_ERR(devinfo_table))
0423         return (struct scsi_dev_info_list *) devinfo_table;
0424 
0425     /* Prepare for "compatible" matches */
0426 
0427     /*
0428      * XXX why skip leading spaces? If an odd INQUIRY
0429      * value, that should have been part of the
0430      * scsi_static_device_list[] entry, such as "  FOO"
0431      * rather than "FOO". Since this code is already
0432      * here, and we don't know what device it is
0433      * trying to work with, leave it as-is.
0434      */
0435     vmax = sizeof(devinfo->vendor);
0436     vskip = vendor;
0437     while (vmax > 0 && *vskip == ' ') {
0438         vmax--;
0439         vskip++;
0440     }
0441     /* Also skip trailing spaces */
0442     while (vmax > 0 && vskip[vmax - 1] == ' ')
0443         --vmax;
0444 
0445     mmax = sizeof(devinfo->model);
0446     mskip = model;
0447     while (mmax > 0 && *mskip == ' ') {
0448         mmax--;
0449         mskip++;
0450     }
0451     while (mmax > 0 && mskip[mmax - 1] == ' ')
0452         --mmax;
0453 
0454     list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
0455                 dev_info_list) {
0456         if (devinfo->compatible) {
0457             /*
0458              * vendor strings must be an exact match
0459              */
0460             if (vmax != strnlen(devinfo->vendor,
0461                         sizeof(devinfo->vendor)) ||
0462                 memcmp(devinfo->vendor, vskip, vmax))
0463                 continue;
0464 
0465             /*
0466              * @model specifies the full string, and
0467              * must be larger or equal to devinfo->model
0468              */
0469             mlen = strnlen(devinfo->model, sizeof(devinfo->model));
0470             if (mmax < mlen || memcmp(devinfo->model, mskip, mlen))
0471                 continue;
0472             return devinfo;
0473         } else {
0474             if (!memcmp(devinfo->vendor, vendor,
0475                     sizeof(devinfo->vendor)) &&
0476                 !memcmp(devinfo->model, model,
0477                     sizeof(devinfo->model)))
0478                 return devinfo;
0479         }
0480     }
0481 
0482     return ERR_PTR(-ENOENT);
0483 }
0484 
0485 /**
0486  * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
0487  * @vendor: vendor string
0488  * @model:  model (product) string
0489  * @key:    specify list to use
0490  *
0491  * Description:
0492  *  Remove and destroy one dev_info entry for @vendor, @model
0493  *  in list specified by @key.
0494  *
0495  * Returns: 0 OK, -error on failure.
0496  **/
0497 int scsi_dev_info_list_del_keyed(char *vendor, char *model,
0498                  enum scsi_devinfo_key key)
0499 {
0500     struct scsi_dev_info_list *found;
0501 
0502     found = scsi_dev_info_list_find(vendor, model, key);
0503     if (IS_ERR(found))
0504         return PTR_ERR(found);
0505 
0506     list_del(&found->dev_info_list);
0507     kfree(found);
0508     return 0;
0509 }
0510 EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
0511 
0512 /**
0513  * scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list.
0514  * @dev_list:   string of device flags to add
0515  *
0516  * Description:
0517  *  Parse dev_list, and add entries to the scsi_dev_info_list.
0518  *  dev_list is of the form "vendor:product:flag,vendor:product:flag".
0519  *  dev_list is modified via strsep. Can be called for command line
0520  *  addition, for proc or mabye a sysfs interface.
0521  *
0522  * Returns: 0 if OK, -error on failure.
0523  **/
0524 static int scsi_dev_info_list_add_str(char *dev_list)
0525 {
0526     char *vendor, *model, *strflags, *next;
0527     char *next_check;
0528     int res = 0;
0529 
0530     next = dev_list;
0531     if (next && next[0] == '"') {
0532         /*
0533          * Ignore both the leading and trailing quote.
0534          */
0535         next++;
0536         next_check = ",\"";
0537     } else {
0538         next_check = ",";
0539     }
0540 
0541     /*
0542      * For the leading and trailing '"' case, the for loop comes
0543      * through the last time with vendor[0] == '\0'.
0544      */
0545     for (vendor = strsep(&next, ":"); vendor && (vendor[0] != '\0')
0546          && (res == 0); vendor = strsep(&next, ":")) {
0547         strflags = NULL;
0548         model = strsep(&next, ":");
0549         if (model)
0550             strflags = strsep(&next, next_check);
0551         if (!model || !strflags) {
0552             printk(KERN_ERR "%s: bad dev info string '%s' '%s'"
0553                    " '%s'\n", __func__, vendor, model,
0554                    strflags);
0555             res = -EINVAL;
0556         } else
0557             res = scsi_dev_info_list_add(0 /* compatible */, vendor,
0558                              model, strflags, 0);
0559     }
0560     return res;
0561 }
0562 
0563 /**
0564  * scsi_get_device_flags - get device specific flags from the dynamic
0565  *  device list.
0566  * @sdev:       &scsi_device to get flags for
0567  * @vendor: vendor name
0568  * @model:  model name
0569  *
0570  * Description:
0571  *     Search the global scsi_dev_info_list (specified by list zero)
0572  *     for an entry matching @vendor and @model, if found, return the
0573  *     matching flags value, else return the host or global default
0574  *     settings.  Called during scan time.
0575  **/
0576 blist_flags_t scsi_get_device_flags(struct scsi_device *sdev,
0577                     const unsigned char *vendor,
0578                     const unsigned char *model)
0579 {
0580     return scsi_get_device_flags_keyed(sdev, vendor, model,
0581                        SCSI_DEVINFO_GLOBAL);
0582 }
0583 
0584 
0585 /**
0586  * scsi_get_device_flags_keyed - get device specific flags from the dynamic device list
0587  * @sdev:       &scsi_device to get flags for
0588  * @vendor: vendor name
0589  * @model:  model name
0590  * @key:    list to look up
0591  *
0592  * Description:
0593  *     Search the scsi_dev_info_list specified by @key for an entry
0594  *     matching @vendor and @model, if found, return the matching
0595  *     flags value, else return the host or global default settings.
0596  *     Called during scan time.
0597  **/
0598 blist_flags_t scsi_get_device_flags_keyed(struct scsi_device *sdev,
0599                 const unsigned char *vendor,
0600                 const unsigned char *model,
0601                 enum scsi_devinfo_key key)
0602 {
0603     struct scsi_dev_info_list *devinfo;
0604 
0605     devinfo = scsi_dev_info_list_find(vendor, model, key);
0606     if (!IS_ERR(devinfo))
0607         return devinfo->flags;
0608 
0609     /* key or device not found: return nothing */
0610     if (key != SCSI_DEVINFO_GLOBAL)
0611         return 0;
0612 
0613     /* except for the global list, where we have an exception */
0614     if (sdev->sdev_bflags)
0615         return sdev->sdev_bflags;
0616 
0617     return scsi_default_dev_flags;
0618 }
0619 EXPORT_SYMBOL(scsi_get_device_flags_keyed);
0620 
0621 #ifdef CONFIG_SCSI_PROC_FS
0622 struct double_list {
0623     struct list_head *top;
0624     struct list_head *bottom;
0625 };
0626 
0627 static int devinfo_seq_show(struct seq_file *m, void *v)
0628 {
0629     struct double_list *dl = v;
0630     struct scsi_dev_info_list_table *devinfo_table =
0631         list_entry(dl->top, struct scsi_dev_info_list_table, node);
0632     struct scsi_dev_info_list *devinfo =
0633         list_entry(dl->bottom, struct scsi_dev_info_list,
0634                dev_info_list);
0635 
0636     if (devinfo_table->scsi_dev_info_list.next == dl->bottom &&
0637         devinfo_table->name)
0638         seq_printf(m, "[%s]:\n", devinfo_table->name);
0639 
0640     seq_printf(m, "'%.8s' '%.16s' 0x%llx\n",
0641            devinfo->vendor, devinfo->model, devinfo->flags);
0642     return 0;
0643 }
0644 
0645 static void *devinfo_seq_start(struct seq_file *m, loff_t *ppos)
0646 {
0647     struct double_list *dl = kmalloc(sizeof(*dl), GFP_KERNEL);
0648     loff_t pos = *ppos;
0649 
0650     if (!dl)
0651         return NULL;
0652 
0653     list_for_each(dl->top, &scsi_dev_info_list) {
0654         struct scsi_dev_info_list_table *devinfo_table =
0655             list_entry(dl->top, struct scsi_dev_info_list_table,
0656                    node);
0657         list_for_each(dl->bottom, &devinfo_table->scsi_dev_info_list)
0658             if (pos-- == 0)
0659                 return dl;
0660     }
0661 
0662     kfree(dl);
0663     return NULL;
0664 }
0665 
0666 static void *devinfo_seq_next(struct seq_file *m, void *v, loff_t *ppos)
0667 {
0668     struct double_list *dl = v;
0669     struct scsi_dev_info_list_table *devinfo_table =
0670         list_entry(dl->top, struct scsi_dev_info_list_table, node);
0671 
0672     ++*ppos;
0673     dl->bottom = dl->bottom->next;
0674     while (&devinfo_table->scsi_dev_info_list == dl->bottom) {
0675         dl->top = dl->top->next;
0676         if (dl->top == &scsi_dev_info_list) {
0677             kfree(dl);
0678             return NULL;
0679         }
0680         devinfo_table = list_entry(dl->top,
0681                        struct scsi_dev_info_list_table,
0682                        node);
0683         dl->bottom = devinfo_table->scsi_dev_info_list.next;
0684     }
0685 
0686     return dl;
0687 }
0688 
0689 static void devinfo_seq_stop(struct seq_file *m, void *v)
0690 {
0691     kfree(v);
0692 }
0693 
0694 static const struct seq_operations scsi_devinfo_seq_ops = {
0695     .start  = devinfo_seq_start,
0696     .next   = devinfo_seq_next,
0697     .stop   = devinfo_seq_stop,
0698     .show   = devinfo_seq_show,
0699 };
0700 
0701 static int proc_scsi_devinfo_open(struct inode *inode, struct file *file)
0702 {
0703     return seq_open(file, &scsi_devinfo_seq_ops);
0704 }
0705 
0706 /*
0707  * proc_scsi_dev_info_write - allow additions to scsi_dev_info_list via /proc.
0708  *
0709  * Description: Adds a black/white list entry for vendor and model with an
0710  * integer value of flag to the scsi device info list.
0711  * To use, echo "vendor:model:flag" > /proc/scsi/device_info
0712  */
0713 static ssize_t proc_scsi_devinfo_write(struct file *file,
0714                        const char __user *buf,
0715                        size_t length, loff_t *ppos)
0716 {
0717     char *buffer;
0718     ssize_t err = length;
0719 
0720     if (!buf || length>PAGE_SIZE)
0721         return -EINVAL;
0722     if (!(buffer = (char *) __get_free_page(GFP_KERNEL)))
0723         return -ENOMEM;
0724     if (copy_from_user(buffer, buf, length)) {
0725         err =-EFAULT;
0726         goto out;
0727     }
0728 
0729     if (length < PAGE_SIZE)
0730         buffer[length] = '\0';
0731     else if (buffer[PAGE_SIZE-1]) {
0732         err = -EINVAL;
0733         goto out;
0734     }
0735 
0736     scsi_dev_info_list_add_str(buffer);
0737 
0738 out:
0739     free_page((unsigned long)buffer);
0740     return err;
0741 }
0742 
0743 static const struct proc_ops scsi_devinfo_proc_ops = {
0744     .proc_open  = proc_scsi_devinfo_open,
0745     .proc_read  = seq_read,
0746     .proc_write = proc_scsi_devinfo_write,
0747     .proc_lseek = seq_lseek,
0748     .proc_release   = seq_release,
0749 };
0750 #endif /* CONFIG_SCSI_PROC_FS */
0751 
0752 module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0);
0753 MODULE_PARM_DESC(dev_flags,
0754      "Given scsi_dev_flags=vendor:model:flags[,v:m:f] add black/white"
0755      " list entries for vendor and model with an integer value of flags"
0756      " to the scsi device info list");
0757 
0758 module_param_named(default_dev_flags, scsi_default_dev_flags, ullong, 0644);
0759 MODULE_PARM_DESC(default_dev_flags,
0760          "scsi default device flag uint64_t value");
0761 
0762 /**
0763  * scsi_exit_devinfo - remove /proc/scsi/device_info & the scsi_dev_info_list
0764  **/
0765 void scsi_exit_devinfo(void)
0766 {
0767 #ifdef CONFIG_SCSI_PROC_FS
0768     remove_proc_entry("scsi/device_info", NULL);
0769 #endif
0770 
0771     scsi_dev_info_remove_list(SCSI_DEVINFO_GLOBAL);
0772 }
0773 
0774 /**
0775  * scsi_dev_info_add_list - add a new devinfo list
0776  * @key:    key of the list to add
0777  * @name:   Name of the list to add (for /proc/scsi/device_info)
0778  *
0779  * Adds the requested list, returns zero on success, -EEXIST if the
0780  * key is already registered to a list, or other error on failure.
0781  */
0782 int scsi_dev_info_add_list(enum scsi_devinfo_key key, const char *name)
0783 {
0784     struct scsi_dev_info_list_table *devinfo_table =
0785         scsi_devinfo_lookup_by_key(key);
0786 
0787     if (!IS_ERR(devinfo_table))
0788         /* list already exists */
0789         return -EEXIST;
0790 
0791     devinfo_table = kmalloc(sizeof(*devinfo_table), GFP_KERNEL);
0792 
0793     if (!devinfo_table)
0794         return -ENOMEM;
0795 
0796     INIT_LIST_HEAD(&devinfo_table->node);
0797     INIT_LIST_HEAD(&devinfo_table->scsi_dev_info_list);
0798     devinfo_table->name = name;
0799     devinfo_table->key = key;
0800     list_add_tail(&devinfo_table->node, &scsi_dev_info_list);
0801 
0802     return 0;
0803 }
0804 EXPORT_SYMBOL(scsi_dev_info_add_list);
0805 
0806 /**
0807  * scsi_dev_info_remove_list - destroy an added devinfo list
0808  * @key: key of the list to destroy
0809  *
0810  * Iterates over the entire list first, freeing all the values, then
0811  * frees the list itself.  Returns 0 on success or -EINVAL if the key
0812  * can't be found.
0813  */
0814 int scsi_dev_info_remove_list(enum scsi_devinfo_key key)
0815 {
0816     struct list_head *lh, *lh_next;
0817     struct scsi_dev_info_list_table *devinfo_table =
0818         scsi_devinfo_lookup_by_key(key);
0819 
0820     if (IS_ERR(devinfo_table))
0821         /* no such list */
0822         return -EINVAL;
0823 
0824     /* remove from the master list */
0825     list_del(&devinfo_table->node);
0826 
0827     list_for_each_safe(lh, lh_next, &devinfo_table->scsi_dev_info_list) {
0828         struct scsi_dev_info_list *devinfo;
0829 
0830         devinfo = list_entry(lh, struct scsi_dev_info_list,
0831                      dev_info_list);
0832         kfree(devinfo);
0833     }
0834     kfree(devinfo_table);
0835 
0836     return 0;
0837 }
0838 EXPORT_SYMBOL(scsi_dev_info_remove_list);
0839 
0840 /**
0841  * scsi_init_devinfo - set up the dynamic device list.
0842  *
0843  * Description:
0844  *  Add command line entries from scsi_dev_flags, then add
0845  *  scsi_static_device_list entries to the scsi device info list.
0846  */
0847 int __init scsi_init_devinfo(void)
0848 {
0849 #ifdef CONFIG_SCSI_PROC_FS
0850     struct proc_dir_entry *p;
0851 #endif
0852     int error, i;
0853 
0854     error = scsi_dev_info_add_list(SCSI_DEVINFO_GLOBAL, NULL);
0855     if (error)
0856         return error;
0857 
0858     error = scsi_dev_info_list_add_str(scsi_dev_flags);
0859     if (error)
0860         goto out;
0861 
0862     for (i = 0; scsi_static_device_list[i].vendor; i++) {
0863         error = scsi_dev_info_list_add(1 /* compatibile */,
0864                 scsi_static_device_list[i].vendor,
0865                 scsi_static_device_list[i].model,
0866                 NULL,
0867                 scsi_static_device_list[i].flags);
0868         if (error)
0869             goto out;
0870     }
0871 
0872 #ifdef CONFIG_SCSI_PROC_FS
0873     p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_ops);
0874     if (!p) {
0875         error = -ENOMEM;
0876         goto out;
0877     }
0878 #endif /* CONFIG_SCSI_PROC_FS */
0879 
0880  out:
0881     if (error)
0882         scsi_exit_devinfo();
0883     return error;
0884 }