Maciej, > So I do have all the reasons to conclude this value has indeed been > arbitrarily chosen, don't I? The SAT spec defines the contents of the first part of the page. The trailing 512 bytes are defined in the ATA spec. > If you insist that the value of 64 stay, then please come up with a > suitable macro name to define along with SCSI_VPD_PG_LEN that reflects > the meaning of 64 in this context and I'll be happy to update 3/3 > accordingly, but please explain why the value of 64 is any better than > 255 here and the inconsistency with the buffer size justified. Can please you try the following patch? -- Martin K. Petersen Oracle Linux Engineering Subject: [PATCH] scsi: core: Request VPD page header before fetching full page We currently default to 255 bytes when fetching for VPD pages during discovery. However, we have had a few devices that are known to wedge if the requested buffer exceeds a certain size. See commit af73623f5f10 ("[SCSI] sd: Reduce buffer size for vpd request") which works around one example of this problem in the SCSI disk driver. With commit d188b0675b21 ("scsi: core: Add sysfs attributes for VPD pages 0h and 89h") we now risk triggering the same issue in the generic midlayer code. The problem with the ATA VPD page in particular is that the SCSI portion of the page is trailed by 512 bytes of verbatim ATA Identify Device information. However, not all controllers actually provide the additional 512 bytes and will lock up if one asks for more than the 64 bytes containing the SCSI protocol fields. Instead of picking a new, somewhat arbitrary, number of bytes for the default VPD buffer size, first fetch the 4-byte header for each page. The header contains the size of the page as far as the device is concerned. Use this reported size to allocate the permanent VPD buffer and then proceed to fetch the full page up to a 1K limit. Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx> Fixes: d188b0675b21 ("scsi: core: Add sysfs attributes for VPD pages 0h and 89h") diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 211aace69c22..d45c4d7526d5 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -384,7 +384,13 @@ EXPORT_SYMBOL_GPL(scsi_get_vpd_page); static struct scsi_vpd *scsi_get_vpd_buf(struct scsi_device *sdev, u8 page) { struct scsi_vpd *vpd_buf; - int vpd_len = SCSI_VPD_PG_LEN, result; + int vpd_len, result; + unsigned char vpd_header[SCSI_VPD_HEADER_SIZE]; + + result = scsi_vpd_inquiry(sdev, vpd_header, page, SCSI_VPD_HEADER_SIZE); + if (result < SCSI_VPD_HEADER_SIZE || result > SCSI_VPD_MAX_SIZE) + return NULL; + vpd_len = result; retry_pg: vpd_buf = kmalloc(sizeof(*vpd_buf) + vpd_len, GFP_KERNEL); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index d1c6fc83b1e3..6d6c44e8da08 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -100,6 +100,11 @@ struct scsi_vpd { unsigned char data[]; }; +enum scsi_vpd_parameters { + SCSI_VPD_HEADER_SIZE = 4, + SCSI_VPD_MAX_SIZE = 1024, +}; + struct scsi_device { struct Scsi_Host *host; struct request_queue *request_queue; @@ -141,7 +146,6 @@ struct scsi_device { const char * model; /* ... after scan; point to static string */ const char * rev; /* ... "nullnullnullnull" before scan */ -#define SCSI_VPD_PG_LEN 255 struct scsi_vpd __rcu *vpd_pg0; struct scsi_vpd __rcu *vpd_pg83; struct scsi_vpd __rcu *vpd_pg80;