* [PATCH 2.6.14-rc1 3/3] Add disk hotswap support to libata RESEND #3
@ 2005-09-15 5:11 Lukasz Kosewski
2005-09-15 14:07 ` Lukasz Kosewski
0 siblings, 1 reply; 3+ messages in thread
From: Lukasz Kosewski @ 2005-09-15 5:11 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-kernel, linux-ide, linux-scsi
[-- Attachment #1: Type: text/plain, Size: 189 bytes --]
Patch 3/3 for libata hotswapping. The sata_promise driver caught red
handed using the new hotswapping API. Depends on patches 1 and 2.
More comments in patch header.
Luke Kosewski
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 03-promise_hotswap_support-2.6.14-rc1.diff --]
[-- Type: text/x-patch; name="03-promise_hotswap_support-2.6.14-rc1.diff", Size: 5638 bytes --]
15.09.05 Luke Kosewski <lkosewsk@nit.ca>
* A patch to sata_promise.c (dependent on patches 1 and 2 in this
series) which makes it use the hotswap API in patch 2. The Promise
controllers are fairly simple in terms of their hotplug mechanism,
so none of the funky 'janitor' functions are used here.
ata_hotplug_plug is called on a plug event, and ata_hotplug_unplug on
an unplug. Simple, simple.
* Pending some confirmation and suggestions from Jim Ramsay
(jim.ramsay@gmail.com) the interrupt handler might change to check for
DMA commands completing as WELL as hotplug events in the same pass.
diff -rpuN linux-2.6.14-rc1/drivers/scsi/sata_promise.c linux-2.6.14-rc1-new/drivers/scsi/sata_promise.c
--- linux-2.6.14-rc1/drivers/scsi/sata_promise.c 2005-09-14 19:57:54.000000000 -0400
+++ linux-2.6.14-rc1-new/drivers/scsi/sata_promise.c 2005-09-14 20:16:09.000000000 -0400
@@ -332,10 +332,43 @@ static void pdc_reset_port(struct ata_po
readl(mmio); /* flush */
}
+/* Mask hotplug interrupts for one channel (ap) */
+static inline void pdc_disable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset + 2;
+
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+}
+
+/* Clear and unmask hotplug interrupts for one channel (ap) */
+static inline void pdc_enable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset;
+
+ //Clear channel hotplug interrupts
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+
+/* Clear and unmask hotplug interrupts for one channel (ap) */
+static inline void pdc_enable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset;
+
+ //Clear channel hotplug interrupts
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+
+ //Unmask channel hotplug interrupts
+ maskflags = readb(mmio + 2);
+ maskflags &= ~(0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio + 2);
+}
+
static void pdc_sata_phy_reset(struct ata_port *ap)
{
pdc_reset_port(ap);
- sata_phy_reset(ap);
+ if (ap->flags & ATA_FLAG_SATA_RESET) {
+ pdc_disable_channel_hotplug_interrupts(ap);
+ sata_phy_reset(ap);
+ pdc_enable_channel_hotplug_interrupts(ap);
+ } else
+ sata_phy_reset(ap);
}
static void pdc_pata_phy_reset(struct ata_port *ap)
@@ -485,11 +518,13 @@ static void pdc_irq_clear(struct ata_por
static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{15.09.05 Luke Kosewski <lkosewsk@nit.ca>
* A patch to add a general-purpose hotswap framework to libata. This is
resend #3 wherein we have a new API! Driver writers call
ata_hotplug_plug or ata_hotplug_unplug when a plug/unplug event
occurs - it takes care of the rest. The idea is to make the sequence
of events as straightforward as possible and not clutter the code
with exceptions; as a result, a series of 'hooks' can be provided at
points in the code for drivers that need it (such as the Silicon
Image drivers which need a reset performed on device removal). See
'hotplug_(un)plug_janitor' for more info.
* This edition is very streamlined. I like it. An area for improvement
might facilitate the removal of the ata_scsi_prepare_qc_abort function
in favour of changes to ata_qc_complete, but that can be up to debate.
struct ata_host_set *host_set = dev_instance;
+ struct pdc_host_priv *hp = host_set->private_data;
struct ata_port *ap;
u32 mask = 0;
unsigned int i, tmp;
- unsigned int handled = 0;
+ unsigned int handled = 0, hotplug_offset = hp->hotplug_offset;
void __iomem *mmio_base;
+ u8 plugdata, maskflags;
VPRINTK("ENTER\n");
@@ -513,7 +548,7 @@ static irqreturn_t pdc_interrupt (int ir
mask &= 0xffff; /* only 16 tags possible */
if (!mask) {
VPRINTK("QUICK EXIT 3\n");
- goto done_irq;
+ goto try_hotplug;
}
writel(mask, mmio_base + PDC_INT_SEQMASK);
@@ -532,7 +567,36 @@ static irqreturn_t pdc_interrupt (int ir
}
}
- VPRINTK("EXIT\n");
+ if (handled) {
+ VPRINTK("EXIT 4\n");
+ goto done_irq;
+ }
+
+try_hotplug:
+ plugdata = readb(mmio_base + hotplug_offset);
+ maskflags = readb(mmio_base + hotplug_offset + 2);
+ plugdata &= ~maskflags;
+ if (plugdata) {
+ writeb(plugdata, mmio_base + hotplug_offset);
+ for (i = 0; i < host_set->n_ports; ++i) {
+ ap = host_set->ports[i];
+ if (!(ap->flags & ATA_FLAG_SATA))
+ continue; //No PATA support here... yet
+ // Check unplug flag
+ if (plugdata & 0x1) {
+ /* Do stuff related to unplugging a device */
+ ata_hotplug_unplug(ap);
+ handled = 1;
+ } else if ((plugdata >> 4) & 0x1) { //Check plug flag
+ /* Do stuff related to plugging in a device */
+ ata_hotplug_plug(ap);
+ handled = 1;
+ }
+ plugdata >>= 1;
+ }
+ }
+
+ VPRINTK("EXIT 5\n");
done_irq:
spin_unlock(&host_set->lock);
@@ -632,9 +696,9 @@ static void pdc_host_init(unsigned int c
tmp = readl(mmio + hotplug_offset);
writel(tmp | 0xff, mmio + hotplug_offset);
- /* mask plug/unplug ints */
+ /* unmask plug/unplug ints */
tmp = readl(mmio + hotplug_offset);
- writel(tmp | 0xff0000, mmio + hotplug_offset);
+ writel(tmp & ~0xff0000, mmio + hotplug_offset);
/* reduce TBG clock to 133 Mhz. */
tmp = readl(mmio + PDC_TBG_MODE);
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 2.6.14-rc1 3/3] Add disk hotswap support to libata RESEND #3
2005-09-15 5:11 [PATCH 2.6.14-rc1 3/3] Add disk hotswap support to libata RESEND #3 Lukasz Kosewski
@ 2005-09-15 14:07 ` Lukasz Kosewski
2005-09-15 15:00 ` Lukasz Kosewski
0 siblings, 1 reply; 3+ messages in thread
From: Lukasz Kosewski @ 2005-09-15 14:07 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-kernel, linux-ide, linux-scsi
[-- Attachment #1: Type: text/plain, Size: 364 bytes --]
On 9/15/05, Lukasz Kosewski <lkosewsk@gmail.com> wrote:
> Patch 3/3 for libata hotswapping. The sata_promise driver caught red
> handed using the new hotswapping API. Depends on patches 1 and 2.
> More comments in patch header.
>
> Luke Kosewski
RESEND! Pulled out the broken comment. Thanks to Robin Johnson for
pointing this out.
Luke Kosewski
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 03-promise_hotswap_support-2.6.14-rc1-FIXED.diff --]
[-- Type: text/x-patch; name="03-promise_hotswap_support-2.6.14-rc1-FIXED.diff", Size: 4770 bytes --]
15.09.05 Luke Kosewski <lkosewsk@nit.ca>
* A patch to sata_promise.c (dependent on patches 1 and 2 in this
series) which makes it use the hotswap API in patch 2. The Promise
controllers are fairly simple in terms of their hotplug mechanism,
so none of the funky 'janitor' functions are used here.
ata_hotplug_plug is called on a plug event, and ata_hotplug_unplug on
an unplug. Simple, simple.
* Pending some confirmation and suggestions from Jim Ramsay
(jim.ramsay@gmail.com) the interrupt handler might change to check for
DMA commands completing as WELL as hotplug events in the same pass.
diff -rpuN linux-2.6.14-rc1/drivers/scsi/sata_promise.c linux-2.6.14-rc1-new/drivers/scsi/sata_promise.c
--- linux-2.6.14-rc1/drivers/scsi/sata_promise.c 2005-09-14 19:57:54.000000000 -0400
+++ linux-2.6.14-rc1-new/drivers/scsi/sata_promise.c 2005-09-14 20:16:09.000000000 -0400
@@ -332,10 +332,43 @@ static void pdc_reset_port(struct ata_po
readl(mmio); /* flush */
}
+/* Mask hotplug interrupts for one channel (ap) */
+static inline void pdc_disable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset + 2;
+
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+}
+
+/* Clear and unmask hotplug interrupts for one channel (ap) */
+static inline void pdc_enable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset;
+
+ //Clear channel hotplug interrupts
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+
+/* Clear and unmask hotplug interrupts for one channel (ap) */
+static inline void pdc_enable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset;
+
+ //Clear channel hotplug interrupts
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+
+ //Unmask channel hotplug interrupts
+ maskflags = readb(mmio + 2);
+ maskflags &= ~(0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio + 2);
+}
+
static void pdc_sata_phy_reset(struct ata_port *ap)
{
pdc_reset_port(ap);
- sata_phy_reset(ap);
+ if (ap->flags & ATA_FLAG_SATA_RESET) {
+ pdc_disable_channel_hotplug_interrupts(ap);
+ sata_phy_reset(ap);
+ pdc_enable_channel_hotplug_interrupts(ap);
+ } else
+ sata_phy_reset(ap);
}
static void pdc_pata_phy_reset(struct ata_port *ap)
@@ -485,11 +518,13 @@ static void pdc_irq_clear(struct ata_por
static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
+ struct pdc_host_priv *hp = host_set->private_data;
struct ata_port *ap;
u32 mask = 0;
unsigned int i, tmp;
- unsigned int handled = 0;
+ unsigned int handled = 0, hotplug_offset = hp->hotplug_offset;
void __iomem *mmio_base;
+ u8 plugdata, maskflags;
VPRINTK("ENTER\n");
@@ -513,7 +548,7 @@ static irqreturn_t pdc_interrupt (int ir
mask &= 0xffff; /* only 16 tags possible */
if (!mask) {
VPRINTK("QUICK EXIT 3\n");
- goto done_irq;
+ goto try_hotplug;
}
writel(mask, mmio_base + PDC_INT_SEQMASK);
@@ -532,7 +567,36 @@ static irqreturn_t pdc_interrupt (int ir
}
}
- VPRINTK("EXIT\n");
+ if (handled) {
+ VPRINTK("EXIT 4\n");
+ goto done_irq;
+ }
+
+try_hotplug:
+ plugdata = readb(mmio_base + hotplug_offset);
+ maskflags = readb(mmio_base + hotplug_offset + 2);
+ plugdata &= ~maskflags;
+ if (plugdata) {
+ writeb(plugdata, mmio_base + hotplug_offset);
+ for (i = 0; i < host_set->n_ports; ++i) {
+ ap = host_set->ports[i];
+ if (!(ap->flags & ATA_FLAG_SATA))
+ continue; //No PATA support here... yet
+ // Check unplug flag
+ if (plugdata & 0x1) {
+ /* Do stuff related to unplugging a device */
+ ata_hotplug_unplug(ap);
+ handled = 1;
+ } else if ((plugdata >> 4) & 0x1) { //Check plug flag
+ /* Do stuff related to plugging in a device */
+ ata_hotplug_plug(ap);
+ handled = 1;
+ }
+ plugdata >>= 1;
+ }
+ }
+
+ VPRINTK("EXIT 5\n");
done_irq:
spin_unlock(&host_set->lock);
@@ -632,9 +696,9 @@ static void pdc_host_init(unsigned int c
tmp = readl(mmio + hotplug_offset);
writel(tmp | 0xff, mmio + hotplug_offset);
- /* mask plug/unplug ints */
+ /* unmask plug/unplug ints */
tmp = readl(mmio + hotplug_offset);
- writel(tmp | 0xff0000, mmio + hotplug_offset);
+ writel(tmp & ~0xff0000, mmio + hotplug_offset);
/* reduce TBG clock to 133 Mhz. */
tmp = readl(mmio + PDC_TBG_MODE);
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 2.6.14-rc1 3/3] Add disk hotswap support to libata RESEND #3
2005-09-15 14:07 ` Lukasz Kosewski
@ 2005-09-15 15:00 ` Lukasz Kosewski
0 siblings, 0 replies; 3+ messages in thread
From: Lukasz Kosewski @ 2005-09-15 15:00 UTC (permalink / raw)
To: Jeff Garzik; +Cc: linux-kernel, linux-ide, linux-scsi
[-- Attachment #1: Type: text/plain, Size: 680 bytes --]
RESEND #2! Nobody should trust me with anything ever. This ACTUALLY
fixes the patch so it... errrm... compiles. I really should never
have added comments. Or should have patched after adding comments.
Luke Kosewski
On 9/15/05, Lukasz Kosewski <lkosewsk@gmail.com> wrote:
> On 9/15/05, Lukasz Kosewski <lkosewsk@gmail.com> wrote:
> > Patch 3/3 for libata hotswapping. The sata_promise driver caught red
> > handed using the new hotswapping API. Depends on patches 1 and 2.
> > More comments in patch header.
> >
> > Luke Kosewski
>
> RESEND! Pulled out the broken comment. Thanks to Robin Johnson for
> pointing this out.
>
> Luke Kosewski
>
>
>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 03-promise_hotswap_support-2.6.14-rc1-FIXED-2.diff --]
[-- Type: text/x-patch; name="03-promise_hotswap_support-2.6.14-rc1-FIXED-2.diff", Size: 4361 bytes --]
15.09.05 Luke Kosewski <lkosewsk@nit.ca>
* A patch to sata_promise.c (dependent on patches 1 and 2 in this
series) which makes it use the hotswap API in patch 2. The Promise
controllers are fairly simple in terms of their hotplug mechanism,
so none of the funky 'janitor' functions are used here.
ata_hotplug_plug is called on a plug event, and ata_hotplug_unplug on
an unplug. Simple, simple.
* Pending some confirmation and suggestions from Jim Ramsay
(jim.ramsay@gmail.com) the interrupt handler might change to check for
DMA commands completing as WELL as hotplug events in the same pass.
diff -rpuN linux-2.6.14-rc1/drivers/scsi/sata_promise.c linux-2.6.14-rc1-new/drivers/scsi/sata_promise.c
--- linux-2.6.14-rc1/drivers/scsi/sata_promise.c 2005-09-14 19:57:54.000000000 -0400
+++ linux-2.6.14-rc1-new/drivers/scsi/sata_promise.c 2005-09-14 20:16:09.000000000 -0400
@@ -332,10 +332,43 @@ static void pdc_reset_port(struct ata_po
readl(mmio); /* flush */
}
+/* Mask hotplug interrupts for one channel (ap) */
+static inline void pdc_disable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset + 2;
+
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+}
+
+/* Clear and unmask hotplug interrupts for one channel (ap) */
+static inline void pdc_enable_channel_hotplug_interrupts(struct ata_port *ap)
+{
+ struct pdc_host_priv *hp = ap->host_set->private_data;
+ void *mmio = ap->host_set->mmio_base + hp->hotplug_offset;
+
+ //Clear channel hotplug interrupts
+ u8 maskflags = readb(mmio);
+ maskflags |= (0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio);
+
+ //Unmask channel hotplug interrupts
+ maskflags = readb(mmio + 2);
+ maskflags &= ~(0x11 << (u8)ap->hard_port_no);
+ writeb(maskflags, mmio + 2);
+}
+
static void pdc_sata_phy_reset(struct ata_port *ap)
{
pdc_reset_port(ap);
- sata_phy_reset(ap);
+ if (ap->flags & ATA_FLAG_SATA_RESET) {
+ pdc_disable_channel_hotplug_interrupts(ap);
+ sata_phy_reset(ap);
+ pdc_enable_channel_hotplug_interrupts(ap);
+ } else
+ sata_phy_reset(ap);
}
static void pdc_pata_phy_reset(struct ata_port *ap)
@@ -485,11 +518,13 @@ static void pdc_irq_clear(struct ata_por
static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
+ struct pdc_host_priv *hp = host_set->private_data;
struct ata_port *ap;
u32 mask = 0;
unsigned int i, tmp;
- unsigned int handled = 0;
+ unsigned int handled = 0, hotplug_offset = hp->hotplug_offset;
void __iomem *mmio_base;
+ u8 plugdata, maskflags;
VPRINTK("ENTER\n");
@@ -513,7 +548,7 @@ static irqreturn_t pdc_interrupt (int ir
mask &= 0xffff; /* only 16 tags possible */
if (!mask) {
VPRINTK("QUICK EXIT 3\n");
- goto done_irq;
+ goto try_hotplug;
}
writel(mask, mmio_base + PDC_INT_SEQMASK);
@@ -532,7 +567,36 @@ static irqreturn_t pdc_interrupt (int ir
}
}
- VPRINTK("EXIT\n");
+ if (handled) {
+ VPRINTK("EXIT 4\n");
+ goto done_irq;
+ }
+
+try_hotplug:
+ plugdata = readb(mmio_base + hotplug_offset);
+ maskflags = readb(mmio_base + hotplug_offset + 2);
+ plugdata &= ~maskflags;
+ if (plugdata) {
+ writeb(plugdata, mmio_base + hotplug_offset);
+ for (i = 0; i < host_set->n_ports; ++i) {
+ ap = host_set->ports[i];
+ if (!(ap->flags & ATA_FLAG_SATA))
+ continue; //No PATA support here... yet
+ // Check unplug flag
+ if (plugdata & 0x1) {
+ /* Do stuff related to unplugging a device */
+ ata_hotplug_unplug(ap);
+ handled = 1;
+ } else if ((plugdata >> 4) & 0x1) { //Check plug flag
+ /* Do stuff related to plugging in a device */
+ ata_hotplug_plug(ap);
+ handled = 1;
+ }
+ plugdata >>= 1;
+ }
+ }
+
+ VPRINTK("EXIT 5\n");
done_irq:
spin_unlock(&host_set->lock);
@@ -632,9 +696,9 @@ static void pdc_host_init(unsigned int c
tmp = readl(mmio + hotplug_offset);
writel(tmp | 0xff, mmio + hotplug_offset);
- /* mask plug/unplug ints */
+ /* unmask plug/unplug ints */
tmp = readl(mmio + hotplug_offset);
- writel(tmp | 0xff0000, mmio + hotplug_offset);
+ writel(tmp & ~0xff0000, mmio + hotplug_offset);
/* reduce TBG clock to 133 Mhz. */
tmp = readl(mmio + PDC_TBG_MODE);
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-09-15 15:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-15 5:11 [PATCH 2.6.14-rc1 3/3] Add disk hotswap support to libata RESEND #3 Lukasz Kosewski
2005-09-15 14:07 ` Lukasz Kosewski
2005-09-15 15:00 ` Lukasz Kosewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).