Commit 8a3e33cf authored by Manuel Lauss's avatar Manuel Lauss Committed by Tejun Heo

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: default avatarManuel Lauss <manuel.lauss@gmail.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent a73f22f9
...@@ -181,6 +181,8 @@ enum { ...@@ -181,6 +181,8 @@ enum {
PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */
PORT_CMD_ESP = (1 << 21), /* External Sata Port */
PORT_CMD_HPCP = (1 << 18), /* HotPlug Capable Port */
PORT_CMD_PMP = (1 << 17), /* PMP attached */ PORT_CMD_PMP = (1 << 17), /* PMP attached */
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
......
...@@ -1117,6 +1117,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, ...@@ -1117,6 +1117,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
int port_no, void __iomem *mmio, int port_no, void __iomem *mmio,
void __iomem *port_mmio) void __iomem *port_mmio)
{ {
struct ahci_host_priv *hpriv = ap->host->private_data;
const char *emsg = NULL; const char *emsg = NULL;
int rc; int rc;
u32 tmp; u32 tmp;
...@@ -1138,6 +1139,12 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, ...@@ -1138,6 +1139,12 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
writel(tmp, port_mmio + PORT_IRQ_STAT); writel(tmp, port_mmio + PORT_IRQ_STAT);
writel(1 << port_no, mmio + HOST_IRQ_STAT); writel(1 << port_no, mmio + HOST_IRQ_STAT);
/* mark esata ports */
tmp = readl(port_mmio + PORT_CMD);
if ((tmp & PORT_CMD_HPCP) ||
((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
ap->pflags |= ATA_PFLAG_EXTERNAL;
} }
void ahci_init_controller(struct ata_host *host) void ahci_init_controller(struct ata_host *host)
......
...@@ -2015,8 +2015,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) ...@@ -2015,8 +2015,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
/* set scsi removable (RMB) bit per ata bit */ /* set scsi removable (RMB) bit per ata bit, or if the
if (ata_id_removable(args->id)) * AHCI port says it's external (Hotplug-capable, eSATA).
*/
if (ata_id_removable(args->id) ||
(args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL))
hdr[1] |= (1 << 7); hdr[1] |= (1 << 7);
if (args->dev->class == ATA_DEV_ZAC) { if (args->dev->class == ATA_DEV_ZAC) {
......
...@@ -254,6 +254,7 @@ enum { ...@@ -254,6 +254,7 @@ enum {
ATA_PFLAG_PIO32 = (1 << 20), /* 32bit PIO */ ATA_PFLAG_PIO32 = (1 << 20), /* 32bit PIO */
ATA_PFLAG_PIO32CHANGE = (1 << 21), /* 32bit PIO can be turned on/off */ ATA_PFLAG_PIO32CHANGE = (1 << 21), /* 32bit PIO can be turned on/off */
ATA_PFLAG_EXTERNAL = (1 << 22), /* eSATA/external port */
/* struct ata_queued_cmd flags */ /* struct ata_queued_cmd flags */
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment