]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/infiniband/hw/i40iw/i40iw_utils.c
i40iw: Add missing cleanup on device close
[karo-tx-linux.git] / drivers / infiniband / hw / i40iw / i40iw_utils.c
index 6fd043b1d71413fbcebe8a209121a9cee50a5586..58151280828d72c8462f516453a8b18639e4bfc1 100644 (file)
@@ -392,6 +392,7 @@ static void i40iw_free_qp(struct i40iw_cqp_request *cqp_request, u32 num)
 
        i40iw_rem_pdusecount(iwqp->iwpd, iwdev);
        i40iw_free_qp_resources(iwdev, iwqp, qp_num);
+       i40iw_rem_devusecount(iwdev);
 }
 
 /**
@@ -458,6 +459,26 @@ enum i40iw_status_code i40iw_handle_cqp_op(struct i40iw_device *iwdev,
        return status;
 }
 
+/**
+ * i40iw_add_devusecount - add dev refcount
+ * @iwdev: dev for refcount
+ */
+void i40iw_add_devusecount(struct i40iw_device *iwdev)
+{
+       atomic64_inc(&iwdev->use_count);
+}
+
+/**
+ * i40iw_rem_devusecount - decrement refcount for dev
+ * @iwdev: device
+ */
+void i40iw_rem_devusecount(struct i40iw_device *iwdev)
+{
+       if (!atomic64_dec_and_test(&iwdev->use_count))
+               return;
+       wake_up(&iwdev->close_wq);
+}
+
 /**
  * i40iw_add_pdusecount - add pd refcount
  * @iwpd: pd for refcount
@@ -711,6 +732,51 @@ enum i40iw_status_code i40iw_cqp_sds_cmd(struct i40iw_sc_dev *dev,
        return status;
 }
 
+/**
+ * i40iw_qp_suspend_resume - cqp command for suspend/resume
+ * @dev: hardware control device structure
+ * @qp: hardware control qp
+ * @suspend: flag if suspend or resume
+ */
+void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, bool suspend)
+{
+       struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+       struct i40iw_cqp_request *cqp_request;
+       struct i40iw_sc_cqp *cqp = dev->cqp;
+       struct cqp_commands_info *cqp_info;
+       enum i40iw_status_code status;
+
+       cqp_request = i40iw_get_cqp_request(&iwdev->cqp, false);
+       if (!cqp_request)
+               return;
+
+       cqp_info = &cqp_request->info;
+       cqp_info->cqp_cmd = (suspend) ? OP_SUSPEND : OP_RESUME;
+       cqp_info->in.u.suspend_resume.cqp = cqp;
+       cqp_info->in.u.suspend_resume.qp = qp;
+       cqp_info->in.u.suspend_resume.scratch = (uintptr_t)cqp_request;
+       status = i40iw_handle_cqp_op(iwdev, cqp_request);
+       if (status)
+               i40iw_pr_err("CQP-OP QP Suspend/Resume fail");
+}
+
+/**
+ * i40iw_qp_mss_modify - modify mss for qp
+ * @dev: hardware control device structure
+ * @qp: hardware control qp
+ */
+void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
+{
+       struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+       struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
+       struct i40iw_modify_qp_info info;
+
+       memset(&info, 0, sizeof(info));
+       info.mss_change = true;
+       info.new_mss = dev->mss;
+       i40iw_hw_modify_qp(iwdev, iwqp, &info, false);
+}
+
 /**
  * i40iw_term_modify_qp - modify qp for term message
  * @qp: hardware control qp
@@ -1208,7 +1274,7 @@ enum i40iw_status_code i40iw_puda_get_tcpip_info(struct i40iw_puda_completion_in
 
        buf->totallen = pkt_len + buf->maclen;
 
-       if (info->payload_len < buf->totallen - 4) {
+       if (info->payload_len < buf->totallen) {
                i40iw_pr_err("payload_len = 0x%x totallen expected0x%x\n",
                             info->payload_len, buf->totallen);
                return I40IW_ERR_INVALID_SIZE;