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

Commit 2e98d6c8 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "u_ether: Handle memory allocation failure case on tx path"

parents 7c9cdac7 7d4a6cb4
Loading
Loading
Loading
Loading
+15 −12
Original line number Diff line number Diff line
@@ -1144,7 +1144,7 @@ int rndis_rm_hdr(struct gether *port,
			struct sk_buff *skb,
			struct sk_buff_head *list)
{
	int num_pkts = 1;
	int num_pkts = 0;

	if (skb->len > rndis_ul_max_xfer_size_rcvd)
		rndis_ul_max_xfer_size_rcvd = skb->len;
@@ -1154,12 +1154,6 @@ int rndis_rm_hdr(struct gether *port,
		struct sk_buff          *skb2;
		u32             msg_len, data_offset, data_len;

		/* some rndis hosts send extra byte to avoid zlp, ignore it */
		if (skb->len == 1) {
			dev_kfree_skb_any(skb);
			return 0;
		}

		if (skb->len < sizeof *hdr) {
			pr_err("invalid rndis pkt: skblen:%u hdr_len:%zu",
					skb->len, sizeof *hdr);
@@ -1188,9 +1182,12 @@ int rndis_rm_hdr(struct gether *port,
			return -EINVAL;
		}

		num_pkts++;

		skb_pull(skb, data_offset + 8);

		if (msg_len == skb->len) {
		if (data_len == skb->len ||
				data_len == (skb->len - 1)) {
			skb_trim(skb, data_len);
			break;
		}
@@ -1205,8 +1202,6 @@ int rndis_rm_hdr(struct gether *port,
		skb_pull(skb, msg_len - sizeof *hdr);
		skb_trim(skb2, data_len);
		skb_queue_tail(list, skb2);

		num_pkts++;
	}

	if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd)
@@ -1244,7 +1239,9 @@ static int rndis_proc_show(struct seq_file *m, void *v)
			 "speed     : %d\n"
			 "cable     : %s\n"
			 "vendor ID : 0x%08X\n"
			 "vendor    : %s\n",
			 "vendor    : %s\n"
			 "ul-max-xfer-size:%zu max-xfer-size-rcvd: %d\n"
			 "ul-max-pkts-per-xfer:%d max-pkts-per-xfer-rcvd:%d\n",
			 param->confignr, (param->used) ? "y" : "n",
			 ({ char *s = "?";
			 switch (param->state) {
@@ -1258,7 +1255,13 @@ static int rndis_proc_show(struct seq_file *m, void *v)
			 param->medium,
			 (param->media_state) ? 0 : param->speed*100,
			 (param->media_state) ? "disconnected" : "connected",
			 param->vendorID, param->vendorDescr);
			 param->vendorID, param->vendorDescr,
			 param->dev ? param->max_pkt_per_xfer *
				 (param->dev->mtu + sizeof(struct ethhdr) +
				 sizeof(struct rndis_packet_msg_type) + 22) : 0,
			 rndis_ul_max_xfer_size_rcvd,
			 param->max_pkt_per_xfer,
			 rndis_ul_max_pkt_per_xfer_rcvd);
	return 0;
}

+23 −4
Original line number Diff line number Diff line
@@ -613,7 +613,7 @@ static inline int is_promisc(u16 cdc_filter)
	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
}

static void alloc_tx_buffer(struct eth_dev *dev)
static int alloc_tx_buffer(struct eth_dev *dev)
{
	struct list_head	*act;
	struct usb_request	*req;
@@ -630,7 +630,21 @@ static void alloc_tx_buffer(struct eth_dev *dev)
		if (!req->buf)
			req->buf = kmalloc(dev->tx_req_bufsize,
						GFP_ATOMIC);

		if (!req->buf)
			goto free_buf;
	}
	return 0;

free_buf:
	/* tx_req_bufsize = 0 retries mem alloc on next eth_start_xmit */
	dev->tx_req_bufsize = 0;
	list_for_each(act, &dev->tx_reqs) {
		req = container_of(act, struct usb_request, list);
		kfree(req->buf);
		req->buf = NULL;
	}
	return -ENOMEM;
}

static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
@@ -662,8 +676,11 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
	}

	/* Allocate memory for tx_reqs to support multi packet transfer */
	if (multi_pkt_xfer && !dev->tx_req_bufsize)
		alloc_tx_buffer(dev);
	if (multi_pkt_xfer && !dev->tx_req_bufsize) {
		retval = alloc_tx_buffer(dev);
		if (retval < 0)
			return -ENOMEM;
	}

	/* apply outgoing CDC or RNDIS filters */
	if (skb && !is_promisc(cdc_filter)) {
@@ -1534,8 +1551,10 @@ void gether_disconnect(struct gether *link)
			list_del(&req->list);

			spin_unlock(&dev->req_lock);
			if (link->multi_pkt_xfer)
			if (link->multi_pkt_xfer) {
				kfree(req->buf);
				req->buf = NULL;
			}
			usb_ep_free_request(link->in_ep, req);
			spin_lock(&dev->req_lock);
		}