@@ -692,6 +692,7 @@ static const match_table_t opt_tokens = {
#ifdef CONFIG_NVME_TCP_TLS
{ NVMF_OPT_TLS, "tls" },
#endif
+ { NVMF_OPT_RECOVERY_DELAY, "recovery_delay=%d" },
{ NVMF_OPT_ERR, NULL }
};
@@ -1038,6 +1039,18 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
}
opts->tls = true;
break;
+ case NVMF_OPT_RECOVERY_DELAY:
+ if (match_int(args, &token)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (token <= 0) {
+ pr_err("Invalid recovery_delay %d\n", token);
+ ret = -EINVAL;
+ goto out;
+ }
+ opts->recovery_delay = token;
+ break;
default:
pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
p);
@@ -66,6 +66,7 @@ enum {
NVMF_OPT_TLS = 1 << 25,
NVMF_OPT_KEYRING = 1 << 26,
NVMF_OPT_TLS_KEY = 1 << 27,
+ NVMF_OPT_RECOVERY_DELAY = 1 << 28,
};
/**
@@ -92,6 +93,7 @@ enum {
* @queue_size: Number of IO queue elements.
* @nr_io_queues: Number of controller IO queues that will be established.
* @reconnect_delay: Time between two consecutive reconnect attempts.
+ * @recovery_delay: Time before error recovery starts after error detection.
* @discovery_nqn: indicates if the subsysnqn is the well-known discovery NQN.
* @kato: Keep-alive timeout.
* @host: Virtual NVMe host, contains the NQN and Host ID.
@@ -121,6 +123,7 @@ struct nvmf_ctrl_options {
size_t queue_size;
unsigned int nr_io_queues;
unsigned int reconnect_delay;
+ unsigned int recovery_delay;
bool discovery_nqn;
bool duplicate_connect;
unsigned int kato;
@@ -578,11 +578,15 @@ static void nvme_tcp_init_recv_ctx(struct nvme_tcp_queue *queue)
*/
static void nvme_tcp_error_recovery(struct nvme_ctrl *ctrl)
{
- unsigned long delay = nvme_keep_alive_work_period(ctrl);
+ unsigned long delay;
if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING))
return;
+ delay = ctrl->opts->recovery_delay * HZ;
+ if (!delay)
+ delay = nvme_keep_alive_work_period(ctrl);
+
dev_warn(ctrl->device, "starting error recovery in %lu seconds\n",
delay / HZ);
queue_delayed_work(nvme_reset_wq, &to_tcp_ctrl(ctrl)->err_work, delay);