diff for duplicates of <200812212156.08723.bzolnier@gmail.com> diff --git a/a/1.txt b/N1/1.txt index c587251..ac16cb3 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,327 +1,12 @@ -during more testing it turned out that v1 was too optimistic w.r.t. -devices serialization, v2 fixes it (so the patch can be finally merged -into pata-2.6 tree) - -From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> -Subject: [PATCH] ide: use lock bitops for ports serialization (v2) - -* Add ->host_busy field to struct ide_host and use it's first bit - together with lock bitops to provide new ports serialization method. - +during more testing it turned out that v1 was too optimistic w.r.t.devices serialization, v2 fixes it (so the patch can be finally mergedinto pata-2.6 tree) +From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>Subject: [PATCH] ide: use lock bitops for ports serialization (v2) +* Add ->host_busy field to struct ide_host and use it's first bit together with lock bitops to provide new ports serialization method. * Convert core IDE code to use new ide_[un]lock_host() helpers. - - This removes the need for taking hwgroup->lock if host is already - busy on serialized hosts and makes it possible to merge ide_hwgroup_t - into ide_hwif_t (done in the later patch). - + This removes the need for taking hwgroup->lock if host is already busy on serialized hosts and makes it possible to merge ide_hwgroup_t into ide_hwif_t (done in the later patch). * Remove no longer needed ide_hwgroup_t.busy and ide_[un]lock_hwgroup(). - * Update do_ide_request() documentation. - -v2: -* ide_release_lock() should be called inside IDE_HFLAG_SERIALIZE check. - -* Add ide_hwif_t.busy flag and ide_[un]lock_port() for serializing - devices on a port. - -Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> ---- - drivers/ide/ide-io.c | 105 ++++++++++++++++++++++++++++++--------------------- - include/linux/ide.h | 35 ++--------------- - 2 files changed, 69 insertions(+), 71 deletions(-) - -Index: b/drivers/ide/ide-io.c -=================================================================== ---- a/drivers/ide/ide-io.c -+++ b/drivers/ide/ide-io.c -@@ -666,45 +666,54 @@ void ide_stall_queue (ide_drive_t *drive - } - EXPORT_SYMBOL(ide_stall_queue); - -+static inline int ide_lock_port(ide_hwif_t *hwif) -+{ -+ if (hwif->busy) -+ return 1; -+ -+ hwif->busy = 1; -+ -+ return 0; -+} -+ -+static inline void ide_unlock_port(ide_hwif_t *hwif) -+{ -+ hwif->busy = 0; -+} -+ -+static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif) -+{ -+ int rc = 0; -+ -+ if (host->host_flags & IDE_HFLAG_SERIALIZE) { -+ rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy); -+ if (rc == 0) { -+ /* for atari only */ -+ ide_get_lock(ide_intr, hwif); -+ } -+ } -+ return rc; -+} -+ -+static inline void ide_unlock_host(struct ide_host *host) -+{ -+ if (host->host_flags & IDE_HFLAG_SERIALIZE) { -+ /* for atari only */ -+ ide_release_lock(); -+ clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy); -+ } -+} -+ - /* - * Issue a new request to a drive from hwgroup -- * -- * A hwgroup is a serialized group of IDE interfaces. Usually there is -- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) -- * may have both interfaces in a single hwgroup to "serialize" access. -- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped -- * together into one hwgroup for serialized access. -- * -- * Note also that several hwgroups can end up sharing a single IRQ, -- * possibly along with many other devices. This is especially common in -- * PCI-based systems with off-board IDE controller cards. -- * -- * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag. -- * -- * The first thread into the driver for a particular hwgroup sets the -- * hwgroup->busy flag to indicate that this hwgroup is now active, -- * and then initiates processing of the top request from the request queue. -- * -- * Other threads attempting entry notice the busy setting, and will simply -- * queue their new requests and exit immediately. Note that hwgroup->busy -- * remains set even when the driver is merely awaiting the next interrupt. -- * Thus, the meaning is "this hwgroup is busy processing a request". -- * -- * When processing of a request completes, the completing thread or IRQ-handler -- * will start the next request from the queue. If no more work remains, -- * the driver will clear the hwgroup->busy flag and exit. -- * -- * The per-hwgroup spinlock is used to protect all access to the -- * hwgroup->busy flag, but is otherwise not needed for most processing in -- * the driver. This makes the driver much more friendlier to shared IRQs -- * than previous designs, while remaining 100% (?) SMP safe and capable. - */ - void do_ide_request(struct request_queue *q) - { - ide_drive_t *drive = q->queuedata; - ide_hwif_t *hwif = drive->hwif; -+ struct ide_host *host = hwif->host; - ide_hwgroup_t *hwgroup = hwif->hwgroup; -- struct request *rq; -+ struct request *rq = NULL; - ide_startstop_t startstop; - - /* -@@ -721,9 +730,13 @@ void do_ide_request(struct request_queue - blk_remove_plug(q); - - spin_unlock_irq(q->queue_lock); -+ -+ if (ide_lock_host(host, hwif)) -+ goto plug_device_2; -+ - spin_lock_irq(&hwgroup->lock); - -- if (!ide_lock_hwgroup(hwgroup, hwif)) { -+ if (!ide_lock_port(hwif)) { - ide_hwif_t *prev_port; - repeat: - prev_port = hwif->host->cur_port; -@@ -731,7 +744,7 @@ repeat: - - if (drive->dev_flags & IDE_DFLAG_SLEEPING) { - if (time_before(drive->sleep, jiffies)) { -- ide_unlock_hwgroup(hwgroup); -+ ide_unlock_port(hwif); - goto plug_device; - } - } -@@ -761,7 +774,7 @@ repeat: - spin_lock_irq(&hwgroup->lock); - - if (!rq) { -- ide_unlock_hwgroup(hwgroup); -+ ide_unlock_port(hwif); - goto out; - } - -@@ -782,7 +795,7 @@ repeat: - blk_pm_request(rq) == 0 && - (rq->cmd_flags & REQ_PREEMPT) == 0) { - /* there should be no pending command at this point */ -- ide_unlock_hwgroup(hwgroup); -+ ide_unlock_port(hwif); - goto plug_device; - } - -@@ -798,11 +811,15 @@ repeat: - goto plug_device; - out: - spin_unlock_irq(&hwgroup->lock); -+ if (rq == NULL) -+ ide_unlock_host(host); - spin_lock_irq(q->queue_lock); - return; - - plug_device: - spin_unlock_irq(&hwgroup->lock); -+ ide_unlock_host(host); -+plug_device_2: - spin_lock_irq(q->queue_lock); - - if (!elv_queue_empty(q)) -@@ -844,9 +861,9 @@ static ide_startstop_t ide_dma_timeout_r - ide_dma_off_quietly(drive); - - /* -- * un-busy drive etc (hwgroup->busy is cleared on return) and -- * make sure request is sane -+ * un-busy drive etc and make sure request is sane - */ -+ - rq = HWGROUP(drive)->rq; - - if (!rq) -@@ -895,6 +912,7 @@ static void ide_plug_device(ide_drive_t - void ide_timer_expiry (unsigned long data) - { - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; -+ ide_hwif_t *uninitialized_var(hwif); - ide_drive_t *uninitialized_var(drive); - ide_handler_t *handler; - ide_expiry_t *expiry; -@@ -918,7 +936,6 @@ void ide_timer_expiry (unsigned long dat - printk(KERN_ERR "%s: ->cur_dev was NULL\n", __func__); - hwgroup->handler = NULL; - } else { -- ide_hwif_t *hwif; - ide_startstop_t startstop = ide_stopped; - - if ((expiry = hwgroup->expiry) != NULL) { -@@ -964,15 +981,17 @@ void ide_timer_expiry (unsigned long dat - spin_lock_irq(&hwgroup->lock); - enable_irq(hwif->irq); - if (startstop == ide_stopped) { -- ide_unlock_hwgroup(hwgroup); -+ ide_unlock_port(hwif); - plug_device = 1; - } - } - } - spin_unlock_irqrestore(&hwgroup->lock, flags); - -- if (plug_device) -+ if (plug_device) { -+ ide_unlock_host(hwif->host); - ide_plug_device(drive); -+ } - } - - /** -@@ -1150,7 +1169,7 @@ irqreturn_t ide_intr (int irq, void *dev - */ - if (startstop == ide_stopped) { - if (hwgroup->handler == NULL) { /* paranoia */ -- ide_unlock_hwgroup(hwgroup); -+ ide_unlock_port(hwif); - plug_device = 1; - } else - printk(KERN_ERR "%s: %s: huh? expected NULL handler " -@@ -1161,8 +1180,10 @@ out_handled: - out: - spin_unlock_irqrestore(&hwgroup->lock, flags); - out_early: -- if (plug_device) -+ if (plug_device) { -+ ide_unlock_host(hwif->host); - ide_plug_device(drive); -+ } - - return irq_ret; - } -Index: b/include/linux/ide.h -=================================================================== ---- a/include/linux/ide.h -+++ b/include/linux/ide.h -@@ -828,6 +828,7 @@ typedef struct hwif_s { - - unsigned present : 1; /* this interface exists */ - unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ -+ unsigned busy : 1; /* serializes devices on a port */ - - struct device gendev; - struct device *portdev; -@@ -851,8 +852,13 @@ struct ide_host { - unsigned long host_flags; - void *host_priv; - ide_hwif_t *cur_port; /* for hosts requiring serialization */ -+ -+ /* used for hosts requiring serialization */ -+ volatile long host_busy; - }; - -+#define IDE_HOST_BUSY 0 -+ - /* - * internal ide interrupt handler type - */ -@@ -866,8 +872,6 @@ typedef struct hwgroup_s { - /* irq handler, if active */ - ide_startstop_t (*handler)(ide_drive_t *); - -- /* BOOL: protects all fields below */ -- volatile int busy; - /* BOOL: polling active & poll_timeout field valid */ - unsigned int polling : 1; - -@@ -1271,26 +1275,6 @@ extern void ide_stall_queue(ide_drive_t - - extern void ide_timer_expiry(unsigned long); - extern irqreturn_t ide_intr(int irq, void *dev_id); -- --static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif) --{ -- if (hwgroup->busy) -- return 1; -- -- hwgroup->busy = 1; -- /* for atari only */ -- ide_get_lock(ide_intr, hwif); -- -- return 0; --} -- --static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup) --{ -- /* for atari only */ -- ide_release_lock(); -- hwgroup->busy = 0; --} -- - extern void do_ide_request(struct request_queue *); - - void ide_init_disk(struct gendisk *, ide_drive_t *); -@@ -1617,13 +1601,6 @@ static inline void ide_set_max_pio(ide_d - - extern spinlock_t ide_lock; - extern struct mutex ide_cfg_mtx; --/* -- * Structure locking: -- * -- * ide_hwgroup_t->busy: hwgroup->lock -- * ide_hwif_t->{hwgroup,mate}: constant, no locking -- * ide_drive_t->hwif: constant, no locking -- */ - - #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) - -\0 +v2:* ide_release_lock() should be called inside IDE_HFLAG_SERIALIZE check. +* Add ide_hwif_t.busy flag and ide_[un]lock_port() for serializing devices on a port. +Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>--- drivers/ide/ide-io.c | 105 ++++++++++++++++++++++++++++++--------------------- include/linux/ide.h | 35 ++--------------- 2 files changed, 69 insertions(+), 71 deletions(-) +Index: b/drivers/ide/ide-io.c===================================================================--- a/drivers/ide/ide-io.c+++ b/drivers/ide/ide-io.c@@ -666,45 +666,54 @@ void ide_stall_queue (ide_drive_t *drive } EXPORT_SYMBOL(ide_stall_queue); +static inline int ide_lock_port(ide_hwif_t *hwif)+{+ if (hwif->busy)+ return 1;++ hwif->busy = 1;++ return 0;+}++static inline void ide_unlock_port(ide_hwif_t *hwif)+{+ hwif->busy = 0;+}++static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)+{+ int rc = 0;++ if (host->host_flags & IDE_HFLAG_SERIALIZE) {+ rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);+ if (rc == 0) {+ /* for atari only */+ ide_get_lock(ide_intr, hwif);+ }+ }+ return rc;+}++static inline void ide_unlock_host(struct ide_host *host)+{+ if (host->host_flags & IDE_HFLAG_SERIALIZE) {+ /* for atari only */+ ide_release_lock();+ clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);+ }+}+ /* * Issue a new request to a drive from hwgroup- *- * A hwgroup is a serialized group of IDE interfaces. Usually there is- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)- * may have both interfaces in a single hwgroup to "serialize" access.- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped- * together into one hwgroup for serialized access.- *- * Note also that several hwgroups can end up sharing a single IRQ,- * possibly along with many other devices. This is especially common in- * PCI-based systems with off-board IDE controller cards.- *- * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag.- *- * The first thread into the driver for a particular hwgroup sets the- * hwgroup->busy flag to indicate that this hwgroup is now active,- * and then initiates processing of the top request from the request queue.- *- * Other threads attempting entry notice the busy setting, and will simply- * queue their new requests and exit immediately. Note that hwgroup->busy- * remains set even when the driver is merely awaiting the next interrupt.- * Thus, the meaning is "this hwgroup is busy processing a request".- *- * When processing of a request completes, the completing thread or IRQ-handler- * will start the next request from the queue. If no more work remains,- * the driver will clear the hwgroup->busy flag and exit.- *- * The per-hwgroup spinlock is used to protect all access to the- * hwgroup->busy flag, but is otherwise not needed for most processing in- * the driver. This makes the driver much more friendlier to shared IRQs- * than previous designs, while remaining 100% (?) SMP safe and capable. */ void do_ide_request(struct request_queue *q) { ide_drive_t *drive = q->queuedata; ide_hwif_t *hwif = drive->hwif;+ struct ide_host *host = hwif->host; ide_hwgroup_t *hwgroup = hwif->hwgroup;- struct request *rq;+ struct request *rq = NULL; ide_startstop_t startstop; /*@@ -721,9 +730,13 @@ void do_ide_request(struct request_queue blk_remove_plug(q); spin_unlock_irq(q->queue_lock);++ if (ide_lock_host(host, hwif))+ goto plug_device_2;+ spin_lock_irq(&hwgroup->lock); - if (!ide_lock_hwgroup(hwgroup, hwif)) {+ if (!ide_lock_port(hwif)) { ide_hwif_t *prev_port; repeat: prev_port = hwif->host->cur_port;@@ -731,7 +744,7 @@ repeat: if (drive->dev_flags & IDE_DFLAG_SLEEPING) { if (time_before(drive->sleep, jiffies)) {- ide_unlock_hwgroup(hwgroup);+ ide_unlock_port(hwif); goto plug_device; } }@@ -761,7 +774,7 @@ repeat: spin_lock_irq(&hwgroup->lock); if (!rq) {- ide_unlock_hwgroup(hwgroup);+ ide_unlock_port(hwif); goto out; } @@ -782,7 +795,7 @@ repeat: blk_pm_request(rq) == 0 && (rq->cmd_flags & REQ_PREEMPT) == 0) { /* there should be no pending command at this point */- ide_unlock_hwgroup(hwgroup);+ ide_unlock_port(hwif); goto plug_device; } @@ -798,11 +811,15 @@ repeat: goto plug_device; out: spin_unlock_irq(&hwgroup->lock);+ if (rq == NULL)+ ide_unlock_host(host); spin_lock_irq(q->queue_lock); return; plug_device: spin_unlock_irq(&hwgroup->lock);+ ide_unlock_host(host);+plug_device_2: spin_lock_irq(q->queue_lock); if (!elv_queue_empty(q))@@ -844,9 +861,9 @@ static ide_startstop_t ide_dma_timeout_r ide_dma_off_quietly(drive); /*- * un-busy drive etc (hwgroup->busy is cleared on return) and- * make sure request is sane+ * un-busy drive etc and make sure request is sane */+ rq = HWGROUP(drive)->rq; if (!rq)@@ -895,6 +912,7 @@ static void ide_plug_device(ide_drive_t void ide_timer_expiry (unsigned long data) { ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;+ ide_hwif_t *uninitialized_var(hwif); ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_expiry_t *expiry;@@ -918,7 +936,6 @@ void ide_timer_expiry (unsigned long dat printk(KERN_ERR "%s: ->cur_dev was NULL\n", __func__); hwgroup->handler = NULL; } else {- ide_hwif_t *hwif; ide_startstop_t startstop = ide_stopped; if ((expiry = hwgroup->expiry) != NULL) {@@ -964,15 +981,17 @@ void ide_timer_expiry (unsigned long dat spin_lock_irq(&hwgroup->lock); enable_irq(hwif->irq); if (startstop == ide_stopped) {- ide_unlock_hwgroup(hwgroup);+ ide_unlock_port(hwif); plug_device = 1; } } } spin_unlock_irqrestore(&hwgroup->lock, flags); - if (plug_device)+ if (plug_device) {+ ide_unlock_host(hwif->host); ide_plug_device(drive);+ } } /**@@ -1150,7 +1169,7 @@ irqreturn_t ide_intr (int irq, void *dev */ if (startstop == ide_stopped) { if (hwgroup->handler == NULL) { /* paranoia */- ide_unlock_hwgroup(hwgroup);+ ide_unlock_port(hwif); plug_device = 1; } else printk(KERN_ERR "%s: %s: huh? expected NULL handler "@@ -1161,8 +1180,10 @@ out_handled: out: spin_unlock_irqrestore(&hwgroup->lock, flags); out_early:- if (plug_device)+ if (plug_device) {+ ide_unlock_host(hwif->host); ide_plug_device(drive);+ } return irq_ret; }Index: b/include/linux/ide.h===================================================================--- a/include/linux/ide.h+++ b/include/linux/ide.h@@ -828,6 +828,7 @@ typedef struct hwif_s { unsigned present : 1; /* this interface exists */ unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */+ unsigned busy : 1; /* serializes devices on a port */ struct device gendev; struct device *portdev;@@ -851,8 +852,13 @@ struct ide_host { unsigned long host_flags; void *host_priv; ide_hwif_t *cur_port; /* for hosts requiring serialization */++ /* used for hosts requiring serialization */+ volatile long host_busy; }; +#define IDE_HOST_BUSY 0+ /* * internal ide interrupt handler type */@@ -866,8 +872,6 @@ typedef struct hwgroup_s { /* irq handler, if active */ ide_startstop_t (*handler)(ide_drive_t *); - /* BOOL: protects all fields below */- volatile int busy; /* BOOL: polling active & poll_timeout field valid */ unsigned int polling : 1; @@ -1271,26 +1275,6 @@ extern void ide_stall_queue(ide_drive_t extern void ide_timer_expiry(unsigned long); extern irqreturn_t ide_intr(int irq, void *dev_id);--static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif)-{- if (hwgroup->busy)- return 1;-- hwgroup->busy = 1;- /* for atari only */- ide_get_lock(ide_intr, hwif);-- return 0;-}--static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup)-{- /* for atari only */- ide_release_lock();- hwgroup->busy = 0;-}- extern void do_ide_request(struct request_queue *); void ide_init_disk(struct gendisk *, ide_drive_t *);@@ -1617,13 +1601,6 @@ static inline void ide_set_max_pio(ide_d extern spinlock_t ide_lock; extern struct mutex ide_cfg_mtx;-/*- * Structure locking:- *- * ide_hwgroup_t->busy: hwgroup->lock- * ide_hwif_t->{hwgroup,mate}: constant, no locking- * ide_drive_t->hwif: constant, no locking- */ #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) \0ÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥ diff --git a/a/content_digest b/N1/content_digest index 6b2a43c..b8d8488 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -6,331 +6,16 @@ "\00:1\0" "b\0" "\n" - "during more testing it turned out that v1 was too optimistic w.r.t.\n" - "devices serialization, v2 fixes it (so the patch can be finally merged\n" - "into pata-2.6 tree)\n" - "\n" - "From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>\n" - "Subject: [PATCH] ide: use lock bitops for ports serialization (v2)\n" - "\n" - "* Add ->host_busy field to struct ide_host and use it's first bit\n" - " together with lock bitops to provide new ports serialization method.\n" - "\n" + "during more testing it turned out that v1 was too optimistic w.r.t.devices serialization, v2 fixes it (so the patch can be finally mergedinto pata-2.6 tree)\n" + "From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>Subject: [PATCH] ide: use lock bitops for ports serialization (v2)\n" + "* Add ->host_busy field to struct ide_host and use it's first bit together with lock bitops to provide new ports serialization method.\n" "* Convert core IDE code to use new ide_[un]lock_host() helpers.\n" - "\n" - " This removes the need for taking hwgroup->lock if host is already\n" - " busy on serialized hosts and makes it possible to merge ide_hwgroup_t\n" - " into ide_hwif_t (done in the later patch).\n" - "\n" + " This removes the need for taking hwgroup->lock if host is already busy on serialized hosts and makes it possible to merge ide_hwgroup_t into ide_hwif_t (done in the later patch).\n" "* Remove no longer needed ide_hwgroup_t.busy and ide_[un]lock_hwgroup().\n" - "\n" "* Update do_ide_request() documentation.\n" - "\n" - "v2:\n" - "* ide_release_lock() should be called inside IDE_HFLAG_SERIALIZE check.\n" - "\n" - "* Add ide_hwif_t.busy flag and ide_[un]lock_port() for serializing\n" - " devices on a port.\n" - "\n" - "Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>\n" - "---\n" - " drivers/ide/ide-io.c | 105 ++++++++++++++++++++++++++++++---------------------\n" - " include/linux/ide.h | 35 ++---------------\n" - " 2 files changed, 69 insertions(+), 71 deletions(-)\n" - "\n" - "Index: b/drivers/ide/ide-io.c\n" - "===================================================================\n" - "--- a/drivers/ide/ide-io.c\n" - "+++ b/drivers/ide/ide-io.c\n" - "@@ -666,45 +666,54 @@ void ide_stall_queue (ide_drive_t *drive\n" - " }\n" - " EXPORT_SYMBOL(ide_stall_queue);\n" - " \n" - "+static inline int ide_lock_port(ide_hwif_t *hwif)\n" - "+{\n" - "+\tif (hwif->busy)\n" - "+\t\treturn 1;\n" - "+\n" - "+\thwif->busy = 1;\n" - "+\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline void ide_unlock_port(ide_hwif_t *hwif)\n" - "+{\n" - "+\thwif->busy = 0;\n" - "+}\n" - "+\n" - "+static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)\n" - "+{\n" - "+\tint rc = 0;\n" - "+\n" - "+\tif (host->host_flags & IDE_HFLAG_SERIALIZE) {\n" - "+\t\trc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);\n" - "+\t\tif (rc == 0) {\n" - "+\t\t\t/* for atari only */\n" - "+\t\t\tide_get_lock(ide_intr, hwif);\n" - "+\t\t}\n" - "+\t}\n" - "+\treturn rc;\n" - "+}\n" - "+\n" - "+static inline void ide_unlock_host(struct ide_host *host)\n" - "+{\n" - "+\tif (host->host_flags & IDE_HFLAG_SERIALIZE) {\n" - "+\t\t/* for atari only */\n" - "+\t\tide_release_lock();\n" - "+\t\tclear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);\n" - "+\t}\n" - "+}\n" - "+\n" - " /*\n" - " * Issue a new request to a drive from hwgroup\n" - "- *\n" - "- * A hwgroup is a serialized group of IDE interfaces. Usually there is\n" - "- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)\n" - "- * may have both interfaces in a single hwgroup to \"serialize\" access.\n" - "- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped\n" - "- * together into one hwgroup for serialized access.\n" - "- *\n" - "- * Note also that several hwgroups can end up sharing a single IRQ,\n" - "- * possibly along with many other devices. This is especially common in\n" - "- * PCI-based systems with off-board IDE controller cards.\n" - "- *\n" - "- * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag.\n" - "- *\n" - "- * The first thread into the driver for a particular hwgroup sets the\n" - "- * hwgroup->busy flag to indicate that this hwgroup is now active,\n" - "- * and then initiates processing of the top request from the request queue.\n" - "- *\n" - "- * Other threads attempting entry notice the busy setting, and will simply\n" - "- * queue their new requests and exit immediately. Note that hwgroup->busy\n" - "- * remains set even when the driver is merely awaiting the next interrupt.\n" - "- * Thus, the meaning is \"this hwgroup is busy processing a request\".\n" - "- *\n" - "- * When processing of a request completes, the completing thread or IRQ-handler\n" - "- * will start the next request from the queue. If no more work remains,\n" - "- * the driver will clear the hwgroup->busy flag and exit.\n" - "- *\n" - "- * The per-hwgroup spinlock is used to protect all access to the\n" - "- * hwgroup->busy flag, but is otherwise not needed for most processing in\n" - "- * the driver. This makes the driver much more friendlier to shared IRQs\n" - "- * than previous designs, while remaining 100% (?) SMP safe and capable.\n" - " */\n" - " void do_ide_request(struct request_queue *q)\n" - " {\n" - " \tide_drive_t\t*drive = q->queuedata;\n" - " \tide_hwif_t\t*hwif = drive->hwif;\n" - "+\tstruct ide_host *host = hwif->host;\n" - " \tide_hwgroup_t\t*hwgroup = hwif->hwgroup;\n" - "-\tstruct request\t*rq;\n" - "+\tstruct request\t*rq = NULL;\n" - " \tide_startstop_t\tstartstop;\n" - " \n" - " \t/*\n" - "@@ -721,9 +730,13 @@ void do_ide_request(struct request_queue\n" - " \t\tblk_remove_plug(q);\n" - " \n" - " \tspin_unlock_irq(q->queue_lock);\n" - "+\n" - "+\tif (ide_lock_host(host, hwif))\n" - "+\t\tgoto plug_device_2;\n" - "+\n" - " \tspin_lock_irq(&hwgroup->lock);\n" - " \n" - "-\tif (!ide_lock_hwgroup(hwgroup, hwif)) {\n" - "+\tif (!ide_lock_port(hwif)) {\n" - " \t\tide_hwif_t *prev_port;\n" - " repeat:\n" - " \t\tprev_port = hwif->host->cur_port;\n" - "@@ -731,7 +744,7 @@ repeat:\n" - " \n" - " \t\tif (drive->dev_flags & IDE_DFLAG_SLEEPING) {\n" - " \t\t\tif (time_before(drive->sleep, jiffies)) {\n" - "-\t\t\t\tide_unlock_hwgroup(hwgroup);\n" - "+\t\t\t\tide_unlock_port(hwif);\n" - " \t\t\t\tgoto plug_device;\n" - " \t\t\t}\n" - " \t\t}\n" - "@@ -761,7 +774,7 @@ repeat:\n" - " \t\tspin_lock_irq(&hwgroup->lock);\n" - " \n" - " \t\tif (!rq) {\n" - "-\t\t\tide_unlock_hwgroup(hwgroup);\n" - "+\t\t\tide_unlock_port(hwif);\n" - " \t\t\tgoto out;\n" - " \t\t}\n" - " \n" - "@@ -782,7 +795,7 @@ repeat:\n" - " \t\t blk_pm_request(rq) == 0 &&\n" - " \t\t (rq->cmd_flags & REQ_PREEMPT) == 0) {\n" - " \t\t\t/* there should be no pending command at this point */\n" - "-\t\t\tide_unlock_hwgroup(hwgroup);\n" - "+\t\t\tide_unlock_port(hwif);\n" - " \t\t\tgoto plug_device;\n" - " \t\t}\n" - " \n" - "@@ -798,11 +811,15 @@ repeat:\n" - " \t\tgoto plug_device;\n" - " out:\n" - " \tspin_unlock_irq(&hwgroup->lock);\n" - "+\tif (rq == NULL)\n" - "+\t\tide_unlock_host(host);\n" - " \tspin_lock_irq(q->queue_lock);\n" - " \treturn;\n" - " \n" - " plug_device:\n" - " \tspin_unlock_irq(&hwgroup->lock);\n" - "+\tide_unlock_host(host);\n" - "+plug_device_2:\n" - " \tspin_lock_irq(q->queue_lock);\n" - " \n" - " \tif (!elv_queue_empty(q))\n" - "@@ -844,9 +861,9 @@ static ide_startstop_t ide_dma_timeout_r\n" - " \tide_dma_off_quietly(drive);\n" - " \n" - " \t/*\n" - "-\t * un-busy drive etc (hwgroup->busy is cleared on return) and\n" - "-\t * make sure request is sane\n" - "+\t * un-busy drive etc and make sure request is sane\n" - " \t */\n" - "+\n" - " \trq = HWGROUP(drive)->rq;\n" - " \n" - " \tif (!rq)\n" - "@@ -895,6 +912,7 @@ static void ide_plug_device(ide_drive_t \n" - " void ide_timer_expiry (unsigned long data)\n" - " {\n" - " \tide_hwgroup_t\t*hwgroup = (ide_hwgroup_t *) data;\n" - "+\tide_hwif_t\t*uninitialized_var(hwif);\n" - " \tide_drive_t\t*uninitialized_var(drive);\n" - " \tide_handler_t\t*handler;\n" - " \tide_expiry_t\t*expiry;\n" - "@@ -918,7 +936,6 @@ void ide_timer_expiry (unsigned long dat\n" - " \t\t\tprintk(KERN_ERR \"%s: ->cur_dev was NULL\\n\", __func__);\n" - " \t\t\thwgroup->handler = NULL;\n" - " \t\t} else {\n" - "-\t\t\tide_hwif_t *hwif;\n" - " \t\t\tide_startstop_t startstop = ide_stopped;\n" - " \n" - " \t\t\tif ((expiry = hwgroup->expiry) != NULL) {\n" - "@@ -964,15 +981,17 @@ void ide_timer_expiry (unsigned long dat\n" - " \t\t\tspin_lock_irq(&hwgroup->lock);\n" - " \t\t\tenable_irq(hwif->irq);\n" - " \t\t\tif (startstop == ide_stopped) {\n" - "-\t\t\t\tide_unlock_hwgroup(hwgroup);\n" - "+\t\t\t\tide_unlock_port(hwif);\n" - " \t\t\t\tplug_device = 1;\n" - " \t\t\t}\n" - " \t\t}\n" - " \t}\n" - " \tspin_unlock_irqrestore(&hwgroup->lock, flags);\n" - " \n" - "-\tif (plug_device)\n" - "+\tif (plug_device) {\n" - "+\t\tide_unlock_host(hwif->host);\n" - " \t\tide_plug_device(drive);\n" - "+\t}\n" - " }\n" - " \n" - " /**\n" - "@@ -1150,7 +1169,7 @@ irqreturn_t ide_intr (int irq, void *dev\n" - " \t */\n" - " \tif (startstop == ide_stopped) {\n" - " \t\tif (hwgroup->handler == NULL) {\t/* paranoia */\n" - "-\t\t\tide_unlock_hwgroup(hwgroup);\n" - "+\t\t\tide_unlock_port(hwif);\n" - " \t\t\tplug_device = 1;\n" - " \t\t} else\n" - " \t\t\tprintk(KERN_ERR \"%s: %s: huh? expected NULL handler \"\n" - "@@ -1161,8 +1180,10 @@ out_handled:\n" - " out:\n" - " \tspin_unlock_irqrestore(&hwgroup->lock, flags);\n" - " out_early:\n" - "-\tif (plug_device)\n" - "+\tif (plug_device) {\n" - "+\t\tide_unlock_host(hwif->host);\n" - " \t\tide_plug_device(drive);\n" - "+\t}\n" - " \n" - " \treturn irq_ret;\n" - " }\n" - "Index: b/include/linux/ide.h\n" - "===================================================================\n" - "--- a/include/linux/ide.h\n" - "+++ b/include/linux/ide.h\n" - "@@ -828,6 +828,7 @@ typedef struct hwif_s {\n" - " \n" - " \tunsigned\tpresent : 1;\t/* this interface exists */\n" - " \tunsigned\tsg_mapped : 1;\t/* sg_table and sg_nents are ready */\n" - "+\tunsigned\tbusy\t : 1; /* serializes devices on a port */\n" - " \n" - " \tstruct device\t\tgendev;\n" - " \tstruct device\t\t*portdev;\n" - "@@ -851,8 +852,13 @@ struct ide_host {\n" - " \tunsigned long\thost_flags;\n" - " \tvoid\t\t*host_priv;\n" - " \tide_hwif_t\t*cur_port;\t/* for hosts requiring serialization */\n" - "+\n" - "+\t/* used for hosts requiring serialization */\n" - "+\tvolatile long\thost_busy;\n" - " };\n" - " \n" - "+#define IDE_HOST_BUSY 0\n" - "+\n" - " /*\n" - " * internal ide interrupt handler type\n" - " */\n" - "@@ -866,8 +872,6 @@ typedef struct hwgroup_s {\n" - " \t\t/* irq handler, if active */\n" - " \tide_startstop_t\t(*handler)(ide_drive_t *);\n" - " \n" - "-\t\t/* BOOL: protects all fields below */\n" - "-\tvolatile int busy;\n" - " \t\t/* BOOL: polling active & poll_timeout field valid */\n" - " \tunsigned int polling\t: 1;\n" - " \n" - "@@ -1271,26 +1275,6 @@ extern void ide_stall_queue(ide_drive_t \n" - " \n" - " extern void ide_timer_expiry(unsigned long);\n" - " extern irqreturn_t ide_intr(int irq, void *dev_id);\n" - "-\n" - "-static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif)\n" - "-{\n" - "-\tif (hwgroup->busy)\n" - "-\t\treturn 1;\n" - "-\n" - "-\thwgroup->busy = 1;\n" - "-\t/* for atari only */\n" - "-\tide_get_lock(ide_intr, hwif);\n" - "-\n" - "-\treturn 0;\n" - "-}\n" - "-\n" - "-static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup)\n" - "-{\n" - "-\t/* for atari only */\n" - "-\tide_release_lock();\n" - "-\thwgroup->busy = 0;\n" - "-}\n" - "-\n" - " extern void do_ide_request(struct request_queue *);\n" - " \n" - " void ide_init_disk(struct gendisk *, ide_drive_t *);\n" - "@@ -1617,13 +1601,6 @@ static inline void ide_set_max_pio(ide_d\n" - " \n" - " extern spinlock_t ide_lock;\n" - " extern struct mutex ide_cfg_mtx;\n" - "-/*\n" - "- * Structure locking:\n" - "- *\n" - "- * ide_hwgroup_t->busy: hwgroup->lock\n" - "- * ide_hwif_t->{hwgroup,mate}: constant, no locking\n" - "- * ide_drive_t->hwif: constant, no locking\n" - "- */\n" - " \n" - " #define local_irq_set(flags)\tdo { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0)\n" - " \n" - "\0" + "v2:* ide_release_lock() should be called inside IDE_HFLAG_SERIALIZE check.\n" + "* Add ide_hwif_t.busy flag and ide_[un]lock_port() for serializing devices on a port.\n" + "Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>--- drivers/ide/ide-io.c | 105 ++++++++++++++++++++++++++++++--------------------- include/linux/ide.h | 35 ++--------------- 2 files changed, 69 insertions(+), 71 deletions(-)\n" + "Index: b/drivers/ide/ide-io.c===================================================================--- a/drivers/ide/ide-io.c+++ b/drivers/ide/ide-io.c@@ -666,45 +666,54 @@ void ide_stall_queue (ide_drive_t *drive } EXPORT_SYMBOL(ide_stall_queue); +static inline int ide_lock_port(ide_hwif_t *hwif)+{+\tif (hwif->busy)+\t\treturn 1;++\thwif->busy = 1;++\treturn 0;+}++static inline void ide_unlock_port(ide_hwif_t *hwif)+{+\thwif->busy = 0;+}++static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)+{+\tint rc = 0;++\tif (host->host_flags & IDE_HFLAG_SERIALIZE) {+\t\trc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);+\t\tif (rc == 0) {+\t\t\t/* for atari only */+\t\t\tide_get_lock(ide_intr, hwif);+\t\t}+\t}+\treturn rc;+}++static inline void ide_unlock_host(struct ide_host *host)+{+\tif (host->host_flags & IDE_HFLAG_SERIALIZE) {+\t\t/* for atari only */+\t\tide_release_lock();+\t\tclear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);+\t}+}+ /* * Issue a new request to a drive from hwgroup- *- * A hwgroup is a serialized group of IDE interfaces. Usually there is- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)- * may have both interfaces in a single hwgroup to \"serialize\" access.- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped- * together into one hwgroup for serialized access.- *- * Note also that several hwgroups can end up sharing a single IRQ,- * possibly along with many other devices. This is especially common in- * PCI-based systems with off-board IDE controller cards.- *- * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag.- *- * The first thread into the driver for a particular hwgroup sets the- * hwgroup->busy flag to indicate that this hwgroup is now active,- * and then initiates processing of the top request from the request queue.- *- * Other threads attempting entry notice the busy setting, and will simply- * queue their new requests and exit immediately. Note that hwgroup->busy- * remains set even when the driver is merely awaiting the next interrupt.- * Thus, the meaning is \"this hwgroup is busy processing a request\".- *- * When processing of a request completes, the completing thread or IRQ-handler- * will start the next request from the queue. If no more work remains,- * the driver will clear the hwgroup->busy flag and exit.- *- * The per-hwgroup spinlock is used to protect all access to the- * hwgroup->busy flag, but is otherwise not needed for most processing in- * the driver. This makes the driver much more friendlier to shared IRQs- * than previous designs, while remaining 100% (?) SMP safe and capable. */ void do_ide_request(struct request_queue *q) { \tide_drive_t\t*drive = q->queuedata; \tide_hwif_t\t*hwif = drive->hwif;+\tstruct ide_host *host = hwif->host; \tide_hwgroup_t\t*hwgroup = hwif->hwgroup;-\tstruct request\t*rq;+\tstruct request\t*rq = NULL; \tide_startstop_t\tstartstop; \t/*@@ -721,9 +730,13 @@ void do_ide_request(struct request_queue \t\tblk_remove_plug(q); \tspin_unlock_irq(q->queue_lock);++\tif (ide_lock_host(host, hwif))+\t\tgoto plug_device_2;+ \tspin_lock_irq(&hwgroup->lock); -\tif (!ide_lock_hwgroup(hwgroup, hwif)) {+\tif (!ide_lock_port(hwif)) { \t\tide_hwif_t *prev_port; repeat: \t\tprev_port = hwif->host->cur_port;@@ -731,7 +744,7 @@ repeat: \t\tif (drive->dev_flags & IDE_DFLAG_SLEEPING) { \t\t\tif (time_before(drive->sleep, jiffies)) {-\t\t\t\tide_unlock_hwgroup(hwgroup);+\t\t\t\tide_unlock_port(hwif); \t\t\t\tgoto plug_device; \t\t\t} \t\t}@@ -761,7 +774,7 @@ repeat: \t\tspin_lock_irq(&hwgroup->lock); \t\tif (!rq) {-\t\t\tide_unlock_hwgroup(hwgroup);+\t\t\tide_unlock_port(hwif); \t\t\tgoto out; \t\t} @@ -782,7 +795,7 @@ repeat: \t\t blk_pm_request(rq) == 0 && \t\t (rq->cmd_flags & REQ_PREEMPT) == 0) { \t\t\t/* there should be no pending command at this point */-\t\t\tide_unlock_hwgroup(hwgroup);+\t\t\tide_unlock_port(hwif); \t\t\tgoto plug_device; \t\t} @@ -798,11 +811,15 @@ repeat: \t\tgoto plug_device; out: \tspin_unlock_irq(&hwgroup->lock);+\tif (rq == NULL)+\t\tide_unlock_host(host); \tspin_lock_irq(q->queue_lock); \treturn; plug_device: \tspin_unlock_irq(&hwgroup->lock);+\tide_unlock_host(host);+plug_device_2: \tspin_lock_irq(q->queue_lock); \tif (!elv_queue_empty(q))@@ -844,9 +861,9 @@ static ide_startstop_t ide_dma_timeout_r \tide_dma_off_quietly(drive); \t/*-\t * un-busy drive etc (hwgroup->busy is cleared on return) and-\t * make sure request is sane+\t * un-busy drive etc and make sure request is sane \t */+ \trq = HWGROUP(drive)->rq; \tif (!rq)@@ -895,6 +912,7 @@ static void ide_plug_device(ide_drive_t void ide_timer_expiry (unsigned long data) { \tide_hwgroup_t\t*hwgroup = (ide_hwgroup_t *) data;+\tide_hwif_t\t*uninitialized_var(hwif); \tide_drive_t\t*uninitialized_var(drive); \tide_handler_t\t*handler; \tide_expiry_t\t*expiry;@@ -918,7 +936,6 @@ void ide_timer_expiry (unsigned long dat \t\t\tprintk(KERN_ERR \"%s: ->cur_dev was NULL\\n\", __func__); \t\t\thwgroup->handler = NULL; \t\t} else {-\t\t\tide_hwif_t *hwif; \t\t\tide_startstop_t startstop = ide_stopped; \t\t\tif ((expiry = hwgroup->expiry) != NULL) {@@ -964,15 +981,17 @@ void ide_timer_expiry (unsigned long dat \t\t\tspin_lock_irq(&hwgroup->lock); \t\t\tenable_irq(hwif->irq); \t\t\tif (startstop == ide_stopped) {-\t\t\t\tide_unlock_hwgroup(hwgroup);+\t\t\t\tide_unlock_port(hwif); \t\t\t\tplug_device = 1; \t\t\t} \t\t} \t} \tspin_unlock_irqrestore(&hwgroup->lock, flags); -\tif (plug_device)+\tif (plug_device) {+\t\tide_unlock_host(hwif->host); \t\tide_plug_device(drive);+\t} } /**@@ -1150,7 +1169,7 @@ irqreturn_t ide_intr (int irq, void *dev \t */ \tif (startstop == ide_stopped) { \t\tif (hwgroup->handler == NULL) {\t/* paranoia */-\t\t\tide_unlock_hwgroup(hwgroup);+\t\t\tide_unlock_port(hwif); \t\t\tplug_device = 1; \t\t} else \t\t\tprintk(KERN_ERR \"%s: %s: huh? expected NULL handler \"@@ -1161,8 +1180,10 @@ out_handled: out: \tspin_unlock_irqrestore(&hwgroup->lock, flags); out_early:-\tif (plug_device)+\tif (plug_device) {+\t\tide_unlock_host(hwif->host); \t\tide_plug_device(drive);+\t} \treturn irq_ret; }Index: b/include/linux/ide.h===================================================================--- a/include/linux/ide.h+++ b/include/linux/ide.h@@ -828,6 +828,7 @@ typedef struct hwif_s { \tunsigned\tpresent : 1;\t/* this interface exists */ \tunsigned\tsg_mapped : 1;\t/* sg_table and sg_nents are ready */+\tunsigned\tbusy\t : 1; /* serializes devices on a port */ \tstruct device\t\tgendev; \tstruct device\t\t*portdev;@@ -851,8 +852,13 @@ struct ide_host { \tunsigned long\thost_flags; \tvoid\t\t*host_priv; \tide_hwif_t\t*cur_port;\t/* for hosts requiring serialization */++\t/* used for hosts requiring serialization */+\tvolatile long\thost_busy; }; +#define IDE_HOST_BUSY 0+ /* * internal ide interrupt handler type */@@ -866,8 +872,6 @@ typedef struct hwgroup_s { \t\t/* irq handler, if active */ \tide_startstop_t\t(*handler)(ide_drive_t *); -\t\t/* BOOL: protects all fields below */-\tvolatile int busy; \t\t/* BOOL: polling active & poll_timeout field valid */ \tunsigned int polling\t: 1; @@ -1271,26 +1275,6 @@ extern void ide_stall_queue(ide_drive_t extern void ide_timer_expiry(unsigned long); extern irqreturn_t ide_intr(int irq, void *dev_id);--static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif)-{-\tif (hwgroup->busy)-\t\treturn 1;--\thwgroup->busy = 1;-\t/* for atari only */-\tide_get_lock(ide_intr, hwif);--\treturn 0;-}--static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup)-{-\t/* for atari only */-\tide_release_lock();-\thwgroup->busy = 0;-}- extern void do_ide_request(struct request_queue *); void ide_init_disk(struct gendisk *, ide_drive_t *);@@ -1617,13 +1601,6 @@ static inline void ide_set_max_pio(ide_d extern spinlock_t ide_lock; extern struct mutex ide_cfg_mtx;-/*- * Structure locking:- *- * ide_hwgroup_t->busy: hwgroup->lock- * ide_hwif_t->{hwgroup,mate}: constant, no locking- * ide_drive_t->hwif: constant, no locking- */ #define local_irq_set(flags)\tdo { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) \0\303\277\303\264\303\250\302\272{.n\303\207+\302\211\302\267\302\237\302\256\302\211\302\255\302\206+%\302\212\303\213\303\277\302\261\303\251\303\235\302\266\027\302\245\302\212w\303\277\302\272{.n\303\207+\302\211\302\267\302\245\302\212{\302\261\303\276G\302\253\302\235\303\251\303\277\302\212{ay\302\272\035\303\212\302\207\303\232\302\231\303\253,j\a\302\255\302\242f\302\243\302\242\302\267h\302\232\302\217\303\257\302\201\303\252\303\277\302\221\303\252\303\247z_\303\250\302\256\003(\302\255\303\251\302\232\302\216\302\212\303\235\302\242j\"\302\235\303\272\032\302\266\033m\302\247\303\277\303\277\302\276\a\302\253\303\276G\302\253\302\235\303\251\303\277\302\242\302\270?\302\231\302\250\303\250\302\255\303\232&\302\243\303\270\302\247~\302\217\303\241\302\266iO\302\225\303\246\302\254z\302\267\302\232v\303\230^\024\004\032\302\266\033m\302\247\303\277\303\277\303\203\f\303\277\302\266\303\254\303\277\302\242\302\270?\302\226I\302\245" -e5c32acc36e563c5ec5d75778e7ca247010465c82a2a9292fc15f60daafc8bbf +903c0082e75c9cbb1584ecc2835260d956f0f94b391b6329fb406e07ea48cd5f
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.