aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorMikael Pettersson <mikpe@it.uu.se>2012-09-16 14:53:43 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-11-28 12:37:56 -0500
commit3100d49d3cd236443faae9d81137c81b22d36003 (patch)
tree7fb4455806be0ac8dad86e26adc0efe82967f874 /drivers/ata
parent2844a48706e54ddda4a04269dba4250b42f449de (diff)
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 <mikpe@it.uu.se> Tested-by: Adko Branil <adkobranil@yahoo.com> Cc: stable@vger.kernel.org Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/sata_promise.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 489c81768321..fb0dd87f8893 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -147,6 +147,10 @@ struct pdc_port_priv {
147 dma_addr_t pkt_dma; 147 dma_addr_t pkt_dma;
148}; 148};
149 149
150struct pdc_host_priv {
151 spinlock_t hard_reset_lock;
152};
153
150static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 154static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
151static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 155static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
152static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 156static 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)
801 void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; 805 void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
802 void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; 806 void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1;
803 unsigned int ata_no = pdc_ata_port_to_ata_no(ap); 807 unsigned int ata_no = pdc_ata_port_to_ata_no(ap);
808 struct pdc_host_priv *hpriv = ap->host->private_data;
804 u8 tmp; 809 u8 tmp;
805 810
806 spin_lock(&ap->host->lock); 811 spin_lock(&hpriv->hard_reset_lock);
807 812
808 tmp = readb(pcictl_b1_mmio); 813 tmp = readb(pcictl_b1_mmio);
809 tmp &= ~(0x10 << ata_no); 814 tmp &= ~(0x10 << ata_no);
@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct ata_port *ap)
814 writeb(tmp, pcictl_b1_mmio); 819 writeb(tmp, pcictl_b1_mmio);
815 readb(pcictl_b1_mmio); /* flush */ 820 readb(pcictl_b1_mmio); /* flush */
816 821
817 spin_unlock(&ap->host->lock); 822 spin_unlock(&hpriv->hard_reset_lock);
818} 823}
819 824
820static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, 825static 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,
1182 const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; 1187 const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
1183 const struct ata_port_info *ppi[PDC_MAX_PORTS]; 1188 const struct ata_port_info *ppi[PDC_MAX_PORTS];
1184 struct ata_host *host; 1189 struct ata_host *host;
1190 struct pdc_host_priv *hpriv;
1185 void __iomem *host_mmio; 1191 void __iomem *host_mmio;
1186 int n_ports, i, rc; 1192 int n_ports, i, rc;
1187 int is_sataii_tx4; 1193 int is_sataii_tx4;
@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
1218 dev_err(&pdev->dev, "failed to allocate host\n"); 1224 dev_err(&pdev->dev, "failed to allocate host\n");
1219 return -ENOMEM; 1225 return -ENOMEM;
1220 } 1226 }
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;
1221 host->iomap = pcim_iomap_table(pdev); 1232 host->iomap = pcim_iomap_table(pdev);
1222 1233
1223 is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); 1234 is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);