* [PATCH 1/3] libata: implement hotplug by polling
2006-07-17 7:00 [RFT][PATCHSET] hotplug polling, take 3 Tejun Heo
@ 2006-07-17 7:00 ` Tejun Heo
2006-07-19 20:57 ` Jeff Garzik
2006-07-17 7:00 ` [PATCH 2/3] libata: add hp-poll support to controllers with hotplug interrutps Tejun Heo
2006-07-17 7:00 ` [PATCH 3/3] libata: add hp-poll support to controllers without hotplug interrupts Tejun Heo
2 siblings, 1 reply; 11+ messages in thread
From: Tejun Heo @ 2006-07-17 7:00 UTC (permalink / raw)
To: jgarzik, alan, lkml, axboe, forrest.zhao, linux-ide; +Cc: Tejun Heo
This patch implements hotplug by polling - hp-poll. It is used for
* hotplug event detection on controllers which don't provide PHY
status changed interrupt.
* hotplug event detection on disabled ports after reset failure.
libata used to leave such ports in frozen state to protect the
system from malfunctioning controller/device. With hp-poll, hotplug
events no such ports are watched safely by polling, such that
removing/replacing the malfunctioning device triggers EH retry on
the port.
There are three port ops for hp-poll - hp_poll_activate, hp_poll,
hp_poll_deactivate. Only hp_poll is mandatory for hp-poll to work.
This patch also implements SATA standard polling callbacks which poll
SError.N/X bits - sata_std_hp_poll_activate() and sata_std_hp_poll().
By default, hp-poll is enabled only on disabled ports. If a LLD
doesn't support hotplug interrupts but can poll for hotplug events, it
should indicate it by setting ATA_FLAG_HP_POLLING which tells libata
to turn on hp-poll by default.
Putting port into any static powersave mode or setting
libata.hotplug_polling_interval to zero disables hp-poll.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 92 ++++++++++++++++++++++++++++
drivers/scsi/libata-eh.c | 143 +++++++++++++++++++++++++++++++++++++++++++-
drivers/scsi/libata.h | 5 ++
include/linux/libata.h | 10 +++
4 files changed, 246 insertions(+), 4 deletions(-)
5cc3fdf67263ca76fc930ab9400a26fb637b18ae
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9890387..f1db8d4 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3082,6 +3082,86 @@ void sata_std_set_powersave(struct ata_p
}
/**
+ * sata_std_hp_poll_activate - standard SATA hotplug polling activation
+ * @ap: the target ata_port
+ *
+ * Activate SATA std hotplug polling.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+void sata_std_hp_poll_activate(struct ata_port *ap)
+{
+ u32 serror, mask;
+
+ /* watch .X and, if not in dynamic powersave, .N */
+ mask = SERR_DEV_XCHG;
+ if (ata_ps_dynamic(ap->ps_state) == ATA_PS_NONE)
+ mask |= SERR_PHYRDY_CHG;
+
+ sata_scr_read(ap, SCR_ERROR, &serror);
+ serror &= mask;
+ if (serror)
+ sata_scr_write(ap, SCR_ERROR, serror);
+
+ ap->hp_poll_data = 0;
+}
+
+/**
+ * sata_std_hp_poll - standard SATA hotplug polling callback
+ * @ap: the target ata_port
+ *
+ * Poll SError.N/X for hotplug event. Hotplug event is triggered
+ * only after PHY stays stable for at least one full polling
+ * interval after the first event detection.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
+ * RETURNS:
+ * 1 if hotplug event has occurred, 0 otherwise.
+ */
+int sata_std_hp_poll(struct ata_port *ap)
+{
+ unsigned long state = (unsigned long)ap->hp_poll_data;
+ u32 serror, mask;
+ int rc = 0;
+
+ /* watch .X and, if not in dynamic powersave, .N */
+ mask = SERR_DEV_XCHG;
+ if (ata_ps_dynamic(ap->ps_state) == ATA_PS_NONE)
+ mask |= SERR_PHYRDY_CHG;
+
+ sata_scr_read(ap, SCR_ERROR, &serror);
+ serror &= mask;
+
+ switch (state) {
+ case 0:
+ if (serror) {
+ /* PHY status could be bouncing crazy due to
+ * faulty controller or device. Don't fire
+ * hotplug event till hotplug event stays
+ * quiescent for one full polling interval.
+ */
+ sata_scr_write(ap, SCR_ERROR, serror);
+ state = 1;
+ }
+ break;
+
+ case 1:
+ if (!serror)
+ rc = 1;
+ else
+ sata_scr_write(ap, SCR_ERROR, serror);
+ break;
+ }
+
+ ap->hp_poll_data = (void *)(unsigned long)state;
+
+ return rc;
+}
+
+/**
* ata_dev_same_device - Determine whether new ID matches configured device
* @dev: device to compare against
* @new_class: class of the new device
@@ -5798,6 +5878,7 @@ #endif
INIT_LIST_HEAD(&ap->eh_done_q);
init_waitqueue_head(&ap->eh_wait_q);
setup_timer(&ap->ps_timer, ata_ps_timer_worker, (unsigned long)ap);
+ INIT_LIST_HEAD(&ap->hp_poll_entry);
/* set cable type */
ap->cbl = ATA_CBL_NONE;
@@ -6119,6 +6200,9 @@ void ata_port_detach(struct ata_port *ap
list_del_init(&ap->all_ports_entry);
mutex_unlock(&ata_all_ports_mutex);
+ /* deactivate hotplug polling */
+ ata_hp_poll_deactivate(ap);
+
/* remove the associated SCSI host */
scsi_remove_host(ap->host);
}
@@ -6365,6 +6449,12 @@ static int __init ata_init(void)
static void __exit ata_exit(void)
{
+ /* hp_poll_list gotta be empty by now and thus hp_poll_work
+ * isn't rearming.
+ */
+ WARN_ON(!list_empty(&hp_poll_list));
+ cancel_delayed_work(&hp_poll_work);
+
destroy_workqueue(ata_wq);
destroy_workqueue(ata_aux_wq);
}
@@ -6504,6 +6594,8 @@ EXPORT_SYMBOL_GPL(sata_std_hips_timer_fn
EXPORT_SYMBOL_GPL(sata_do_set_powersave);
EXPORT_SYMBOL_GPL(sata_determine_hips_params);
EXPORT_SYMBOL_GPL(sata_std_set_powersave);
+EXPORT_SYMBOL_GPL(sata_std_hp_poll_activate);
+EXPORT_SYMBOL_GPL(sata_std_hp_poll);
EXPORT_SYMBOL_GPL(ata_dev_revalidate);
EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_pair);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index b19eaae..f9d9bb7 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -34,6 +34,8 @@
#include <linux/config.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_eh.h>
@@ -45,6 +47,17 @@ #include <linux/libata.h>
#include "libata.h"
+static unsigned long hotplug_polling_interval = 2000;
+module_param(hotplug_polling_interval, ulong, 0644);
+MODULE_PARM_DESC(hotplug_polling_interval, "Hotplug polling interval "
+ "(milliseconds, default 2000, 0 to disable)");
+
+static void ata_hp_poll_worker(void *data);
+
+static DEFINE_MUTEX(hp_poll_mutex);
+struct list_head hp_poll_list = LIST_HEAD_INIT(hp_poll_list);
+DECLARE_WORK(hp_poll_work, ata_hp_poll_worker, NULL);
+
static void __ata_port_freeze(struct ata_port *ap);
static void ata_eh_finish(struct ata_port *ap);
static void ata_eh_handle_port_suspend(struct ata_port *ap);
@@ -628,7 +641,10 @@ int ata_port_freeze(struct ata_port *ap)
* ata_eh_freeze_port - EH helper to freeze port
* @ap: ATA port to freeze
*
- * Freeze @ap.
+ * Freeze @ap. As the 'freeze' operation means 'shutdown event
+ * reporting', it is a perfect place to deactivate hp-poll. Note
+ * that ata_port_freeze() always invokes EH and eventually this
+ * function, so deactivating hp-poll in this function is enough.
*
* LOCKING:
* None.
@@ -640,6 +656,8 @@ void ata_eh_freeze_port(struct ata_port
if (!ap->ops->error_handler)
return;
+ ata_hp_poll_deactivate(ap);
+
spin_lock_irqsave(ap->lock, flags);
__ata_port_freeze(ap);
spin_unlock_irqrestore(ap->lock, flags);
@@ -649,7 +667,7 @@ void ata_eh_freeze_port(struct ata_port
* ata_port_thaw_port - EH helper to thaw port
* @ap: ATA port to thaw
*
- * Thaw frozen port @ap.
+ * Thaw frozen port @ap and activate hp-poll if necessary.
*
* LOCKING:
* None.
@@ -670,6 +688,9 @@ void ata_eh_thaw_port(struct ata_port *a
spin_unlock_irqrestore(ap->lock, flags);
+ if (ap->flags & ATA_FLAG_HP_POLLING)
+ ata_hp_poll_activate(ap);
+
DPRINTK("ata%u port thawed\n", ap->id);
}
@@ -1926,8 +1947,12 @@ static int ata_eh_set_powersave(struct a
/* At this point, we're in ATA_PS_NONE state and DIPS setting
* is unknown. Execute the requested PS state transition.
*/
- if (ps_state && set_ps)
- set_ps(ap, ps_state);
+ if (ps_state) {
+ if (set_ps)
+ set_ps(ap, ps_state);
+ if (ata_ps_static(ps_state))
+ ata_hp_poll_deactivate(ap);
+ }
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
@@ -2172,6 +2197,9 @@ static int ata_eh_recover(struct ata_por
out:
if (rc) {
+ /* recovery failed, activate hp-poll */
+ ata_hp_poll_activate(ap);
+
for (i = 0; i < ATA_MAX_DEVICES; i++)
ata_dev_disable(&ap->device[i]);
}
@@ -2360,3 +2388,110 @@ static void ata_eh_handle_port_resume(st
}
spin_unlock_irqrestore(ap->lock, flags);
}
+
+static void ata_hp_poll_worker(void *data)
+{
+ unsigned long interval = msec_to_jiffies(hotplug_polling_interval);
+ unsigned long flags = 0; /* shut up, gcc */
+ struct ata_port *ap, *next;
+ spinlock_t *held_lock = NULL;
+
+ mutex_lock(&hp_poll_mutex);
+
+ list_for_each_entry_safe(ap, next, &hp_poll_list, hp_poll_entry) {
+ int rc;
+
+ /* Ports sharing a lock are registered sequentially.
+ * Cache locking.
+ */
+ if (ap->lock != held_lock) {
+ if (held_lock)
+ spin_unlock_irqrestore(held_lock, flags);
+ spin_lock_irqsave(ap->lock, flags);
+ held_lock = ap->lock;
+ }
+
+ /* Poll. Positive return value indicates hotplug
+ * event while negative indicates error condition.
+ */
+ rc = ap->ops->hp_poll(ap);
+ if (rc) {
+ if (rc > 0) {
+ ata_ehi_hotplugged(&ap->eh_info);
+ ata_port_freeze(ap);
+ }
+ list_del_init(&ap->hp_poll_entry);
+ }
+ }
+
+ if (held_lock)
+ spin_unlock_irqrestore(held_lock, flags);
+
+ if (!list_empty(&hp_poll_list) && interval)
+ schedule_delayed_work(&hp_poll_work, interval);
+
+ mutex_unlock(&hp_poll_mutex);
+}
+
+/**
+ * ata_hp_poll_activate - activate hotplug polling
+ * @ap: host port to activate hotplug polling for
+ *
+ * Activate hotplug probing for @ap.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+void ata_hp_poll_activate(struct ata_port *ap)
+{
+ unsigned long interval = msec_to_jiffies(hotplug_polling_interval);
+ struct list_head *pos;
+
+ if (!ap->ops->hp_poll || !hotplug_polling_interval ||
+ !list_empty(&ap->hp_poll_entry))
+ return;
+
+ if (ap->ops->hp_poll_activate)
+ ap->ops->hp_poll_activate(ap);
+
+ mutex_lock(&hp_poll_mutex);
+
+ if (list_empty(&hp_poll_list) && interval)
+ schedule_delayed_work(&hp_poll_work, interval);
+
+ /* group poll entries by lock to cache locking when polling */
+ list_for_each(pos, &hp_poll_list) {
+ struct ata_port *pos_ap =
+ list_entry(pos, struct ata_port, hp_poll_entry);
+
+ if (ap->lock == pos_ap->lock)
+ break;
+ }
+
+ list_add(&ap->hp_poll_entry, pos);
+ ap->hp_poll_data = 0;
+
+ mutex_unlock(&hp_poll_mutex);
+}
+
+/**
+ * ata_hp_poll_deactivate - deactivate hotplug polling
+ * @ap: host port to deactivate hotplug polling for
+ *
+ * Deactivate hotplug probing for @ap.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+void ata_hp_poll_deactivate(struct ata_port *ap)
+{
+ if (list_empty(&ap->hp_poll_entry))
+ return;
+
+ mutex_lock(&hp_poll_mutex);
+ list_del_init(&ap->hp_poll_entry);
+ mutex_unlock(&hp_poll_mutex);
+
+ if (ap->ops->hp_poll_deactivate)
+ ap->ops->hp_poll_deactivate(ap);
+}
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 9e44f56..bc71b3f 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -118,9 +118,14 @@ extern void ata_schedule_scsi_eh(struct
extern void ata_scsi_dev_rescan(void *data);
/* libata-eh.c */
+extern struct list_head hp_poll_list;
+extern struct work_struct hp_poll_work;
+
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_port_wait_eh(struct ata_port *ap);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
+extern void ata_hp_poll_activate(struct ata_port *ap);
+extern void ata_hp_poll_deactivate(struct ata_port *ap);
#endif /* __LIBATA_H__ */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b8bee5f..39d6186 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -164,6 +164,7 @@ enum {
ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_HIPS = (1 << 14), /* SATA host-initiated powersave */
ATA_FLAG_DIPS = (1 << 15), /* SATA dev-initiated powersave */
+ ATA_FLAG_HP_POLLING = (1 << 16), /* hotplug by polling */
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
@@ -586,6 +587,9 @@ struct ata_port {
struct list_head all_ports_entry;
+ struct list_head hp_poll_entry; /* hotplug poll list entry */
+ void *hp_poll_data;
+
void *private_data;
u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */
@@ -633,6 +637,10 @@ struct ata_port_operations {
void (*error_handler) (struct ata_port *ap);
void (*post_internal_cmd) (struct ata_queued_cmd *qc);
+ void (*hp_poll_activate) (struct ata_port *ap);
+ void (*hp_poll_deactivate) (struct ata_port *ap);
+ int (*hp_poll) (struct ata_port *ap);
+
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *);
@@ -702,6 +710,8 @@ extern int ata_std_prereset(struct ata_p
extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
+extern void sata_std_hp_poll_activate(struct ata_port *ap);
+extern int sata_std_hp_poll(struct ata_port *ap);
extern unsigned long sata_do_hips_timer_fn(struct ata_port *ap, int seq,
u8 sctl_ipm, ata_update_sctl_spm_fn_t update_sctl_spm);
extern unsigned long sata_std_hips_timer_fn(struct ata_port *ap, int seq);
--
1.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 1/3] libata: implement hotplug by polling
2006-07-17 7:00 ` [PATCH 1/3] libata: implement hotplug by polling Tejun Heo
@ 2006-07-19 20:57 ` Jeff Garzik
2006-07-24 7:06 ` Tejun Heo
0 siblings, 1 reply; 11+ messages in thread
From: Jeff Garzik @ 2006-07-19 20:57 UTC (permalink / raw)
To: Tejun Heo; +Cc: alan, lkml, axboe, forrest.zhao, linux-ide
Tejun Heo wrote:
> This patch implements hotplug by polling - hp-poll. It is used for
>
> * hotplug event detection on controllers which don't provide PHY
> status changed interrupt.
>
> * hotplug event detection on disabled ports after reset failure.
> libata used to leave such ports in frozen state to protect the
> system from malfunctioning controller/device. With hp-poll, hotplug
> events no such ports are watched safely by polling, such that
> removing/replacing the malfunctioning device triggers EH retry on
> the port.
>
> There are three port ops for hp-poll - hp_poll_activate, hp_poll,
> hp_poll_deactivate. Only hp_poll is mandatory for hp-poll to work.
> This patch also implements SATA standard polling callbacks which poll
> SError.N/X bits - sata_std_hp_poll_activate() and sata_std_hp_poll().
>
> By default, hp-poll is enabled only on disabled ports. If a LLD
> doesn't support hotplug interrupts but can poll for hotplug events, it
> should indicate it by setting ATA_FLAG_HP_POLLING which tells libata
> to turn on hp-poll by default.
>
> Putting port into any static powersave mode or setting
> libata.hotplug_polling_interval to zero disables hp-poll.
>
> Signed-off-by: Tejun Heo <htejun@gmail.com>
NAK, there is no reason why a global poll list is needed. Simply having
a struct workqueue in each schedule-able entity implicitly creates such
a list. But regardless, this is another example of adding
cross-controller synchronization, where none is needed.
If the worker fired per-host_set, then you could use an ata_port dynamic
flag to indicate the poll-active ports, for the ata_hp_poll_worker() loop.
If the worker fires per-port, then no loop or mutex is needed at all.
You could simply call the hp_poll hook.
> @@ -633,6 +637,10 @@ struct ata_port_operations {
> void (*error_handler) (struct ata_port *ap);
> void (*post_internal_cmd) (struct ata_queued_cmd *qc);
>
> + void (*hp_poll_activate) (struct ata_port *ap);
> + void (*hp_poll_deactivate) (struct ata_port *ap);
> + int (*hp_poll) (struct ata_port *ap);
> +
> irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
> void (*irq_clear) (struct ata_port *);
>
All new hooks require at least a one-two sentence description in the
DocBook docs, telling driver writers how to use them.
Jeff
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 1/3] libata: implement hotplug by polling
2006-07-19 20:57 ` Jeff Garzik
@ 2006-07-24 7:06 ` Tejun Heo
0 siblings, 0 replies; 11+ messages in thread
From: Tejun Heo @ 2006-07-24 7:06 UTC (permalink / raw)
To: Jeff Garzik; +Cc: alan, lkml, axboe, forrest.zhao, linux-ide
Jeff Garzik wrote:
> NAK, there is no reason why a global poll list is needed. Simply having
> a struct workqueue in each schedule-able entity implicitly creates such
> a list. But regardless, this is another example of adding
> cross-controller synchronization, where none is needed.
>
> If the worker fired per-host_set, then you could use an ata_port dynamic
> flag to indicate the poll-active ports, for the ata_hp_poll_worker() loop.
>
> If the worker fires per-port, then no loop or mutex is needed at all.
> You could simply call the hp_poll hook.
It was basically an optimization to reduce storage usage and spread all
polling operations at least by polling interval even when there are many
ports to poll. Cross-port synchronization aside, it's very simple too.
Hmm... I don't think it makes much difference either way though. I'll
convert to per-port workqueue + timer.
>> @@ -633,6 +637,10 @@ struct ata_port_operations {
>> void (*error_handler) (struct ata_port *ap);
>> void (*post_internal_cmd) (struct ata_queued_cmd *qc);
>>
>> + void (*hp_poll_activate) (struct ata_port *ap);
>> + void (*hp_poll_deactivate) (struct ata_port *ap);
>> + int (*hp_poll) (struct ata_port *ap);
>> +
>> irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
>> void (*irq_clear) (struct ata_port *);
>>
>
> All new hooks require at least a one-two sentence description in the
> DocBook docs, telling driver writers how to use them.
Will do.
--
tejun
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/3] libata: add hp-poll support to controllers with hotplug interrutps
2006-07-17 7:00 [RFT][PATCHSET] hotplug polling, take 3 Tejun Heo
2006-07-17 7:00 ` [PATCH 1/3] libata: implement hotplug by polling Tejun Heo
@ 2006-07-17 7:00 ` Tejun Heo
2006-07-17 7:00 ` [PATCH 3/3] libata: add hp-poll support to controllers without hotplug interrupts Tejun Heo
2 siblings, 0 replies; 11+ messages in thread
From: Tejun Heo @ 2006-07-17 7:00 UTC (permalink / raw)
To: jgarzik, alan, lkml, axboe, forrest.zhao, linux-ide; +Cc: Tejun Heo
This patch adds hp-poll support to the following drivers.
* ahci
* sata_nv (nf2 and c804 only)
* sata_sil
* sata_sil24
All the above controllers are capable of hotplug-by-interrupt and
hp-poll will be used only for watching disabled ports.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/ahci.c | 3 +++
drivers/scsi/sata_nv.c | 4 ++++
drivers/scsi/sata_sil.c | 2 ++
drivers/scsi/sata_sil24.c | 3 +++
4 files changed, 12 insertions(+), 0 deletions(-)
a7fe2cefdb1abfed43df9e12c3f05d885638b07b
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index b5fe19a..9fc2e57 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -261,6 +261,9 @@ static const struct ata_port_operations
.error_handler = ahci_error_handler,
.post_internal_cmd = ahci_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.set_powersave = ahci_set_powersave,
.port_start = ahci_port_start,
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 56da255..cdf3b65 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -216,6 +216,8 @@ static const struct ata_port_operations
.thaw = nv_nf2_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_nf2_interrupt,
.irq_clear = ata_bmdma_irq_clear,
@@ -243,6 +245,8 @@ static const struct ata_port_operations
.thaw = nv_ck804_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_ck804_interrupt,
.irq_clear = ata_bmdma_irq_clear,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index d0a8507..62deca4 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -205,6 +205,8 @@ static const struct ata_port_operations
.thaw = sil_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.irq_handler = sil_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = sil_scr_read,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 0b5c3f1..0c1f082 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -407,6 +407,9 @@ static const struct ata_port_operations
.error_handler = sil24_error_handler,
.post_internal_cmd = sil24_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.set_powersave = sil24_set_powersave,
.port_start = sil24_port_start,
--
1.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/3] libata: add hp-poll support to controllers without hotplug interrupts
2006-07-17 7:00 [RFT][PATCHSET] hotplug polling, take 3 Tejun Heo
2006-07-17 7:00 ` [PATCH 1/3] libata: implement hotplug by polling Tejun Heo
2006-07-17 7:00 ` [PATCH 2/3] libata: add hp-poll support to controllers with hotplug interrutps Tejun Heo
@ 2006-07-17 7:00 ` Tejun Heo
2006-07-19 20:57 ` Jeff Garzik
2 siblings, 1 reply; 11+ messages in thread
From: Tejun Heo @ 2006-07-17 7:00 UTC (permalink / raw)
To: jgarzik, alan, lkml, axboe, forrest.zhao, linux-ide; +Cc: Tejun Heo
This patch adds hp-poll support to the following drivers.
* sata_nv (generic)
* sata_sis
* sata_svw
* sata_uli
* sata_via
* sata_vsc
All the above drivers currently don't support hotplug interrupts (H/W
restrictions or lack of doc/effort) and all hotplug operations should
be done via hp-poll; thus, ATA_FLAG_HP_POLLING is set for these
drivers.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/sata_nv.c | 5 ++++-
drivers/scsi/sata_sis.c | 5 ++++-
drivers/scsi/sata_svw.c | 4 +++-
drivers/scsi/sata_uli.c | 6 +++++-
drivers/scsi/sata_vsc.c | 4 +++-
5 files changed, 19 insertions(+), 5 deletions(-)
3a5e2866b5e69d113c1a7740969b9847ed41b545
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index cdf3b65..7bd9305 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -189,6 +189,8 @@ static const struct ata_port_operations
.thaw = ata_bmdma_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_generic_interrupt,
.irq_clear = ata_bmdma_irq_clear,
@@ -261,7 +263,8 @@ static struct ata_port_info nv_port_info
/* generic */
{
.sht = &nv_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_HP_POLLING,
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index ee6b5df..3b4bc5a 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -117,6 +117,8 @@ static const struct ata_port_operations
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = sis_scr_read,
@@ -128,7 +130,8 @@ static const struct ata_port_operations
static struct ata_port_info sis_port_info = {
.sht = &sis_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_HP_POLLING,
.pio_mask = 0x1f,
.mwdma_mask = 0x7,
.udma_mask = 0x7f,
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 7d08580..9a446ad 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -324,6 +324,8 @@ static const struct ata_port_operations
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = k2_sata_scr_read,
@@ -424,7 +426,7 @@ static int k2_sata_init_one (struct pci_
probe_ent->sht = &k2_sata_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_MMIO;
+ ATA_FLAG_MMIO | ATA_FLAG_HP_POLLING;
probe_ent->port_ops = &k2_sata_ops;
probe_ent->n_ports = 4;
probe_ent->irq = pdev->irq;
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 33cdb48..d3ab9ed 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -115,6 +115,9 @@ static const struct ata_port_operations
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
@@ -128,7 +131,8 @@ static const struct ata_port_operations
static struct ata_port_info uli_port_info = {
.sht = &uli_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_HP_POLLING,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &uli_ops,
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index ad37871..d7da4c2 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -302,6 +302,8 @@ static const struct ata_port_operations
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.irq_handler = vsc_sata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = vsc_sata_scr_read,
@@ -396,7 +398,7 @@ static int __devinit vsc_sata_init_one (
probe_ent->sht = &vsc_sata_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_MMIO;
+ ATA_FLAG_MMIO | ATA_FLAG_HP_POLLING;
probe_ent->port_ops = &vsc_sata_ops;
probe_ent->n_ports = 4;
probe_ent->irq = pdev->irq;
--
1.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] libata: add hp-poll support to controllers with hotplug interrutps
2006-07-05 6:06 [RFT][PATCHSET] hotplug polling, take 2 Tejun Heo
@ 2006-07-05 6:06 ` Tejun Heo
0 siblings, 0 replies; 11+ messages in thread
From: Tejun Heo @ 2006-07-05 6:06 UTC (permalink / raw)
To: jgarzik, lkml, axboe, forrest.zhao, alan, linux-ide; +Cc: Tejun Heo
This patch adds hp-poll support to the following drivers.
* ahci
* sata_nv (nf2 and c804 only)
* sata_sil
* sata_sil24
All the above controllers are capable of hotplug-by-interrupt and
hp-poll will be used only for watching disabled ports.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/ahci.c | 4 +++-
drivers/scsi/sata_nv.c | 4 ++++
drivers/scsi/sata_sil.c | 2 ++
drivers/scsi/sata_sil24.c | 3 +++
4 files changed, 12 insertions(+), 1 deletions(-)
4faf1e519f3a190b35a03fc21be1d4027ac3e499
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 54f01b2..a404ec0 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -253,10 +253,12 @@ static const struct ata_port_operations
.freeze = ahci_freeze,
.thaw = ahci_thaw,
-
.error_handler = ahci_error_handler,
.post_internal_cmd = ahci_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
};
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 5cc42c6..79b0550 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -217,6 +217,8 @@ static const struct ata_port_operations
.thaw = nv_nf2_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_nf2_interrupt,
.irq_clear = ata_bmdma_irq_clear,
@@ -244,6 +246,8 @@ static const struct ata_port_operations
.thaw = nv_ck804_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_ck804_interrupt,
.irq_clear = ata_bmdma_irq_clear,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 9f2a48a..01abe09 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -205,6 +205,8 @@ static const struct ata_port_operations
.thaw = sil_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.irq_handler = sil_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = sil_scr_read,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index b8e590d..0904088 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -405,6 +405,9 @@ static const struct ata_port_operations
.error_handler = sil24_error_handler,
.post_internal_cmd = sil24_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.port_start = sil24_port_start,
.port_stop = sil24_port_stop,
.host_stop = sil24_host_stop,
--
1.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] libata: add hp-poll support to controllers with hotplug interrutps
2006-07-04 14:16 [RFT][PATCHSET] hotplug polling Tejun Heo
@ 2006-07-04 14:16 ` Tejun Heo
0 siblings, 0 replies; 11+ messages in thread
From: Tejun Heo @ 2006-07-04 14:16 UTC (permalink / raw)
To: jgarzik, lkml, axboe, forrest.zhao, alan, linux-ide; +Cc: Tejun Heo
This patch adds hp-poll support to the following drivers.
* ahci
* sata_nv (nf2 and c804 only)
* sata_sil
* sata_sil24
All the above controllers are capable of hotplug-by-interrupt and
hp-poll will be used only for watching disabled ports.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/ahci.c | 4 +++-
drivers/scsi/sata_nv.c | 4 ++++
drivers/scsi/sata_sil.c | 2 ++
drivers/scsi/sata_sil24.c | 3 +++
4 files changed, 12 insertions(+), 1 deletions(-)
15decf1370fe778e6df39cb8944cf5568e46b5b5
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 54f01b2..a404ec0 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -253,10 +253,12 @@ static const struct ata_port_operations
.freeze = ahci_freeze,
.thaw = ahci_thaw,
-
.error_handler = ahci_error_handler,
.post_internal_cmd = ahci_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
};
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 5cc42c6..79b0550 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -217,6 +217,8 @@ static const struct ata_port_operations
.thaw = nv_nf2_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_nf2_interrupt,
.irq_clear = ata_bmdma_irq_clear,
@@ -244,6 +246,8 @@ static const struct ata_port_operations
.thaw = nv_ck804_thaw,
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.data_xfer = ata_pio_data_xfer,
.irq_handler = nv_ck804_interrupt,
.irq_clear = ata_bmdma_irq_clear,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 9f2a48a..01abe09 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -205,6 +205,8 @@ static const struct ata_port_operations
.thaw = sil_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
.irq_handler = sil_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = sil_scr_read,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index b8e590d..0904088 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -405,6 +405,9 @@ static const struct ata_port_operations
.error_handler = sil24_error_handler,
.post_internal_cmd = sil24_post_internal_cmd,
+ .hp_poll_activate = sata_std_hp_poll_activate,
+ .hp_poll = sata_std_hp_poll,
+
.port_start = sil24_port_start,
.port_stop = sil24_port_stop,
.host_stop = sil24_host_stop,
--
1.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread