@@ -270,8 +270,29 @@ static int param_set_kgdboe_var(const char *kmessage, struct kernel_param *kp)
return 0;
}
+static int eth_try_quiesce(void)
+{
+ struct napi_struct *napi;
+
+ list_for_each_entry(napi, &np.dev->napi_list, dev_list) {
+ if (!napi_try_disable(napi))
+ return 0;
+ }
+ return 1;
+}
+
+static void eth_activate(void)
+{
+ struct napi_struct *napi;
+
+ list_for_each_entry(napi, &np.dev->napi_list, dev_list)
+ napi_enable(napi);
+}
+
static struct kgdb_io local_kgdb_io_ops = {
.name = "kgdboe",
+ .try_quiesce = eth_try_quiesce,
+ .activate = eth_activate,
.read_char = eth_get_char,
.write_char = eth_put_char,
.flush = eth_flush_buf,
@@ -250,6 +250,8 @@ struct kgdb_arch {
*/
struct kgdb_io {
const char *name;
+ int (*try_quiesce) (void);
+ void (*activate) (void);
int (*read_char) (void);
void (*write_char) (u8);
void (*flush) (void);
@@ -1475,6 +1475,9 @@ return_normal:
atomic_inc(&passive_cpu_wait[i]);
}
+ while (kgdb_io_ops->try_quiesce && !kgdb_io_ops->try_quiesce())
+ kgdb_arch_poll_ipi(regs);
+
#ifdef CONFIG_SMP
/* Signal the other CPUs to enter kgdb_wait() */
if ((!kgdb_single_step) && kgdb_do_roundup)
@@ -1489,6 +1492,9 @@ return_normal:
kgdb_arch_poll_ipi(regs);
}
+ if (kgdb_io_ops->activate)
+ kgdb_io_ops->activate();
+
/*
* At this point the primary processor is completely
* in the debugger and all secondary CPUs are quiescent
KGDB may try to roundup secondary CPUs while they're in the IO back-end code (e.g. NAPI is polling an eth device), so the secondary CPU might stop processing IO at a random place, which may cause the IO back-end to become unusable for KGDB itself. This patch implements try_quiesce and activate KGDB IO callbacks, so that we quiesce the IO back-end before rounding up the CPUs. So far it's only implemented for KGDBoE driver. Note that we have to quiesce the devices via _try mechanism since we have to poll for IPIs during the time we wait for the other CPUs. Signed-off-by: Anton Vorontsov <avorontsov@mvista.com> --- drivers/net/kgdboe.c | 21 +++++++++++++++++++++ include/linux/kgdb.h | 2 ++ kernel/kgdb.c | 6 ++++++ 3 files changed, 29 insertions(+), 0 deletions(-)