@@ -148,6 +148,59 @@ do { \
info->send_credit_target); \
} while (0)
+static void cifs_destroy_rdma_work(struct work_struct *work)
+{
+ unsigned long flags;
+ struct cifs_rdma_response *response;
+ struct cifs_rdma_info *info =
+ container_of(work, struct cifs_rdma_info, destroy_work);
+
+ log_rdma_event("cancelling all pending works\n");
+
+ cancel_delayed_work_sync(&info->idle_timer_work);
+ cancel_delayed_work_sync(&info->send_immediate_work);
+
+ ib_drain_qp(info->id->qp);
+ rdma_destroy_qp(info->id);
+
+ log_rdma_event("wait for all send or recv finish\n");
+ wait_event(info->wait_send_pending,
+ atomic_read(&info->send_pending) == 0);
+ wait_event(info->wait_recv_pending,
+ atomic_read(&info->recv_pending) == 0);
+
+ ib_free_cq(info->cq);
+ ib_dealloc_pd(info->pd);
+ rdma_destroy_id(info->id);
+
+ log_rdma_event("drain the reassembly queue\n");
+ spin_lock_irqsave(&info->reassembly_queue_lock, flags);
+ while ((response = _get_first_reassembly(info))) {
+ put_receive_buffer(info, response);
+ }
+ atomic_set(&info->reassembly_data_length, 0);
+ spin_unlock_irqrestore(&info->reassembly_queue_lock, flags);
+ wake_up(&info->wait_reassembly_queue);
+
+ log_rdma_event("free buffers\n");
+ destroy_receive_buffers(info);
+
+ // free mempools
+ mempool_destroy(info->request_mempool);
+ kmem_cache_destroy(info->request_cache);
+
+ mempool_destroy(info->response_mempool);
+ kmem_cache_destroy(info->response_cache);
+
+ info->transport_status = CIFS_RDMA_DESTROYED;
+}
+
+static int cifs_rdma_process_disconnected(struct cifs_rdma_info *info)
+{
+ schedule_work(&info->destroy_work);
+ return 0;
+}
+
/* Upcall from RDMA CM */
static int cifs_rdma_conn_upcall(
struct rdma_cm_id *id, struct rdma_cm_event *event)
@@ -186,6 +239,7 @@ static int cifs_rdma_conn_upcall(
case RDMA_CM_EVENT_DISCONNECTED:
info->transport_status = CIFS_RDMA_DISCONNECTED;
+ cifs_rdma_process_disconnected(info);
break;
default:
@@ -1421,6 +1475,8 @@ struct cifs_rdma_info* cifs_create_rdma_session(
init_waitqueue_head(&info->wait_recv_pending);
atomic_set(&info->recv_pending, 0);
+ INIT_WORK(&info->destroy_work, cifs_destroy_rdma_work);
+
rc = cifs_rdma_negotiate(info);
if (!rc)
return info;
@@ -66,6 +66,8 @@ struct cifs_rdma_info {
struct completion negotiate_completion;
bool negotiate_done;
+ struct work_struct destroy_work;
+
//connection paramters
int receive_credit_max;
int send_credit_target;