Skip to content

Commit 8a3e33c

Browse files
mlauss2htejun
authored andcommitted
ata: ahci: find eSATA ports and flag them as removable
If the AHCI ports' HPCP or ESP bits are set, the port should be considered external (e.g. eSATA) and is marked as removable. Userspace tools like udisks then treat it like an usb drive. With this patch applied, when I plug a drive into the esata port, KDE pops up a window asking what to do with the drives(s), just like it does for any random USB stick. Removability is indicated to the upper layers by way of the SCSI RMB bit, as I haven't found another way to signal userspace to treat a sata disk like any usb stick. Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com> Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent a73f22f commit 8a3e33c

File tree

4 files changed

+15
-2
lines changed

4 files changed

+15
-2
lines changed

drivers/ata/ahci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ enum {
181181
PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
182182
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
183183
PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */
184+
PORT_CMD_ESP = (1 << 21), /* External Sata Port */
185+
PORT_CMD_HPCP = (1 << 18), /* HotPlug Capable Port */
184186
PORT_CMD_PMP = (1 << 17), /* PMP attached */
185187
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
186188
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */

drivers/ata/libahci.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
11171117
int port_no, void __iomem *mmio,
11181118
void __iomem *port_mmio)
11191119
{
1120+
struct ahci_host_priv *hpriv = ap->host->private_data;
11201121
const char *emsg = NULL;
11211122
int rc;
11221123
u32 tmp;
@@ -1138,6 +1139,12 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
11381139
writel(tmp, port_mmio + PORT_IRQ_STAT);
11391140

11401141
writel(1 << port_no, mmio + HOST_IRQ_STAT);
1142+
1143+
/* mark esata ports */
1144+
tmp = readl(port_mmio + PORT_CMD);
1145+
if ((tmp & PORT_CMD_HPCP) ||
1146+
((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
1147+
ap->pflags |= ATA_PFLAG_EXTERNAL;
11411148
}
11421149

11431150
void ahci_init_controller(struct ata_host *host)

drivers/ata/libata-scsi.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,8 +2015,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
20152015

20162016
VPRINTK("ENTER\n");
20172017

2018-
/* set scsi removable (RMB) bit per ata bit */
2019-
if (ata_id_removable(args->id))
2018+
/* set scsi removable (RMB) bit per ata bit, or if the
2019+
* AHCI port says it's external (Hotplug-capable, eSATA).
2020+
*/
2021+
if (ata_id_removable(args->id) ||
2022+
(args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL))
20202023
hdr[1] |= (1 << 7);
20212024

20222025
if (args->dev->class == ATA_DEV_ZAC) {

include/linux/libata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ enum {
254254

255255
ATA_PFLAG_PIO32 = (1 << 20), /* 32bit PIO */
256256
ATA_PFLAG_PIO32CHANGE = (1 << 21), /* 32bit PIO can be turned on/off */
257+
ATA_PFLAG_EXTERNAL = (1 << 22), /* eSATA/external port */
257258

258259
/* struct ata_queued_cmd flags */
259260
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */

0 commit comments

Comments
 (0)