Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7b4e9f4 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "byte-cntr: Don't start usb transfer when rwp offset is invalid"

parents e6498863 3109d0a3
Loading
Loading
Loading
Loading
+52 −26
Original line number Diff line number Diff line
@@ -189,6 +189,8 @@ static int tmc_etr_byte_cntr_release(struct inode *in, struct file *fp)

int usb_bypass_start(struct byte_cntr *byte_cntr_data)
{
	long offset;

	if (!byte_cntr_data)
		return -ENOMEM;

@@ -200,7 +202,15 @@ int usb_bypass_start(struct byte_cntr *byte_cntr_data)
	}

	atomic_set(&byte_cntr_data->usb_free_buf, USB_BUF_NUM);
	byte_cntr_data->offset = tmc_sg_get_rwp_offset(tmcdrvdata);

	offset = tmc_sg_get_rwp_offset(tmcdrvdata);
	if (offset < 0) {
		dev_err(&tmcdrvdata->csdev->dev,
			"%s: invalid rwp offset value\n", __func__);
		return offset;
	}
	byte_cntr_data->offset = offset;

	byte_cntr_data->read_active = true;
	/*
	 * IRQ is a '8- byte' counter and to observe interrupt at
@@ -326,6 +336,13 @@ static int usb_transfer_small_packet(struct qdss_request *usb_req,
	long w_offset;

	w_offset = tmc_sg_get_rwp_offset(tmcdrvdata);
	if (w_offset < 0) {
		ret = w_offset;
		dev_err_ratelimited(&tmcdrvdata->csdev->dev,
			"%s: RWP offset is invalid\n", __func__);
		goto out;
	}

	req_size = ((w_offset < drvdata->offset) ? etr_buf->size : 0) +
				w_offset - drvdata->offset;
	req_size = ((req_size + *small_size) < USB_BLK_SIZE) ? req_size :
@@ -333,8 +350,7 @@ static int usb_transfer_small_packet(struct qdss_request *usb_req,

	while (req_size > 0) {

		usb_req = devm_kzalloc(tmcdrvdata->dev, sizeof(*usb_req),
			GFP_KERNEL);
		usb_req = kzalloc(sizeof(*usb_req), GFP_KERNEL);
		if (!usb_req) {
			ret = -EFAULT;
			goto out;
@@ -342,6 +358,16 @@ static int usb_transfer_small_packet(struct qdss_request *usb_req,

		actual = tmc_etr_buf_get_data(etr_buf, drvdata->offset,
					req_size, &usb_req->buf);

		if (actual <= 0 || actual > req_size) {
			kfree(usb_req);
			usb_req = NULL;
			dev_err_ratelimited(&tmcdrvdata->csdev->dev,
				"%s: Invalid data in ETR\n", __func__);
			ret = -EINVAL;
			goto out;
		}

		usb_req->length = actual;
		drvdata->usb_req = usb_req;
		req_size -= actual;
@@ -358,7 +384,7 @@ static int usb_transfer_small_packet(struct qdss_request *usb_req,
			ret = usb_qdss_write(tmcdrvdata->usbch, usb_req);

			if (ret) {
				devm_kfree(tmcdrvdata->dev, usb_req);
				kfree(usb_req);
				usb_req = NULL;
				drvdata->usb_req = NULL;
				dev_err_ratelimited(tmcdrvdata->dev,
@@ -371,7 +397,7 @@ static int usb_transfer_small_packet(struct qdss_request *usb_req,
			dev_dbg(tmcdrvdata->dev,
			"Drop data, offset = %d, len = %d\n",
				drvdata->offset, req_size);
			devm_kfree(tmcdrvdata->dev, usb_req);
			kfree(usb_req);
			drvdata->usb_req = NULL;
		}
	}
@@ -422,15 +448,13 @@ static void usb_read_work_fn(struct work_struct *work)
		if (req_size > 0) {
			seq++;
			req_sg_num = (req_size - 1) / PAGE_SIZE + 1;
			usb_req = devm_kzalloc(tmcdrvdata->dev,
						sizeof(*usb_req), GFP_KERNEL);
			usb_req = kzalloc(sizeof(*usb_req), GFP_KERNEL);
			if (!usb_req)
				return;
			usb_req->sg = devm_kzalloc(tmcdrvdata->dev,
					sizeof(*(usb_req->sg)) * req_sg_num,
					GFP_KERNEL);
			usb_req->sg = kcalloc(req_sg_num,
				sizeof(*(usb_req->sg)), GFP_KERNEL);
			if (!usb_req->sg) {
				devm_kfree(tmcdrvdata->dev, usb_req);
				kfree(usb_req);
				usb_req = NULL;
				return;
			}
@@ -440,13 +464,13 @@ static void usb_read_work_fn(struct work_struct *work)
							drvdata->offset,
							PAGE_SIZE, &buf);

				if (actual <= 0) {
					devm_kfree(tmcdrvdata->dev,
							usb_req->sg);
					devm_kfree(tmcdrvdata->dev, usb_req);
				if (actual <= 0 || actual > PAGE_SIZE) {
					kfree(usb_req->sg);
					kfree(usb_req);
					usb_req = NULL;
					dev_err_ratelimited(tmcdrvdata->dev,
						 "No data in ETR\n");
					dev_err_ratelimited(
						&tmcdrvdata->csdev->dev,
						"Invalid data in ETR\n");
					return;
				}

@@ -473,9 +497,8 @@ static void usb_read_work_fn(struct work_struct *work)
				ret = usb_qdss_write(tmcdrvdata->usbch,
						drvdata->usb_req);
				if (ret) {
					devm_kfree(tmcdrvdata->dev,
							usb_req->sg);
					devm_kfree(tmcdrvdata->dev, usb_req);
					kfree(usb_req->sg);
					kfree(usb_req);
					usb_req = NULL;
					drvdata->usb_req = NULL;
					dev_err_ratelimited(tmcdrvdata->dev,
@@ -491,8 +514,8 @@ static void usb_read_work_fn(struct work_struct *work)
				"Drop data, offset = %d, seq = %d, irq = %d\n",
					drvdata->offset, seq,
					atomic_read(&drvdata->irq_cnt));
				devm_kfree(tmcdrvdata->dev, usb_req->sg);
				devm_kfree(tmcdrvdata->dev, usb_req);
				kfree(usb_req->sg);
				kfree(usb_req);
				drvdata->usb_req = NULL;
			}
		}
@@ -509,15 +532,15 @@ static void usb_write_done(struct byte_cntr *drvdata,
	atomic_inc(&drvdata->usb_free_buf);
	if (d_req->status)
		pr_err_ratelimited("USB write failed err:%d\n", d_req->status);
	if (d_req->sg)
		devm_kfree(tmcdrvdata->dev, d_req->sg);
	devm_kfree(tmcdrvdata->dev, d_req);
	kfree(d_req->sg);
	kfree(d_req);
}

void usb_bypass_notifier(void *priv, unsigned int event,
			struct qdss_request *d_req, struct usb_qdss_ch *ch)
{
	struct byte_cntr *drvdata = priv;
	int ret;

	if (!drvdata)
		return;
@@ -531,8 +554,11 @@ void usb_bypass_notifier(void *priv, unsigned int event,

	switch (event) {
	case USB_QDSS_CONNECT:
		ret = usb_bypass_start(drvdata);
		if (ret < 0)
			return;

		usb_qdss_alloc_req(ch, USB_BUF_NUM);
		usb_bypass_start(drvdata);
		queue_work(drvdata->usb_wq, &(drvdata->read_work));
		break;