Ewan, I like it, more generic than my patch. I never saw the other cases, so I limited my patch to WS16. Acked-by: Bill Kuzeja <William.Kuzeja@xxxxxxxxxxx> On Tue-09-19 at 12:14 Ewan D. Milne wrote: > Some devices do not support a WRITE SAME / WRITE SAME(16) with the > UNMAP > bit set up to the length specified in the MAXIMUM WRITE SAME LENGTH > field > in the block limits VPD page (or, the field is zero, indicating there is > no limit). Limit the length by the MAXIMUM UNMAP LBA COUNT value. > Otherwise the command might be rejected. > > Signed-off-by: Ewan D. Milne <emilne@xxxxxxxxxx> > --- > drivers/scsi/sd.c | 14 +++++++++++--- > 1 file changed, 11 insertions(+), 3 deletions(-) > > diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c > index 6549e5c..fa07ac2 100644 > --- a/drivers/scsi/sd.c > +++ b/drivers/scsi/sd.c > @@ -693,6 +693,7 @@ static void sd_config_discard(struct scsi_disk *sdkp, > unsigned int mode) > struct request_queue *q = sdkp->disk->queue; > unsigned int logical_block_size = sdkp->device->sector_size; > unsigned int max_blocks = 0; > + u32 max_ws_blocks = sdkp->max_ws_blocks; > > q->limits.discard_alignment = > sdkp->unmap_alignment * logical_block_size; > @@ -701,6 +702,13 @@ static void sd_config_discard(struct scsi_disk *sdkp, > unsigned int mode) > sdkp->unmap_granularity * logical_block_size); > sdkp->provisioning_mode = mode; > > + /* > + * Some devices limit WRITE SAME / WRITE SAME(16) w/UNMAP > + * by MAXIMUM UNMAP LBA COUNT instead of MAXIMUM WRITE > SAME LENGTH. > + * Use the smaller of the two values to avoid ILLEGAL REQUEST > errors. > + */ > + max_ws_blocks = min_not_zero(max_ws_blocks, sdkp- > >max_unmap_blocks); > + > switch (mode) { > > case SD_LBP_FULL: > @@ -715,17 +723,17 @@ static void sd_config_discard(struct scsi_disk *sdkp, > unsigned int mode) > break; > > case SD_LBP_WS16: > - max_blocks = min_not_zero(sdkp->max_ws_blocks, > + max_blocks = min_not_zero(max_ws_blocks, > (u32)SD_MAX_WS16_BLOCKS); > break; > > case SD_LBP_WS10: > - max_blocks = min_not_zero(sdkp->max_ws_blocks, > + max_blocks = min_not_zero(max_ws_blocks, > (u32)SD_MAX_WS10_BLOCKS); > break; > > case SD_LBP_ZERO: > - max_blocks = min_not_zero(sdkp->max_ws_blocks, > + max_blocks = min_not_zero(max_ws_blocks, > (u32)SD_MAX_WS10_BLOCKS); > break; > } > -- > 2.1.0