Merge tag 'ata-6.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull ata fixes from Niklas Cassel:

 - Add a missing refcount decrement in ata_scsi_dev_rescan() when
   the device or its queue is not running.

   In the case where the device is running, the recount is already
   decremented properly (Yihang Li)

 - Generate the proper sense code for a Security locked device.

   There was a regression caused by a recent change of how sense
   data is generated for commands that did not provide any sense
   data. This broke system suspend for Security locked devices.

   Generate the sense data that the SCSI disk driver expects for a
   Security locked device so that system suspend works again (me)

 - Set capacity to zero for a Security locked device.

   All I/O commands will be aborted by a Security locked device.
   Thus, the block layer disk partition scanning will result in
   a bunch of, for the user, confusing I/O errors in dmesg during
   boot.

   Since a Security locked device is unusable anyway, set the capacity
   to zero, to avoid the disk partition scanning during boot. We still
   create the block device in /dev such that the user may unlock the
   device using e.g. hdparm (me)

* tag 'ata-6.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-core: Set capacity to zero for a security locked drive
  ata: libata-scsi: Fix system suspend for a security locked drive
  ata: libata-scsi: Add missing scsi_device_put() in ata_scsi_dev_rescan()
This commit is contained in:
Linus Torvalds
2025-11-21 10:53:23 -08:00
3 changed files with 21 additions and 1 deletions

View File

@@ -3006,6 +3006,16 @@ int ata_dev_configure(struct ata_device *dev)
}
dev->n_sectors = ata_id_n_sectors(id);
if (ata_id_is_locked(id)) {
/*
* If Security locked, set capacity to zero to prevent
* any I/O, e.g. partition scanning, as any I/O to a
* locked drive will result in user visible errors.
*/
ata_dev_info(dev,
"Security locked, setting capacity to zero\n");
dev->n_sectors = 0;
}
/* get current R/W Multiple count setting */
if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) {

View File

@@ -992,6 +992,13 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
return;
}
if (ata_id_is_locked(dev->id)) {
/* Security locked */
/* LOGICAL UNIT ACCESS NOT AUTHORIZED */
ata_scsi_set_sense(dev, cmd, DATA_PROTECT, 0x74, 0x71);
return;
}
if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
ata_dev_dbg(dev,
"Missing result TF: reporting aborted command\n");
@@ -4894,8 +4901,10 @@ void ata_scsi_dev_rescan(struct work_struct *work)
spin_unlock_irqrestore(ap->lock, flags);
if (do_resume) {
ret = scsi_resume_device(sdev);
if (ret == -EWOULDBLOCK)
if (ret == -EWOULDBLOCK) {
scsi_device_put(sdev);
goto unlock_scan;
}
dev->flags &= ~ATA_DFLAG_RESUMING;
}
ret = scsi_rescan_device(sdev);

View File

@@ -566,6 +566,7 @@ struct ata_bmdma_prd {
#define ata_id_has_ncq(id) ((id)[ATA_ID_SATA_CAPABILITY] & (1 << 8))
#define ata_id_queue_depth(id) (((id)[ATA_ID_QUEUE_DEPTH] & 0x1f) + 1)
#define ata_id_removable(id) ((id)[ATA_ID_CONFIG] & (1 << 7))
#define ata_id_is_locked(id) (((id)[ATA_ID_DLF] & 0x7) == 0x7)
#define ata_id_has_atapi_AN(id) \
((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \