Skip to content

Commit 3100d49

Browse files
Mikael PetterssonJeff Garzik
Mikael Pettersson
authored and
Jeff Garzik
committed
sata_promise: fix hardreset lockdep error
sata_promise's pdc_hard_reset_port() needs to serialize because it flips a port-specific bit in controller register that's shared by all ports. The code takes the ata host lock for this, but that's broken because an interrupt may arrive on our irq during the hard reset sequence, and that too will take the ata host lock. With lockdep enabled a big nasty warning is seen. Fixed by adding private state to the ata host structure, containing a second lock used only for serializing the hard reset sequences. This eliminated the lockdep warnings both on my test rig and on the original reporter's machine. Signed-off-by: Mikael Pettersson <[email protected]> Tested-by: Adko Branil <[email protected]> Cc: [email protected] Signed-off-by: Jeff Garzik <[email protected]>
1 parent 2844a48 commit 3100d49

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

drivers/ata/sata_promise.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ struct pdc_port_priv {
147147
dma_addr_t pkt_dma;
148148
};
149149

150+
struct pdc_host_priv {
151+
spinlock_t hard_reset_lock;
152+
};
153+
150154
static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
151155
static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
152156
static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct ata_port *ap)
801805
void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
802806
void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1;
803807
unsigned int ata_no = pdc_ata_port_to_ata_no(ap);
808+
struct pdc_host_priv *hpriv = ap->host->private_data;
804809
u8 tmp;
805810

806-
spin_lock(&ap->host->lock);
811+
spin_lock(&hpriv->hard_reset_lock);
807812

808813
tmp = readb(pcictl_b1_mmio);
809814
tmp &= ~(0x10 << ata_no);
@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct ata_port *ap)
814819
writeb(tmp, pcictl_b1_mmio);
815820
readb(pcictl_b1_mmio); /* flush */
816821

817-
spin_unlock(&ap->host->lock);
822+
spin_unlock(&hpriv->hard_reset_lock);
818823
}
819824

820825
static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
@@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
11821187
const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
11831188
const struct ata_port_info *ppi[PDC_MAX_PORTS];
11841189
struct ata_host *host;
1190+
struct pdc_host_priv *hpriv;
11851191
void __iomem *host_mmio;
11861192
int n_ports, i, rc;
11871193
int is_sataii_tx4;
@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
12181224
dev_err(&pdev->dev, "failed to allocate host\n");
12191225
return -ENOMEM;
12201226
}
1227+
hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL);
1228+
if (!hpriv)
1229+
return -ENOMEM;
1230+
spin_lock_init(&hpriv->hard_reset_lock);
1231+
host->private_data = hpriv;
12211232
host->iomap = pcim_iomap_table(pdev);
12221233

12231234
is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);

0 commit comments

Comments
 (0)