diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index c82f2da34..2b325f54b 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2234,7 +2234,7 @@ islocked({expr})		Number	|TRUE| if {expr} is locked
 isnan({expr})			Number	|TRUE| if {expr} is NaN
 items({dict})			List	key-value pairs in {dict}
 job_getchannel({job})		Channel	get the channel handle for {job}
-job_info({job})			Dict	get information about {job}
+job_info([{job}])		Dict	get information about {job}
 job_setoptions({job}, {options}) none	set options for {job}
 job_start({command} [, {options}])
 				Job	start a job
@@ -5387,7 +5387,7 @@ job_getchannel({job})					 *job_getchannel()*
 <
 		{only available when compiled with the |+job| feature}
 
-job_info({job})						*job_info()*
+job_info([{job}])					*job_info()*
 		Returns a Dictionary with information about {job}:
 		   "status"	what |job_status()| returns
 		   "channel"	what |job_getchannel()| returns
@@ -5398,6 +5398,9 @@ job_info({job})						*job_info()*
 		   "exit_cb"	function to be called on exit
 		   "stoponexit"	|job-stoponexit|
 
+		Without any arguments, returns information about all the jobs
+		in a List.
+
 job_setoptions({job}, {options})			*job_setoptions()*
 		Change options for {job}.  Supported are:
 		   "stoponexit"	|job-stoponexit|
diff --git a/src/channel.c b/src/channel.c
index 3b71472fd..f30909bef 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -5630,6 +5630,28 @@ job_info(job_T *job, dict_T *dict)
     dict_add_nr_str(dict, "stoponexit", 0L, job->jv_stoponexit);
 }
 
+/*
+ * Implementation of job_info() to return info for all jobs.
+ */
+    void
+job_info_all(list_T *l)
+{
+    job_T	*job;
+    dict_T	*d;
+
+    for (job = first_job; job != NULL; job = job->jv_next)
+    {
+	d = dict_alloc();
+	if (d == NULL)
+	    return;
+
+	job_info(job, d);
+
+	if (list_append_dict(l, d) != OK)
+	    return;
+    }
+}
+
 /*
  * Send a signal to "job".  Implements job_stop().
  * When "type" is not NULL use this for the type.
diff --git a/src/evalfunc.c b/src/evalfunc.c
index dc2c14c3d..77ffd2f49 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -682,7 +682,7 @@ static struct fst
     {"items",		1, 1, f_items},
 #ifdef FEAT_JOB_CHANNEL
     {"job_getchannel",	1, 1, f_job_getchannel},
-    {"job_info",	1, 1, f_job_info},
+    {"job_info",	0, 1, f_job_info},
     {"job_setoptions",	2, 2, f_job_setoptions},
     {"job_start",	1, 2, f_job_start},
     {"job_status",	1, 1, f_job_status},
@@ -7000,10 +7000,17 @@ f_job_getchannel(typval_T *argvars, typval_T *rettv)
     static void
 f_job_info(typval_T *argvars, typval_T *rettv)
 {
-    job_T	*job = get_job_arg(&argvars[0]);
-
-    if (job != NULL && rettv_dict_alloc(rettv) != FAIL)
-	job_info(job, rettv->vval.v_dict);
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+	job_T	*job = get_job_arg(&argvars[0]);
+	if (job != NULL && rettv_dict_alloc(rettv) != FAIL)
+	    job_info(job, rettv->vval.v_dict);
+    }
+    else
+    {
+	if (rettv_list_alloc(rettv) == OK)
+	    job_info_all(rettv->vval.v_list);
+    }
 }
 
 /*
diff --git a/src/proto/channel.pro b/src/proto/channel.pro
index 9b63490b7..8e2cc22ab 100644
--- a/src/proto/channel.pro
+++ b/src/proto/channel.pro
@@ -69,5 +69,6 @@ void job_check_ended(void);
 job_T *job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg);
 char *job_status(job_T *job);
 void job_info(job_T *job, dict_T *dict);
+void job_info_all(list_T *l);
 int job_stop(job_T *job, typval_T *argvars, char *type);
 /* vim: set ft=c : */
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 9de3ca01f..fa59b88f7 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -508,6 +508,7 @@ func Test_raw_pipe()
   let info = job_info(job)
   call assert_equal("dead", info.status)
   call assert_equal("term", info.stoponexit)
+  call assert_notequal([], job_info())
 endfunc
 
 func Test_nl_pipe()
