Merge android-msm-pixel-4.14-sc-qpr3 into android-msm-pixel-4.14

SBMerger: 410055097
Change-Id: Ia1937fbaeee2785f0478e9f165f6a832b3f46eb1
Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
Signed-off-by: Lucas Wei <lucaswei@google.com>
diff --git a/arch/arm64/configs/floral_defconfig b/arch/arm64/configs/floral_defconfig
index ae47b44..d18a14a 100644
--- a/arch/arm64/configs/floral_defconfig
+++ b/arch/arm64/configs/floral_defconfig
@@ -493,6 +493,7 @@
 CONFIG_HID_STEAM=y
 CONFIG_HID_GREENASIA=y
 CONFIG_GREENASIA_FF=y
+CONFIG_HID_WACOM=y
 CONFIG_HID_WIIMOTE=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
@@ -531,8 +532,6 @@
 CONFIG_TYPEC_TCPM=y
 CONFIG_USB_PD_ENGINE=y
 CONFIG_QPNP_USB_PDPHY=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP_FLASH_V2=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_TRANSIENT=y
diff --git a/arch/arm64/configs/sunfish_defconfig b/arch/arm64/configs/sunfish_defconfig
index 7d91361..06ed6b8 100644
--- a/arch/arm64/configs/sunfish_defconfig
+++ b/arch/arm64/configs/sunfish_defconfig
@@ -477,6 +477,7 @@
 CONFIG_SONY_FF=y
 CONFIG_HID_GREENASIA=y
 CONFIG_GREENASIA_FF=y
+CONFIG_HID_WACOM=y
 CONFIG_HID_WIIMOTE=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
@@ -521,8 +522,6 @@
 CONFIG_TYPEC_TCPM=y
 CONFIG_USB_PD_ENGINE=y
 CONFIG_QPNP_USB_PDPHY=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_QPNP_FLASH_V2=y
 CONFIG_LEDS_QPNP_HAPTICS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index df601d4..a973454 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1,4 +1,4 @@
-/* Copyright (c)2017-2020, The Linux Foundation. All rights reserved.
+/* Copyright (c)2017-2020,2021 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -388,6 +388,7 @@
 	{ 0x8D0, 0x23, 0 },
 	{ 0x980, 0x4, 0 },
 	{ 0xA630, 0x0, 1 },
+	{ 0x1b400, 0x1fff, 1 },
 };
 
 /* IFPC & Preemption static powerup restore list */
diff --git a/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 1a99564..27fcef9 100644
--- a/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/ais/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019,2021 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -750,10 +750,12 @@
 	}
 
 	if ((packet->num_cmd_buf > 5) || !packet->num_patches ||
-		!packet->num_io_configs) {
-		CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u",
-			packet->num_cmd_buf,
-			packet->num_patches);
+	    !packet->num_io_configs ||
+	    (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) {
+		CAM_ERR(CAM_JPEG,
+			"wrong number of cmd/patch/io_configs info: %u %u %u",
+			packet->num_cmd_buf, packet->num_patches,
+			packet->num_io_configs);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 1a99564..27fcef9 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019,2021 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -750,10 +750,12 @@
 	}
 
 	if ((packet->num_cmd_buf > 5) || !packet->num_patches ||
-		!packet->num_io_configs) {
-		CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u",
-			packet->num_cmd_buf,
-			packet->num_patches);
+	    !packet->num_io_configs ||
+	    (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) {
+		CAM_ERR(CAM_JPEG,
+			"wrong number of cmd/patch/io_configs info: %u %u %u",
+			packet->num_cmd_buf, packet->num_patches,
+			packet->num_io_configs);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera_floral/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera_floral/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 9ea8e3f..ceaa1f6 100644
--- a/drivers/media/platform/msm/camera_floral/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_floral/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019,2021 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -745,10 +745,12 @@
 	}
 
 	if ((packet->num_cmd_buf > 5) || !packet->num_patches ||
-		!packet->num_io_configs) {
-		CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u",
-			packet->num_cmd_buf,
-			packet->num_patches);
+	    !packet->num_io_configs ||
+	    (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) {
+		CAM_ERR(CAM_JPEG,
+			"wrong number of cmd/patch/io_configs info: %u %u %u",
+			packet->num_cmd_buf, packet->num_patches,
+			packet->num_io_configs);
 		return -EINVAL;
 	}
 
diff --git a/drivers/mfd/adnc/iaxxx-btp.c b/drivers/mfd/adnc/iaxxx-btp.c
index d331e42..f727cdf 100644
--- a/drivers/mfd/adnc/iaxxx-btp.c
+++ b/drivers/mfd/adnc/iaxxx-btp.c
@@ -150,6 +150,10 @@
 	 * so calculate the offset and use it for first transaction
 	 */
 	addr_offset = phy_addr % IAXXX_MAC_WINDOW_SIZE;
+	if ((addr_offset >> 2) > btp_size) {
+		ret = -EINVAL;
+		goto exit;
+	}
 
 	while (words) {
 		/* Size of each transfer cannot exceed chunk size */
@@ -230,6 +234,10 @@
 	 * so calculate the offset and use it for first transaction
 	 */
 	addr_offset = phy_addr % IAXXX_MAC_WINDOW_SIZE;
+	if ((addr_offset >> 2) > btp_size) {
+		ret = -EINVAL;
+		goto exit;
+	}
 
 	while (words) {
 		/* Size of each transfer cannot exceed chunk size */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index dc2e030..55281f0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -3433,18 +3433,22 @@
 	list_for_each_entry(tbl, &set->head_rt_tbl_list, link) {
 		i = 0;
 		list_for_each_entry(entry, &tbl->head_rt_rule_list, link) {
-			if (entry->proc_ctx) {
+			if (entry->proc_ctx && entry->proc_ctx->offset_entry) {
 				ofst = entry->proc_ctx->offset_entry->offset;
 				ofst_words =
 					(ofst +
 					ipa3_ctx->hdr_proc_ctx_tbl.start_offset)
 					>> 5;
 
-				nbytes += scnprintf(msg_buff + nbytes,
-					max_buff_len - nbytes,
-					"tbl_idx:%d tbl_name:%s tbl_ref:%u\n",
-					entry->tbl->idx, entry->tbl->name,
-					entry->tbl->ref_cnt);
+				if (entry->tbl) {
+					nbytes += scnprintf(
+						msg_buff + nbytes,
+						max_buff_len - nbytes,
+						"tbl_idx:%d tbl_name:%s tbl_ref:%u\n",
+						entry->tbl->idx,
+						entry->tbl->name,
+						entry->tbl->ref_cnt);
+				}
 				nbytes += scnprintf(msg_buff + nbytes,
 					max_buff_len - nbytes,
 					"rule_idx:%d dst:%d ep:%d S:%u\n",
@@ -3472,16 +3476,20 @@
 					entry->rule.hashable,
 					entry->rule.retain_hdr);
 			} else {
-				if (entry->hdr)
+				if (entry->hdr && entry->hdr->offset_entry)
 					ofst = entry->hdr->offset_entry->offset;
 				else
 					ofst = 0;
 
-				nbytes += scnprintf(msg_buff + nbytes,
-					max_buff_len - nbytes,
-					"tbl_idx:%d tbl_name:%s tbl_ref:%u\n",
-					entry->tbl->idx, entry->tbl->name,
-					entry->tbl->ref_cnt);
+				if (entry->tbl) {
+					nbytes += scnprintf(
+						msg_buff + nbytes,
+						max_buff_len - nbytes,
+						"tbl_idx:%d tbl_name:%s tbl_ref:%u\n",
+						entry->tbl->idx,
+						entry->tbl->name,
+						entry->tbl->ref_cnt);
+				}
 				nbytes += scnprintf(msg_buff + nbytes,
 					max_buff_len - nbytes,
 					"rule_idx:%d dst:%d ep:%d S:%u\n",
diff --git a/drivers/power/supply/google/google_battery.c b/drivers/power/supply/google/google_battery.c
index c486daa..47ff65b 100644
--- a/drivers/power/supply/google/google_battery.c
+++ b/drivers/power/supply/google/google_battery.c
@@ -2012,6 +2012,7 @@
 	}
 
 	chg_health->dry_run_deadline = 0;
+	chg_health->active_time = 0;
 }
 
 /* should not reset rl state */
@@ -2256,13 +2257,14 @@
 
 #define HEALTH_PAUSE_DEBOUNCE 180
 #define HEALTH_PAUSE_MAX_SSOC 95
+#define HEALTH_PAUSE_TIME 3
 static bool msc_health_pause(struct batt_drv *batt_drv, const ktime_t ttf,
 			      const ktime_t now,
 			      const enum chg_health_state rest_state)
 {
 	const struct gbms_charging_event *ce_data = &batt_drv->ce_data;
 	const struct gbms_ce_tier_stats	*h = &ce_data->health_stats;
-	const struct batt_chg_health *rest = &batt_drv->chg_health;
+	struct batt_chg_health *rest = &batt_drv->chg_health;
 	const ktime_t deadline = rest->rest_deadline;
 	const ktime_t safety_margin = (ktime_t)batt_drv->health_safety_margin;
 	/* Note: We only capture ACTIVE time in health stats */
@@ -2287,17 +2289,31 @@
 		return false;
 
 	/*
-	 * elap_h: running active for a while wait status and current stable
 	 * ssoc: transfer in high soc impact charge full condition, disable
 	 * pause behavior in high soc
 	 */
-	if (elap_h < HEALTH_PAUSE_DEBOUNCE || ssoc > HEALTH_PAUSE_MAX_SSOC)
+	if (ssoc > HEALTH_PAUSE_MAX_SSOC)
+		return false;
+
+	/*
+	 * elap_h: running active for a while wait status and current stable
+	 * need to re-check before re-enter pause, so we need to minus previous
+	 * health active time (rest->active_time) for next HEALTH_PAUSE_DEBOUNCE
+	 */
+	if (elap_h - rest->active_time < HEALTH_PAUSE_DEBOUNCE)
+		return false;
+
+	/* prevent enter <---> leave PAUSE too many times */
+	if (rest->active_time > (HEALTH_PAUSE_TIME * HEALTH_PAUSE_DEBOUNCE))
 		return false;
 
 	/* check if time meets the PAUSE condition or not */
 	if (ttf > 0 && deadline > now + ttf + safety_margin)
 		return true;
 
+	/* record time for next pause check */
+	rest->active_time = elap_h;
+
 	return false;
 }
 
@@ -2487,13 +2503,17 @@
 	if (!changed)
 		return false;
 
-	pr_info("MSC_HEALTH: now=%d deadline=%d aon_soc=%d ttf=%ld state=%d->%d fv_uv=%d, cc_max=%d\n",
+	pr_info("MSC_HEALTH: now=%d deadline=%d aon_soc=%d ttf=%ld state=%d->%d fv_uv=%d, cc_max=%d"
+		" safety_margin=%d active_time:%d\n",
 		now, rest->rest_deadline, rest->always_on_soc,
-		ttf, rest->rest_state, rest_state, fv_uv, cc_max);
+		ttf, rest->rest_state, rest_state, fv_uv, cc_max,
+		batt_drv->health_safety_margin, rest->active_time);
 	logbuffer_log(batt_drv->ttf_stats.ttf_log,
-		      "MSC_HEALTH: now=%d deadline=%d aon_soc=%d ttf=%ld state=%d->%d fv_uv=%d, cc_max=%d\n",
+		      "MSC_HEALTH: now=%d deadline=%d aon_soc=%d ttf=%ld state=%d->%d fv_uv=%d, cc_max=%d"
+			  " safety_margin=%d active_time:%d\n",
 		      now, rest->rest_deadline, rest->always_on_soc,
-		      ttf, rest->rest_state, rest_state, fv_uv, cc_max);
+		      ttf, rest->rest_state, rest_state, fv_uv, cc_max,
+			  batt_drv->health_safety_margin, rest->active_time);
 
 	rest->rest_state = rest_state;
 	memcpy(&batt_drv->ce_data.ce_health, &batt_drv->chg_health,
diff --git a/drivers/power/supply/google/google_bms.h b/drivers/power/supply/google/google_bms.h
index fa5247f5..477641f 100644
--- a/drivers/power/supply/google/google_bms.h
+++ b/drivers/power/supply/google/google_bms.h
@@ -293,6 +293,7 @@
 	enum chg_health_state rest_state;
 	int rest_cc_max;
 	int rest_fv_uv;
+	ktime_t active_time;
 };
 
 #define CHG_HEALTH_REST_IS_ACTIVE(rest) \
diff --git a/drivers/power/supply/google/sm7150_bms.c b/drivers/power/supply/google/sm7150_bms.c
index 909a657..aecf04d 100644
--- a/drivers/power/supply/google/sm7150_bms.c
+++ b/drivers/power/supply/google/sm7150_bms.c
@@ -630,8 +630,6 @@
 	case SM7150_TAPER_CHARGE:
 		ret = POWER_SUPPLY_STATUS_CHARGING;
 		break;
-	/* pause on FCC=0, JEITA, USB/DC suspend or on INPUT UV/OV */
-	case SM7150_PAUSE_CHARGE:
 	case SM7150_INHIBIT_CHARGE:
 	case SM7150_TERMINATE_CHARGE:
 		/* flag full only at the correct voltage */
@@ -643,6 +641,8 @@
 		else
 			ret = POWER_SUPPLY_STATUS_FULL;
 		break;
+	/* pause on JEITA, USB/DC suspend or on INPUT UV/OV */
+	case SM7150_PAUSE_CHARGE:
 	/* disabled disconnect */
 	case SM7150_DISABLE_CHARGE:
 		ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
diff --git a/drivers/power/supply/google/sm8150_bms.c b/drivers/power/supply/google/sm8150_bms.c
index 0652684..37ef7b0f 100644
--- a/drivers/power/supply/google/sm8150_bms.c
+++ b/drivers/power/supply/google/sm8150_bms.c
@@ -660,8 +660,6 @@
 	case SM8150_TAPER_CHARGE:
 		ret = POWER_SUPPLY_STATUS_CHARGING;
 		break;
-	/* pause on FCC=0, JEITA, USB/DC suspend or on INPUT UV/OV */
-	case SM8150_PAUSE_CHARGE:
 	case SM8150_INHIBIT_CHARGE:
 	case SM8150_TERMINATE_CHARGE:
 		/* flag full only at the correct voltage */
@@ -673,6 +671,8 @@
 		else
 			ret = POWER_SUPPLY_STATUS_FULL;
 		break;
+	/* pause on JEITA, USB/DC suspend or on INPUT UV/OV */
+	case SM8150_PAUSE_CHARGE:
 	/* disabled disconnect */
 	case SM8150_DISABLE_CHARGE:
 		ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index b0025bd..d4dd488 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1772,6 +1772,18 @@
 	struct usb_function		*f = NULL;
 	u8				endp;
 
+	if (w_length > USB_COMP_EP0_BUFSIZ) {
+		if (ctrl->bRequestType & USB_DIR_IN) {
+			/* Cast away the const, we are going to overwrite on purpose. */
+			__le16 *temp = (__le16 *)&ctrl->wLength;
+
+			*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
+			w_length = USB_COMP_EP0_BUFSIZ;
+		} else {
+			goto done;
+		}
+	}
+
 	/* partial re-init of the response message; the function or the
 	 * gadget might need to intercept e.g. a control-OUT completion
 	 * when we delegate to it.
@@ -2313,7 +2325,7 @@
 	if (!cdev->req)
 		return -ENOMEM;
 
-	cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
+	cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
 	if (!cdev->req->buf)
 		goto fail;
 
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 8f4fb34..2707e5e 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1802,11 +1802,13 @@
 	if (atomic_dec_and_test(&ffs->opened)) {
 		if (ffs->no_disconnect) {
 			ffs->state = FFS_DEACTIVATED;
+			mutex_lock(&ffs->mutex);
 			if (ffs->epfiles) {
 				ffs_epfiles_destroy(ffs->epfiles,
 						   ffs->eps_count);
 				ffs->epfiles = NULL;
 			}
+			mutex_unlock(&ffs->mutex);
 			if (ffs->setup_state == FFS_SETUP_PENDING)
 				__ffs_ep0_stall(ffs);
 		} else {
@@ -1878,8 +1880,12 @@
 
 	BUG_ON(ffs->gadget);
 
-	if (ffs->epfiles)
+	mutex_lock(&ffs->mutex);
+	if (ffs->epfiles) {
 		ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
+		ffs->epfiles = NULL;
+	}
+	mutex_unlock(&ffs->mutex);
 
 	if (ffs->ffs_eventfd)
 		eventfd_ctx_put(ffs->ffs_eventfd);
@@ -1898,7 +1904,6 @@
 
 	ffs_data_clear(ffs);
 
-	ffs->epfiles = NULL;
 	ffs->raw_descs_data = NULL;
 	ffs->raw_descs = NULL;
 	ffs->raw_strings = NULL;
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index 99ca3da..e8818ad 100644
--- a/drivers/usb/gadget/legacy/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
@@ -136,7 +136,7 @@
 		goto fail_1;
 	}
 
-	req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL);
+	req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL);
 	if (!req->buf) {
 		err = -ENOMEM;
 		stp = 2;
@@ -344,6 +344,19 @@
 	void *data = NULL;
 	u16 len = 0;
 
+	if (length > DBGP_REQ_LEN) {
+		if (ctrl->bRequestType & USB_DIR_IN) {
+			/* Cast away the const, we are going to overwrite on purpose. */
+			__le16 *temp = (__le16 *)&ctrl->wLength;
+
+			*temp = cpu_to_le16(DBGP_REQ_LEN);
+			length = DBGP_REQ_LEN;
+		} else {
+			return err;
+		}
+	}
+
+
 	if (request == USB_REQ_GET_DESCRIPTOR) {
 		switch (value>>8) {
 		case USB_DT_DEVICE:
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index e9f7f26..c67d53b 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -113,6 +113,8 @@
 /* enough for the whole queue: most events invalidate others */
 #define	N_EVENT			5
 
+#define RBUF_SIZE		256
+
 struct dev_data {
 	spinlock_t			lock;
 	refcount_t			count;
@@ -147,7 +149,7 @@
 	struct dentry			*dentry;
 
 	/* except this scratch i/o buffer for ep0 */
-	u8				rbuf [256];
+	u8				rbuf[RBUF_SIZE];
 };
 
 static inline void get_dev (struct dev_data *data)
@@ -1336,6 +1338,18 @@
 	u16				w_value = le16_to_cpu(ctrl->wValue);
 	u16				w_length = le16_to_cpu(ctrl->wLength);
 
+	if (w_length > RBUF_SIZE) {
+		if (ctrl->bRequestType & USB_DIR_IN) {
+			/* Cast away the const, we are going to overwrite on purpose. */
+			__le16 *temp = (__le16 *)&ctrl->wLength;
+
+			*temp = cpu_to_le16(RBUF_SIZE);
+			w_length = RBUF_SIZE;
+		} else {
+			return value;
+		}
+	}
+
 	spin_lock (&dev->lock);
 	dev->setup_abort = 0;
 	if (dev->state == STATE_DEV_UNCONNECTED) {
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 177325c..e099738 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4477,9 +4477,10 @@
 	}
 
 out_free_pg_vec:
-	bitmap_free(rx_owner_map);
-	if (pg_vec)
+	if (pg_vec) {
+		bitmap_free(rx_owner_map);
 		free_pg_vec(pg_vec, order, req->tp_block_nr);
+	}
 out:
 	return err;
 }