All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-13  1:48 ` Shuah Khan
  0 siblings, 0 replies; 26+ messages in thread
From: Shuah Khan @ 2016-03-13  1:48 UTC (permalink / raw)
  To: mchehab, kyungmin.park, a.hajda, sakari.ailus, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606
  Cc: Shuah Khan, linux-media, linux-kernel, linux-arm-kernel,
	linux-samsung-soc, linux-renesas-soc, devel, alsa-devel

Add GFP flags to media_create_pad_link(), media_create_intf_link(),
media_devnode_create(), and media_add_link() that could get called
in atomic context to allow callers to pass in the right flags for
memory allocation.

tree-wide driver changes for media_*() GFP flags change:
Change drivers to add gfpflags to interffaces, media_create_pad_link(),
media_create_intf_link() and media_devnode_create().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
---
Ran through kbuild-all compile testing.
Tested the changes in Win-TV HVR-950Q device

 drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
 drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
 drivers/media/i2c/s5k5baf.c                        |  3 +-
 drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
 drivers/media/i2c/tvp5150.c                        |  3 +-
 drivers/media/media-entity.c                       | 30 ++++++++------
 drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
 drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
 drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
 drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
 drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
 drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
 drivers/media/usb/au0828/au0828-core.c             |  3 +-
 drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
 drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
 drivers/media/v4l2-core/v4l2-device.c              |  3 +-
 drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
 drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
 drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
 drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
 .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
 drivers/staging/media/omap4iss/iss.c               | 17 +++++---
 drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
 drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
 drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
 include/media/media-entity.h                       |  9 +++--
 sound/usb/media.c                                  | 15 ++++---
 27 files changed, 170 insertions(+), 106 deletions(-)

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index e1684c5..57f3e1e 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 
 	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
 						    intf_type, 0,
-						    DVB_MAJOR, minor);
+						    DVB_MAJOR, minor,
+						    GFP_KERNEL);
 
 	if (!dvbdev->intf_devnode)
 		return -ENOMEM;
@@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 		return 0;
 
 	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
-				      MEDIA_LNK_FL_ENABLED);
+				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 	if (!link)
 		return -ENOMEM;
 #endif
@@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
 			if (strncmp(entity->name, name, strlen(name)))
 				continue;
 			link = media_create_intf_link(entity, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
@@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 	}
 	if (demux && ca) {
 		ret = media_create_pad_link(demux, 1, ca,
-					    0, MEDIA_LNK_FL_ENABLED);
+					    0, MEDIA_LNK_FL_ENABLED,
+					    GFP_KERNEL);
 		if (ret)
 			return -ENOMEM;
 	}
@@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 				    strlen(DVR_TSOUT))) {
 					ret = media_create_pad_link(demux,
 								++dvr_pad,
-							    entity, 0, 0);
+							    entity, 0, 0,
+								GFP_KERNEL);
 					if (ret)
 						return ret;
 				}
@@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 				    strlen(DEMUX_TSOUT))) {
 					ret = media_create_pad_link(demux,
 							      ++demux_pad,
-							    entity, 0, 0);
+							    entity, 0, 0,
+								GFP_KERNEL);
 					if (ret)
 						return ret;
 				}
@@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 	media_device_for_each_intf(intf, mdev) {
 		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
 			link = media_create_intf_link(ca, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
 
 		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
 			link = media_create_intf_link(tuner, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
@@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 		 */
 		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
 			link = media_create_intf_link(demux, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index 08af58f..dd994f1 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
 
 	ret = media_create_pad_link(&state->sensor_sd.entity,
 			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
-			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
+			GFP_KERNEL);
 
 	ret = media_create_pad_link(&state->sensor_sd.entity,
 			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
-			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
+			GFP_KERNEL);
 
 	return ret;
 }
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index db82ed0..3692bec 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
 		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
 					       &state->sd.entity, PAD_CIS,
 					       MEDIA_LNK_FL_IMMUTABLE |
-					       MEDIA_LNK_FL_ENABLED);
+					       MEDIA_LNK_FL_ENABLED,
+					       GFP_KERNEL);
 	return ret;
 }
 
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index a215efe..8c2e9ad 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
 					     &last->sd.entity,
 					     last->sink_pad,
 					     MEDIA_LNK_FL_ENABLED |
-					     MEDIA_LNK_FL_IMMUTABLE);
+					     MEDIA_LNK_FL_IMMUTABLE,
+					     GFP_KERNEL);
 		if (rval) {
 			dev_err(&client->dev,
 				"media_create_pad_link failed\n");
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index ff18444..fd99683 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
 			return ret;
 
 		ret = media_create_pad_link(input, 0, &sd->entity,
-					    DEMOD_PAD_IF_INPUT, 0);
+					    DEMOD_PAD_IF_INPUT, 0,
+					    GFP_KERNEL);
 		if (ret < 0) {
 			media_device_unregister_entity(input);
 			return ret;
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 66a5392..115435b 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
  * Links management
  */
 
-static struct media_link *media_add_link(struct list_head *head)
+static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
 {
 	struct media_link *link;
 
 	if (in_atomic())
 		dump_stack();
 
-	link = kzalloc(sizeof(*link), GFP_KERNEL);
+	link = kzalloc(sizeof(*link), gfpflags);
 	if (link == NULL)
 		return NULL;
 
@@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
 
 int
 media_create_pad_link(struct media_entity *source, u16 source_pad,
-			 struct media_entity *sink, u16 sink_pad, u32 flags)
+		      struct media_entity *sink, u16 sink_pad, u32 flags,
+		      gfp_t gfpflags)
 {
 	struct media_link *link;
 	struct media_link *backlink;
@@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	BUG_ON(source_pad >= source->num_pads);
 	BUG_ON(sink_pad >= sink->num_pads);
 
-	link = media_add_link(&source->links);
+	link = media_add_link(&source->links, gfpflags);
 	if (link == NULL)
 		return -ENOMEM;
 
@@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	/* Create the backlink. Backlinks are used to help graph traversal and
 	 * are not reported to userspace.
 	 */
-	backlink = media_add_link(&sink->links);
+	backlink = media_add_link(&sink->links, gfpflags);
 	if (backlink == NULL) {
 		__media_entity_remove_link(source, link);
 		return -ENOMEM;
@@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
 	/* Trivial case: 1:1 relation */
 	if (source && sink)
 		return media_create_pad_link(source, source_pad,
-					     sink, sink_pad, flags);
+					     sink, sink_pad, flags, GFP_KERNEL);
 
 	/* Worse case scenario: n:n relation */
 	if (!source && !sink) {
@@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
 					continue;
 				ret = media_create_pad_link(source, source_pad,
 							    sink, sink_pad,
-							    flags);
+							    flags, GFP_KERNEL);
 				if (ret)
 					return ret;
 				flags &= ~(MEDIA_LNK_FL_ENABLED |
@@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
 
 		if (source)
 			ret = media_create_pad_link(source, source_pad,
-						    entity, sink_pad, flags);
+						    entity, sink_pad, flags,
+						    GFP_KERNEL);
 		else
 			ret = media_create_pad_link(entity, source_pad,
-						    sink, sink_pad, flags);
+						    sink, sink_pad, flags,
+						    GFP_KERNEL);
 		if (ret)
 			return ret;
 		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
@@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
 
 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 						u32 type, u32 flags,
-						u32 major, u32 minor)
+						u32 major, u32 minor,
+						gfp_t gfpflags)
 {
 	struct media_intf_devnode *devnode;
 
 	if (in_atomic())
 		dump_stack();
 
-	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
+	devnode = kzalloc(sizeof(*devnode), gfpflags);
 	if (!devnode)
 		return NULL;
 
@@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
 
 struct media_link *media_create_intf_link(struct media_entity *entity,
 					    struct media_interface *intf,
-					    u32 flags)
+					    u32 flags, gfp_t gfpflags)
 {
 	struct media_link *link;
 
-	link = media_add_link(&intf->links);
+	link = media_add_link(&intf->links, gfpflags);
 	if (link == NULL)
 		return NULL;
 
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index feb521f..145d90e 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
 
 		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
 		ret = media_create_pad_link(source, pad, sink,
-					      FIMC_SD_PAD_SINK_CAM, flags);
+					      FIMC_SD_PAD_SINK_CAM, flags,
+					    GFP_KERNEL);
 		if (ret)
 			return ret;
 
@@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
 
 		sink = &fmd->fimc_lite[i]->subdev.entity;
 		ret = media_create_pad_link(source, pad, sink,
-					       FLITE_SD_PAD_SINK, 0);
+					       FLITE_SD_PAD_SINK, 0,
+					    GFP_KERNEL);
 		if (ret)
 			return ret;
 
@@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
 		sink = &fimc->ve.vdev.entity;
 		/* FIMC-LITE's subdev and video node */
 		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
-					       sink, 0, 0);
+					       sink, 0, 0, GFP_KERNEL);
 		if (ret)
 			break;
 		/* Link from FIMC-LITE to IS-ISP subdev */
 		sink = &fmd->fimc_is->isp.subdev.entity;
 		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
-					       sink, 0, 0);
+					       sink, 0, 0, GFP_KERNEL);
 		if (ret)
 			break;
 	}
@@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
 		/* Link from FIMC-IS-ISP subdev to FIMC */
 		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
 		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
-					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
+					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
+					    GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
 		return 0;
 
 	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
-					sink, 0, 0);
+					sink, 0, 0, GFP_KERNEL);
 }
 
 /**
@@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
 			ret = media_create_pad_link(&sensor->entity, pad,
 					      &csis->entity, CSIS_PAD_SINK,
 					      MEDIA_LNK_FL_IMMUTABLE |
-					      MEDIA_LNK_FL_ENABLED);
+					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 			if (ret)
 				return ret;
 
@@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
 		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
 
 		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
-					      sink, 0, flags);
+					      sink, 0, flags, GFP_KERNEL);
 		if (ret)
 			break;
 	}
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 5d54e2c..f8d9c84 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1669,7 +1669,7 @@ static int isp_link_entity(
 		return -EINVAL;
 	}
 
-	return media_create_pad_link(entity, i, input, pad, flags);
+	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
 }
 
 static int isp_register_entities(struct isp_device *isp)
@@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
 	/* Create links between entities and video nodes. */
 	ret = media_create_pad_link(
 			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&isp->isp_csi2a.video_out.video.entity, 0, 0);
+			&isp->isp_csi2a.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccp2.video_in.video.entity, 0,
-			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
+			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
-			&isp->isp_ccdc.video_out.video.entity, 0, 0);
+			&isp->isp_ccdc.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_prev.video_in.video.entity, 0,
-			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
-			&isp->isp_prev.video_out.video.entity, 0, 0);
+			&isp->isp_prev.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_res.video_in.video.entity, 0,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
-			&isp->isp_res.video_out.video.entity, 0, 0);
+			&isp->isp_res.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 
 	if (ret < 0)
 		return ret;
@@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
 	/* Create links between entities. */
 	ret = media_create_pad_link(
 			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
-			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
 			&isp->isp_aewb.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
 			&isp->isp_af.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
 			&isp->isp_hist.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index 0b44b9a..a49b4c3 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
 	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
 				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
 				MEDIA_LNK_FL_IMMUTABLE |
-				MEDIA_LNK_FL_ENABLED);
+				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 	if (ret)
 		return ret;
 
@@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
 		ret = media_create_pad_link(&camif->subdev.entity, i,
 				&camif->vp[i - 1].vdev.entity, 0,
 				MEDIA_LNK_FL_IMMUTABLE |
-				MEDIA_LNK_FL_ENABLED);
+				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 	}
 
 	return ret;
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 021fe57..f868dec 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 		ret = media_create_pad_link(&rpf->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
 					    &vsp1->bru->entity.subdev.entity,
-					    i, flags);
+					    i, flags, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 
@@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
 				    vsp1->bru->entity.source_pad,
 				    &vsp1->wpf[0]->entity.subdev.entity,
-				    RWPF_PAD_SINK, flags);
+				    RWPF_PAD_SINK, flags, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
@@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
 				    RWPF_PAD_SOURCE,
 				    &vsp1->lif->entity.subdev.entity,
-				    LIF_PAD_SINK, flags);
+				    LIF_PAD_SINK, flags, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 25750a0..7295587 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
 
 			ret = media_create_pad_link(&source->subdev.entity,
 						       source->source_pad,
-						       entity, pad, flags);
+						       entity, pad, flags,
+						    GFP_KERNEL);
 			if (ret < 0)
 				return ret;
 
@@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
 					    &vsp1->lif->entity.subdev.entity,
-					    LIF_PAD_SINK, 0);
+					    LIF_PAD_SINK, 0, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
@@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 					    &rpf->entity.subdev.entity,
 					    RWPF_PAD_SINK,
 					    MEDIA_LNK_FL_ENABLED |
-					    MEDIA_LNK_FL_IMMUTABLE);
+					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
@@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 		ret = media_create_pad_link(&wpf->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
 					    &wpf->video->video.entity, 0,
-					    flags);
+					    flags, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index e795a45..b444db4 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
 
 		ret = media_create_pad_link(local, local_pad->index,
 					       remote, remote_pad->index,
-					       link_flags);
+					       link_flags, GFP_KERNEL);
 		if (ret < 0) {
 			dev_err(xdev->dev,
 				"failed to create %s:%u -> %s:%u link\n",
@@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
 
 		ret = media_create_pad_link(source, source_pad->index,
 					       sink, sink_pad->index,
-					       link_flags);
+					       link_flags, GFP_KERNEL);
 		if (ret < 0) {
 			dev_err(xdev->dev,
 				"failed to create %s:%u -> %s:%u link\n",
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 552ac58..de9ab11 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -251,7 +251,8 @@ create_link:
 		ret = media_create_pad_link(decoder,
 					    DEMOD_PAD_AUDIO_OUT,
 					    mixer, 0,
-					    MEDIA_LNK_FL_ENABLED);
+					    MEDIA_LNK_FL_ENABLED,
+					    GFP_KERNEL);
 		if (ret)
 			dev_err(&dev->usbdev->dev,
 				"Mixer Pad Link Create Error: %d\n", ret);
diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
index ac386bb..d9555dc 100644
--- a/drivers/media/usb/uvc/uvc_entity.c
+++ b/drivers/media/usb/uvc/uvc_entity.c
@@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
 
 		remote_pad = remote->num_pads - 1;
 		ret = media_create_pad_link(source, remote_pad,
-					       sink, i, flags);
+					       sink, i, flags, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index d8e5994..b0f53a2 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
 	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
 						  intf_type,
 						  0, VIDEO_MAJOR,
-						  vdev->minor);
+						  vdev->minor, GFP_KERNEL);
 	if (!vdev->intf_devnode) {
 		media_device_unregister_entity(&vdev->entity);
 		return -ENOMEM;
@@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
 
 		link = media_create_intf_link(&vdev->entity,
 					      &vdev->intf_devnode->intf,
-					      MEDIA_LNK_FL_ENABLED);
+					      MEDIA_LNK_FL_ENABLED,
+					      GFP_KERNEL);
 		if (!link) {
 			media_devnode_remove(vdev->intf_devnode);
 			media_device_unregister_entity(&vdev->entity);
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
index 06fa5f1..c7514e7 100644
--- a/drivers/media/v4l2-core/v4l2-device.c
+++ b/drivers/media/v4l2-core/v4l2-device.c
@@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
 
 			link = media_create_intf_link(&sd->entity,
 						      &vdev->intf_devnode->intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link) {
 				err = -ENOMEM;
 				goto clean_up;
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 40ee864..b1652f9 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 				continue;
 			ret = media_create_pad_link(entity, 0,
 						    io_v4l, 0,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 		}
@@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
 						    if_vid,
 						    IF_VID_DEC_PAD_IF_INPUT,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
 						decoder, DEMOD_PAD_IF_INPUT,
-						MEDIA_LNK_FL_ENABLED);
+						MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 		} else {
 			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
 						decoder, DEMOD_PAD_IF_INPUT,
-						MEDIA_LNK_FL_ENABLED);
+						MEDIA_LNK_FL_ENABLED,
+						GFP_KERNEL);
 			if (ret)
 				return ret;
 		}
@@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
 						    if_aud,
 						    IF_AUD_DEC_PAD_IF_INPUT,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 		} else {
@@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	if (io_v4l) {
 		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
 					io_v4l, 0,
-					MEDIA_LNK_FL_ENABLED);
+					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	if (io_swradio) {
 		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
 					io_swradio, 0,
-					MEDIA_LNK_FL_ENABLED);
+					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	if (io_vbi) {
 		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
 					    io_vbi, 0,
-					    MEDIA_LNK_FL_ENABLED);
+					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 
 			ret = media_create_pad_link(entity, 0, tuner,
 						    TUNER_PAD_RF_INPUT,
-						    flags);
+						    flags, GFP_KERNEL);
 			break;
 		case MEDIA_ENT_F_CONN_SVIDEO:
 		case MEDIA_ENT_F_CONN_COMPOSITE:
 			ret = media_create_pad_link(entity, 0, decoder,
 						    DEMOD_PAD_IF_INPUT,
-						    flags);
+						    flags, GFP_KERNEL);
 			break;
 		default:
 			continue;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
index 633d645..d1442b9 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
@@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
 
 	flags = 0;
 	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
-					&ipipeif->subdev.entity, 0, flags);
+					&ipipeif->subdev.entity, 0, flags,
+				    GFP_KERNEL);
 	if (ret < 0)
 		goto fail;
 
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
index 9905789..2470655 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
@@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
 	/* connect isif to video node */
 	ret = media_create_pad_link(&isif->subdev.entity, 1,
 				       &isif->video_out.video_dev.entity,
-				       0, flags);
+				       0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 	return 0;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
index a91395c..067f699 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
@@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
 	/* create link between Resizer Crop----> Resizer A*/
 	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
 				&resizer->resizer_a.subdev.entity,
-				0, flags);
+				0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
 	/* create link between Resizer Crop----> Resizer B*/
 	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
 				&resizer->resizer_b.subdev.entity,
-				0, flags);
+				0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
 	/* create link between Resizer A ----> video out */
 	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
-		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
+		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
+		GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
 	/* create link between Resizer B ----> video out */
 	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
-		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
+		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
+		GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
index ec46f36..bee9f5c 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
@@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
 		if (vpfe_dev->sd[i]->entity.num_pads) {
 			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
 				0, &vpfe_dev->vpfe_isif.subdev.entity,
-				0, flags);
+				0, flags, GFP_KERNEL);
 			if (ret < 0)
 				goto out_resizer_register;
 		}
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
 				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
-				       0, flags);
+				       0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
 				       &vpfe_dev->vpfe_ipipe.subdev.entity,
-				       0, flags);
+				       0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
 			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
-			0, flags);
+			0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
 			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
-			0, flags);
+			0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
index fb80d2b..933c8a7 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
 		}
 
 		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
-					       flags);
+					       flags, GFP_KERNEL);
 		if (ret < 0)
 			goto done;
 	}
@@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
 	/* Connect the submodules. */
 	ret = media_create_pad_link(
 			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
+			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
-			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
+			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
-			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
+			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
-			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
+			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
-			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
+			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index aaca39d..4b40132 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
 
 	/* Connect the CSI2a subdev to the video node. */
 	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
-				    &csi2a->video_out.video.entity, 0, 0);
+				    &csi2a->video_out.video.entity, 0, 0,
+				    GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	/* Connect the CSI2b subdev to the video node. */
 	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
-				    &csi2b->video_out.video.entity, 0, 0);
+				    &csi2b->video_out.video.entity, 0, 0,
+				    GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
index 23de833..2f124b0 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.c
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
@@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
 	/* Connect the IPIPEIF subdev to the video node. */
 	return media_create_pad_link(&ipipeif->subdev.entity,
 				     IPIPEIF_PAD_SOURCE_ISIF_SF,
-				     &ipipeif->video_out.video.entity, 0, 0);
+				     &ipipeif->video_out.video.entity, 0, 0,
+				     GFP_KERNEL);
 }
 
 /*
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
index f1d352c..8d5766a 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.c
+++ b/drivers/staging/media/omap4iss/iss_resizer.c
@@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
 	/* Connect the RESIZER subdev to the video node. */
 	return media_create_pad_link(&resizer->subdev.entity,
 				     RESIZER_PAD_SOURCE_MEM,
-				     &resizer->video_out.video.entity, 0, 0);
+				     &resizer->video_out.video.entity, 0, 0,
+				     GFP_KERNEL);
 }
 
 /*
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 6dc9e4e..0665c2d 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
  * @sink:	pointer to &media_entity of the sink pad.
  * @sink_pad:	number of the sink pad in the pads array.
  * @flags:	Link flags, as defined in include/uapi/linux/media.h.
+ * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
  *
  * Valid values for flags:
  * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
@@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
  */
 __must_check int media_create_pad_link(struct media_entity *source,
 			u16 source_pad, struct media_entity *sink,
-			u16 sink_pad, u32 flags);
+			u16 sink_pad, u32 flags, gfp_t gfpflags);
 
 /**
  * media_create_pad_links() - creates a link between two entities.
@@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
 struct media_intf_devnode *
 __must_check media_devnode_create(struct media_device *mdev,
 				  u32 type, u32 flags,
-				  u32 major, u32 minor);
+				  u32 major, u32 minor, gfp_t gfpflags);
 /**
  * media_devnode_remove() - removes a device node interface
  *
  * @devnode:	pointer to &media_intf_devnode to be freed.
+ * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
  *
  * When a device node interface is removed, all links to it are automatically
  * removed.
@@ -901,6 +903,7 @@ struct media_link *
  * @entity:	pointer to %media_entity
  * @intf:	pointer to %media_interface
  * @flags:	Link flags, as defined in include/uapi/linux/media.h.
+ * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
  *
  *
  * Valid values for flags:
@@ -921,7 +924,7 @@ struct media_link *
  */
 __must_check media_create_intf_link(struct media_entity *entity,
 				    struct media_interface *intf,
-				    u32 flags);
+				    u32 flags, gfp_t gfpflags);
 /**
  * __media_remove_intf_link() - remove a single interface link
  *
diff --git a/sound/usb/media.c b/sound/usb/media.c
index 93a50d01..f5ac038 100644
--- a/sound/usb/media.c
+++ b/sound/usb/media.c
@@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 
 	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
 						  MAJOR(pcm_dev->devt),
-						  MINOR(pcm_dev->devt));
+						  MINOR(pcm_dev->devt),
+						  GFP_KERNEL);
 	if (!mctl->intf_devnode) {
 		ret = -ENOMEM;
 		goto unregister_entity;
 	}
 	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
 						 &mctl->intf_devnode->intf,
-						 MEDIA_LNK_FL_ENABLED);
+						 MEDIA_LNK_FL_ENABLED,
+						 GFP_KERNEL);
 	if (!mctl->intf_link) {
 		ret = -ENOMEM;
 		goto devnode_remove;
@@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 		case MEDIA_ENT_F_AUDIO_MIXER:
 			ret = media_create_pad_link(entity, mixer_pad,
 						    &mctl->media_entity, 0,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				goto remove_intf_link;
 			break;
@@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
 	if (!ctl_intf) {
 		ctl_intf = media_devnode_create(mdev, intf_type, 0,
 						MAJOR(ctl_dev->devt),
-						MINOR(ctl_dev->devt));
+						MINOR(ctl_dev->devt),
+						GFP_KERNEL);
 		if (!ctl_intf)
 			return -ENOMEM;
 		chip->ctl_intf_media_devnode = ctl_intf;
@@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
 
 		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
 							 &ctl_intf->intf,
-							 MEDIA_LNK_FL_ENABLED);
+							 MEDIA_LNK_FL_ENABLED,
+							 GFP_KERNEL);
 		if (!mctl->intf_link) {
 			media_device_unregister_entity(&mctl->media_entity);
 			media_entity_cleanup(&mctl->media_entity);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-13  1:48 ` Shuah Khan
  0 siblings, 0 replies; 26+ messages in thread
From: Shuah Khan @ 2016-03-13  1:48 UTC (permalink / raw)
  To: linux-arm-kernel

Add GFP flags to media_create_pad_link(), media_create_intf_link(),
media_devnode_create(), and media_add_link() that could get called
in atomic context to allow callers to pass in the right flags for
memory allocation.

tree-wide driver changes for media_*() GFP flags change:
Change drivers to add gfpflags to interffaces, media_create_pad_link(),
media_create_intf_link() and media_devnode_create().

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
---
Ran through kbuild-all compile testing.
Tested the changes in Win-TV HVR-950Q device

 drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
 drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
 drivers/media/i2c/s5k5baf.c                        |  3 +-
 drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
 drivers/media/i2c/tvp5150.c                        |  3 +-
 drivers/media/media-entity.c                       | 30 ++++++++------
 drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
 drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
 drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
 drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
 drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
 drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
 drivers/media/usb/au0828/au0828-core.c             |  3 +-
 drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
 drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
 drivers/media/v4l2-core/v4l2-device.c              |  3 +-
 drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
 drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
 drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
 drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
 .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
 drivers/staging/media/omap4iss/iss.c               | 17 +++++---
 drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
 drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
 drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
 include/media/media-entity.h                       |  9 +++--
 sound/usb/media.c                                  | 15 ++++---
 27 files changed, 170 insertions(+), 106 deletions(-)

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index e1684c5..57f3e1e 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 
 	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
 						    intf_type, 0,
-						    DVB_MAJOR, minor);
+						    DVB_MAJOR, minor,
+						    GFP_KERNEL);
 
 	if (!dvbdev->intf_devnode)
 		return -ENOMEM;
@@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 		return 0;
 
 	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
-				      MEDIA_LNK_FL_ENABLED);
+				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 	if (!link)
 		return -ENOMEM;
 #endif
@@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
 			if (strncmp(entity->name, name, strlen(name)))
 				continue;
 			link = media_create_intf_link(entity, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
@@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 	}
 	if (demux && ca) {
 		ret = media_create_pad_link(demux, 1, ca,
-					    0, MEDIA_LNK_FL_ENABLED);
+					    0, MEDIA_LNK_FL_ENABLED,
+					    GFP_KERNEL);
 		if (ret)
 			return -ENOMEM;
 	}
@@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 				    strlen(DVR_TSOUT))) {
 					ret = media_create_pad_link(demux,
 								++dvr_pad,
-							    entity, 0, 0);
+							    entity, 0, 0,
+								GFP_KERNEL);
 					if (ret)
 						return ret;
 				}
@@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 				    strlen(DEMUX_TSOUT))) {
 					ret = media_create_pad_link(demux,
 							      ++demux_pad,
-							    entity, 0, 0);
+							    entity, 0, 0,
+								GFP_KERNEL);
 					if (ret)
 						return ret;
 				}
@@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 	media_device_for_each_intf(intf, mdev) {
 		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
 			link = media_create_intf_link(ca, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
 
 		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
 			link = media_create_intf_link(tuner, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
@@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 		 */
 		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
 			link = media_create_intf_link(demux, intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link)
 				return -ENOMEM;
 		}
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index 08af58f..dd994f1 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
 
 	ret = media_create_pad_link(&state->sensor_sd.entity,
 			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
-			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
+			GFP_KERNEL);
 
 	ret = media_create_pad_link(&state->sensor_sd.entity,
 			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
-			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
+			GFP_KERNEL);
 
 	return ret;
 }
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index db82ed0..3692bec 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
 		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
 					       &state->sd.entity, PAD_CIS,
 					       MEDIA_LNK_FL_IMMUTABLE |
-					       MEDIA_LNK_FL_ENABLED);
+					       MEDIA_LNK_FL_ENABLED,
+					       GFP_KERNEL);
 	return ret;
 }
 
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index a215efe..8c2e9ad 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
 					     &last->sd.entity,
 					     last->sink_pad,
 					     MEDIA_LNK_FL_ENABLED |
-					     MEDIA_LNK_FL_IMMUTABLE);
+					     MEDIA_LNK_FL_IMMUTABLE,
+					     GFP_KERNEL);
 		if (rval) {
 			dev_err(&client->dev,
 				"media_create_pad_link failed\n");
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index ff18444..fd99683 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
 			return ret;
 
 		ret = media_create_pad_link(input, 0, &sd->entity,
-					    DEMOD_PAD_IF_INPUT, 0);
+					    DEMOD_PAD_IF_INPUT, 0,
+					    GFP_KERNEL);
 		if (ret < 0) {
 			media_device_unregister_entity(input);
 			return ret;
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 66a5392..115435b 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
  * Links management
  */
 
-static struct media_link *media_add_link(struct list_head *head)
+static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
 {
 	struct media_link *link;
 
 	if (in_atomic())
 		dump_stack();
 
-	link = kzalloc(sizeof(*link), GFP_KERNEL);
+	link = kzalloc(sizeof(*link), gfpflags);
 	if (link == NULL)
 		return NULL;
 
@@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
 
 int
 media_create_pad_link(struct media_entity *source, u16 source_pad,
-			 struct media_entity *sink, u16 sink_pad, u32 flags)
+		      struct media_entity *sink, u16 sink_pad, u32 flags,
+		      gfp_t gfpflags)
 {
 	struct media_link *link;
 	struct media_link *backlink;
@@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	BUG_ON(source_pad >= source->num_pads);
 	BUG_ON(sink_pad >= sink->num_pads);
 
-	link = media_add_link(&source->links);
+	link = media_add_link(&source->links, gfpflags);
 	if (link == NULL)
 		return -ENOMEM;
 
@@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
 	/* Create the backlink. Backlinks are used to help graph traversal and
 	 * are not reported to userspace.
 	 */
-	backlink = media_add_link(&sink->links);
+	backlink = media_add_link(&sink->links, gfpflags);
 	if (backlink == NULL) {
 		__media_entity_remove_link(source, link);
 		return -ENOMEM;
@@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
 	/* Trivial case: 1:1 relation */
 	if (source && sink)
 		return media_create_pad_link(source, source_pad,
-					     sink, sink_pad, flags);
+					     sink, sink_pad, flags, GFP_KERNEL);
 
 	/* Worse case scenario: n:n relation */
 	if (!source && !sink) {
@@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
 					continue;
 				ret = media_create_pad_link(source, source_pad,
 							    sink, sink_pad,
-							    flags);
+							    flags, GFP_KERNEL);
 				if (ret)
 					return ret;
 				flags &= ~(MEDIA_LNK_FL_ENABLED |
@@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
 
 		if (source)
 			ret = media_create_pad_link(source, source_pad,
-						    entity, sink_pad, flags);
+						    entity, sink_pad, flags,
+						    GFP_KERNEL);
 		else
 			ret = media_create_pad_link(entity, source_pad,
-						    sink, sink_pad, flags);
+						    sink, sink_pad, flags,
+						    GFP_KERNEL);
 		if (ret)
 			return ret;
 		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
@@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
 
 struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
 						u32 type, u32 flags,
-						u32 major, u32 minor)
+						u32 major, u32 minor,
+						gfp_t gfpflags)
 {
 	struct media_intf_devnode *devnode;
 
 	if (in_atomic())
 		dump_stack();
 
-	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
+	devnode = kzalloc(sizeof(*devnode), gfpflags);
 	if (!devnode)
 		return NULL;
 
@@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
 
 struct media_link *media_create_intf_link(struct media_entity *entity,
 					    struct media_interface *intf,
-					    u32 flags)
+					    u32 flags, gfp_t gfpflags)
 {
 	struct media_link *link;
 
-	link = media_add_link(&intf->links);
+	link = media_add_link(&intf->links, gfpflags);
 	if (link == NULL)
 		return NULL;
 
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index feb521f..145d90e 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
 
 		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
 		ret = media_create_pad_link(source, pad, sink,
-					      FIMC_SD_PAD_SINK_CAM, flags);
+					      FIMC_SD_PAD_SINK_CAM, flags,
+					    GFP_KERNEL);
 		if (ret)
 			return ret;
 
@@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
 
 		sink = &fmd->fimc_lite[i]->subdev.entity;
 		ret = media_create_pad_link(source, pad, sink,
-					       FLITE_SD_PAD_SINK, 0);
+					       FLITE_SD_PAD_SINK, 0,
+					    GFP_KERNEL);
 		if (ret)
 			return ret;
 
@@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
 		sink = &fimc->ve.vdev.entity;
 		/* FIMC-LITE's subdev and video node */
 		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
-					       sink, 0, 0);
+					       sink, 0, 0, GFP_KERNEL);
 		if (ret)
 			break;
 		/* Link from FIMC-LITE to IS-ISP subdev */
 		sink = &fmd->fimc_is->isp.subdev.entity;
 		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
-					       sink, 0, 0);
+					       sink, 0, 0, GFP_KERNEL);
 		if (ret)
 			break;
 	}
@@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
 		/* Link from FIMC-IS-ISP subdev to FIMC */
 		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
 		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
-					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
+					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
+					    GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
 		return 0;
 
 	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
-					sink, 0, 0);
+					sink, 0, 0, GFP_KERNEL);
 }
 
 /**
@@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
 			ret = media_create_pad_link(&sensor->entity, pad,
 					      &csis->entity, CSIS_PAD_SINK,
 					      MEDIA_LNK_FL_IMMUTABLE |
-					      MEDIA_LNK_FL_ENABLED);
+					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 			if (ret)
 				return ret;
 
@@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
 		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
 
 		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
-					      sink, 0, flags);
+					      sink, 0, flags, GFP_KERNEL);
 		if (ret)
 			break;
 	}
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 5d54e2c..f8d9c84 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1669,7 +1669,7 @@ static int isp_link_entity(
 		return -EINVAL;
 	}
 
-	return media_create_pad_link(entity, i, input, pad, flags);
+	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
 }
 
 static int isp_register_entities(struct isp_device *isp)
@@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
 	/* Create links between entities and video nodes. */
 	ret = media_create_pad_link(
 			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&isp->isp_csi2a.video_out.video.entity, 0, 0);
+			&isp->isp_csi2a.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccp2.video_in.video.entity, 0,
-			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
+			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
-			&isp->isp_ccdc.video_out.video.entity, 0, 0);
+			&isp->isp_ccdc.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_prev.video_in.video.entity, 0,
-			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
-			&isp->isp_prev.video_out.video.entity, 0, 0);
+			&isp->isp_prev.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_res.video_in.video.entity, 0,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
-			&isp->isp_res.video_out.video.entity, 0, 0);
+			&isp->isp_res.video_out.video.entity, 0, 0,
+			GFP_KERNEL);
 
 	if (ret < 0)
 		return ret;
@@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
 	/* Create links between entities. */
 	ret = media_create_pad_link(
 			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
-			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
-			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
-			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
 			&isp->isp_aewb.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
 			&isp->isp_af.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
 			&isp->isp_hist.subdev.entity, 0,
-			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index 0b44b9a..a49b4c3 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
 	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
 				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
 				MEDIA_LNK_FL_IMMUTABLE |
-				MEDIA_LNK_FL_ENABLED);
+				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 	if (ret)
 		return ret;
 
@@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
 		ret = media_create_pad_link(&camif->subdev.entity, i,
 				&camif->vp[i - 1].vdev.entity, 0,
 				MEDIA_LNK_FL_IMMUTABLE |
-				MEDIA_LNK_FL_ENABLED);
+				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 	}
 
 	return ret;
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 021fe57..f868dec 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 		ret = media_create_pad_link(&rpf->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
 					    &vsp1->bru->entity.subdev.entity,
-					    i, flags);
+					    i, flags, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 
@@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
 				    vsp1->bru->entity.source_pad,
 				    &vsp1->wpf[0]->entity.subdev.entity,
-				    RWPF_PAD_SINK, flags);
+				    RWPF_PAD_SINK, flags, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
@@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
 				    RWPF_PAD_SOURCE,
 				    &vsp1->lif->entity.subdev.entity,
-				    LIF_PAD_SINK, flags);
+				    LIF_PAD_SINK, flags, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 25750a0..7295587 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
 
 			ret = media_create_pad_link(&source->subdev.entity,
 						       source->source_pad,
-						       entity, pad, flags);
+						       entity, pad, flags,
+						    GFP_KERNEL);
 			if (ret < 0)
 				return ret;
 
@@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
 					    &vsp1->lif->entity.subdev.entity,
-					    LIF_PAD_SINK, 0);
+					    LIF_PAD_SINK, 0, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
@@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 					    &rpf->entity.subdev.entity,
 					    RWPF_PAD_SINK,
 					    MEDIA_LNK_FL_ENABLED |
-					    MEDIA_LNK_FL_IMMUTABLE);
+					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
@@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 		ret = media_create_pad_link(&wpf->entity.subdev.entity,
 					    RWPF_PAD_SOURCE,
 					    &wpf->video->video.entity, 0,
-					    flags);
+					    flags, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index e795a45..b444db4 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
 
 		ret = media_create_pad_link(local, local_pad->index,
 					       remote, remote_pad->index,
-					       link_flags);
+					       link_flags, GFP_KERNEL);
 		if (ret < 0) {
 			dev_err(xdev->dev,
 				"failed to create %s:%u -> %s:%u link\n",
@@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
 
 		ret = media_create_pad_link(source, source_pad->index,
 					       sink, sink_pad->index,
-					       link_flags);
+					       link_flags, GFP_KERNEL);
 		if (ret < 0) {
 			dev_err(xdev->dev,
 				"failed to create %s:%u -> %s:%u link\n",
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 552ac58..de9ab11 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -251,7 +251,8 @@ create_link:
 		ret = media_create_pad_link(decoder,
 					    DEMOD_PAD_AUDIO_OUT,
 					    mixer, 0,
-					    MEDIA_LNK_FL_ENABLED);
+					    MEDIA_LNK_FL_ENABLED,
+					    GFP_KERNEL);
 		if (ret)
 			dev_err(&dev->usbdev->dev,
 				"Mixer Pad Link Create Error: %d\n", ret);
diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
index ac386bb..d9555dc 100644
--- a/drivers/media/usb/uvc/uvc_entity.c
+++ b/drivers/media/usb/uvc/uvc_entity.c
@@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
 
 		remote_pad = remote->num_pads - 1;
 		ret = media_create_pad_link(source, remote_pad,
-					       sink, i, flags);
+					       sink, i, flags, GFP_KERNEL);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index d8e5994..b0f53a2 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
 	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
 						  intf_type,
 						  0, VIDEO_MAJOR,
-						  vdev->minor);
+						  vdev->minor, GFP_KERNEL);
 	if (!vdev->intf_devnode) {
 		media_device_unregister_entity(&vdev->entity);
 		return -ENOMEM;
@@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
 
 		link = media_create_intf_link(&vdev->entity,
 					      &vdev->intf_devnode->intf,
-					      MEDIA_LNK_FL_ENABLED);
+					      MEDIA_LNK_FL_ENABLED,
+					      GFP_KERNEL);
 		if (!link) {
 			media_devnode_remove(vdev->intf_devnode);
 			media_device_unregister_entity(&vdev->entity);
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
index 06fa5f1..c7514e7 100644
--- a/drivers/media/v4l2-core/v4l2-device.c
+++ b/drivers/media/v4l2-core/v4l2-device.c
@@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
 
 			link = media_create_intf_link(&sd->entity,
 						      &vdev->intf_devnode->intf,
-						      MEDIA_LNK_FL_ENABLED);
+						      MEDIA_LNK_FL_ENABLED,
+						      GFP_KERNEL);
 			if (!link) {
 				err = -ENOMEM;
 				goto clean_up;
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 40ee864..b1652f9 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 				continue;
 			ret = media_create_pad_link(entity, 0,
 						    io_v4l, 0,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 		}
@@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
 						    if_vid,
 						    IF_VID_DEC_PAD_IF_INPUT,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
 						decoder, DEMOD_PAD_IF_INPUT,
-						MEDIA_LNK_FL_ENABLED);
+						MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 		} else {
 			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
 						decoder, DEMOD_PAD_IF_INPUT,
-						MEDIA_LNK_FL_ENABLED);
+						MEDIA_LNK_FL_ENABLED,
+						GFP_KERNEL);
 			if (ret)
 				return ret;
 		}
@@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
 						    if_aud,
 						    IF_AUD_DEC_PAD_IF_INPUT,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				return ret;
 		} else {
@@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	if (io_v4l) {
 		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
 					io_v4l, 0,
-					MEDIA_LNK_FL_ENABLED);
+					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	if (io_swradio) {
 		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
 					io_swradio, 0,
-					MEDIA_LNK_FL_ENABLED);
+					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	if (io_vbi) {
 		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
 					    io_vbi, 0,
-					    MEDIA_LNK_FL_ENABLED);
+					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
 		if (ret)
 			return ret;
 	}
@@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 
 			ret = media_create_pad_link(entity, 0, tuner,
 						    TUNER_PAD_RF_INPUT,
-						    flags);
+						    flags, GFP_KERNEL);
 			break;
 		case MEDIA_ENT_F_CONN_SVIDEO:
 		case MEDIA_ENT_F_CONN_COMPOSITE:
 			ret = media_create_pad_link(entity, 0, decoder,
 						    DEMOD_PAD_IF_INPUT,
-						    flags);
+						    flags, GFP_KERNEL);
 			break;
 		default:
 			continue;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
index 633d645..d1442b9 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
@@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
 
 	flags = 0;
 	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
-					&ipipeif->subdev.entity, 0, flags);
+					&ipipeif->subdev.entity, 0, flags,
+				    GFP_KERNEL);
 	if (ret < 0)
 		goto fail;
 
diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
index 9905789..2470655 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
@@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
 	/* connect isif to video node */
 	ret = media_create_pad_link(&isif->subdev.entity, 1,
 				       &isif->video_out.video_dev.entity,
-				       0, flags);
+				       0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 	return 0;
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
index a91395c..067f699 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
@@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
 	/* create link between Resizer Crop----> Resizer A*/
 	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
 				&resizer->resizer_a.subdev.entity,
-				0, flags);
+				0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
 	/* create link between Resizer Crop----> Resizer B*/
 	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
 				&resizer->resizer_b.subdev.entity,
-				0, flags);
+				0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
 	/* create link between Resizer A ----> video out */
 	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
-		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
+		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
+		GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
 	/* create link between Resizer B ----> video out */
 	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
-		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
+		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
+		GFP_KERNEL);
 	if (ret < 0)
 		goto out_create_link;
 
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
index ec46f36..bee9f5c 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
@@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
 		if (vpfe_dev->sd[i]->entity.num_pads) {
 			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
 				0, &vpfe_dev->vpfe_isif.subdev.entity,
-				0, flags);
+				0, flags, GFP_KERNEL);
 			if (ret < 0)
 				goto out_resizer_register;
 		}
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
 				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
-				       0, flags);
+				       0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
 				       &vpfe_dev->vpfe_ipipe.subdev.entity,
-				       0, flags);
+				       0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
 			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
-			0, flags);
+			0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
 	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
 			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
-			0, flags);
+			0, flags, GFP_KERNEL);
 	if (ret < 0)
 		goto out_resizer_register;
 
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
index fb80d2b..933c8a7 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
 		}
 
 		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
-					       flags);
+					       flags, GFP_KERNEL);
 		if (ret < 0)
 			goto done;
 	}
@@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
 	/* Connect the submodules. */
 	ret = media_create_pad_link(
 			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
-			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
+			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
-			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
+			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
-			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
+			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
-			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
+			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	ret = media_create_pad_link(
 			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
-			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
+			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
+			GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index aaca39d..4b40132 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
 
 	/* Connect the CSI2a subdev to the video node. */
 	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
-				    &csi2a->video_out.video.entity, 0, 0);
+				    &csi2a->video_out.video.entity, 0, 0,
+				    GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
 	/* Connect the CSI2b subdev to the video node. */
 	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
-				    &csi2b->video_out.video.entity, 0, 0);
+				    &csi2b->video_out.video.entity, 0, 0,
+				    GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
index 23de833..2f124b0 100644
--- a/drivers/staging/media/omap4iss/iss_ipipeif.c
+++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
@@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
 	/* Connect the IPIPEIF subdev to the video node. */
 	return media_create_pad_link(&ipipeif->subdev.entity,
 				     IPIPEIF_PAD_SOURCE_ISIF_SF,
-				     &ipipeif->video_out.video.entity, 0, 0);
+				     &ipipeif->video_out.video.entity, 0, 0,
+				     GFP_KERNEL);
 }
 
 /*
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
index f1d352c..8d5766a 100644
--- a/drivers/staging/media/omap4iss/iss_resizer.c
+++ b/drivers/staging/media/omap4iss/iss_resizer.c
@@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
 	/* Connect the RESIZER subdev to the video node. */
 	return media_create_pad_link(&resizer->subdev.entity,
 				     RESIZER_PAD_SOURCE_MEM,
-				     &resizer->video_out.video.entity, 0, 0);
+				     &resizer->video_out.video.entity, 0, 0,
+				     GFP_KERNEL);
 }
 
 /*
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 6dc9e4e..0665c2d 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
  * @sink:	pointer to &media_entity of the sink pad.
  * @sink_pad:	number of the sink pad in the pads array.
  * @flags:	Link flags, as defined in include/uapi/linux/media.h.
+ * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
  *
  * Valid values for flags:
  * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
@@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
  */
 __must_check int media_create_pad_link(struct media_entity *source,
 			u16 source_pad, struct media_entity *sink,
-			u16 sink_pad, u32 flags);
+			u16 sink_pad, u32 flags, gfp_t gfpflags);
 
 /**
  * media_create_pad_links() - creates a link between two entities.
@@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
 struct media_intf_devnode *
 __must_check media_devnode_create(struct media_device *mdev,
 				  u32 type, u32 flags,
-				  u32 major, u32 minor);
+				  u32 major, u32 minor, gfp_t gfpflags);
 /**
  * media_devnode_remove() - removes a device node interface
  *
  * @devnode:	pointer to &media_intf_devnode to be freed.
+ * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
  *
  * When a device node interface is removed, all links to it are automatically
  * removed.
@@ -901,6 +903,7 @@ struct media_link *
  * @entity:	pointer to %media_entity
  * @intf:	pointer to %media_interface
  * @flags:	Link flags, as defined in include/uapi/linux/media.h.
+ * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
  *
  *
  * Valid values for flags:
@@ -921,7 +924,7 @@ struct media_link *
  */
 __must_check media_create_intf_link(struct media_entity *entity,
 				    struct media_interface *intf,
-				    u32 flags);
+				    u32 flags, gfp_t gfpflags);
 /**
  * __media_remove_intf_link() - remove a single interface link
  *
diff --git a/sound/usb/media.c b/sound/usb/media.c
index 93a50d01..f5ac038 100644
--- a/sound/usb/media.c
+++ b/sound/usb/media.c
@@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 
 	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
 						  MAJOR(pcm_dev->devt),
-						  MINOR(pcm_dev->devt));
+						  MINOR(pcm_dev->devt),
+						  GFP_KERNEL);
 	if (!mctl->intf_devnode) {
 		ret = -ENOMEM;
 		goto unregister_entity;
 	}
 	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
 						 &mctl->intf_devnode->intf,
-						 MEDIA_LNK_FL_ENABLED);
+						 MEDIA_LNK_FL_ENABLED,
+						 GFP_KERNEL);
 	if (!mctl->intf_link) {
 		ret = -ENOMEM;
 		goto devnode_remove;
@@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
 		case MEDIA_ENT_F_AUDIO_MIXER:
 			ret = media_create_pad_link(entity, mixer_pad,
 						    &mctl->media_entity, 0,
-						    MEDIA_LNK_FL_ENABLED);
+						    MEDIA_LNK_FL_ENABLED,
+						    GFP_KERNEL);
 			if (ret)
 				goto remove_intf_link;
 			break;
@@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
 	if (!ctl_intf) {
 		ctl_intf = media_devnode_create(mdev, intf_type, 0,
 						MAJOR(ctl_dev->devt),
-						MINOR(ctl_dev->devt));
+						MINOR(ctl_dev->devt),
+						GFP_KERNEL);
 		if (!ctl_intf)
 			return -ENOMEM;
 		chip->ctl_intf_media_devnode = ctl_intf;
@@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
 
 		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
 							 &ctl_intf->intf,
-							 MEDIA_LNK_FL_ENABLED);
+							 MEDIA_LNK_FL_ENABLED,
+							 GFP_KERNEL);
 		if (!mctl->intf_link) {
 			media_device_unregister_entity(&mctl->media_entity);
 			media_entity_cleanup(&mctl->media_entity);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-13  1:48 ` Shuah Khan
  (?)
@ 2016-03-13  8:30   ` Nicholas Mc Guire
  -1 siblings, 0 replies; 26+ messages in thread
From: Nicholas Mc Guire @ 2016-03-13  8:30 UTC (permalink / raw)
  To: Shuah Khan
  Cc: mchehab, kyungmin.park, a.hajda, sakari.ailus, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, navyasri.tech,
	Julia.Lawall, amitoj1606, linux-media, linux-kernel,
	linux-arm-kernel, linux-samsung-soc, linux-renesas-soc, devel,
	alsa-devel

On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
>

in two cases (media_add_link,media_devnode_create) it is passing in 
gfpflags but then checking for in_atomic() and in case it is, dumping
stack - so does it make sense in those cases to allow GFP_ATOMIC to be
passed in ? could not figure out why that would be needed (current 
callers in media-entity.c do not seem to be under a spin_lock).

and in a few cases there seems to be a little glitch with indentation 
  dvb_create_media_graph
  __fimc_md_create_fimc_sink_links
  __fimc_md_create_fimc_is_links
  vsp1_create_sink_links
  v4l2_mc_create_media_graph
  vpfe_ipipeif_register_entities

thx!
hofrat
 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> ---
> Ran through kbuild-all compile testing.
> Tested the changes in Win-TV HVR-950Q device
> 
>  drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
>  drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
>  drivers/media/i2c/s5k5baf.c                        |  3 +-
>  drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
>  drivers/media/i2c/tvp5150.c                        |  3 +-
>  drivers/media/media-entity.c                       | 30 ++++++++------
>  drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
>  drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
>  drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
>  drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
>  drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
>  drivers/media/usb/au0828/au0828-core.c             |  3 +-
>  drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
>  drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
>  drivers/media/v4l2-core/v4l2-device.c              |  3 +-
>  drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
>  drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
>  drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
>  drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
>  .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
>  drivers/staging/media/omap4iss/iss.c               | 17 +++++---
>  drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
>  drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
>  drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
>  include/media/media-entity.h                       |  9 +++--
>  sound/usb/media.c                                  | 15 ++++---
>  27 files changed, 170 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
> index e1684c5..57f3e1e 100644
> --- a/drivers/media/dvb-core/dvbdev.c
> +++ b/drivers/media/dvb-core/dvbdev.c
> @@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  
>  	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
>  						    intf_type, 0,
> -						    DVB_MAJOR, minor);
> +						    DVB_MAJOR, minor,
> +						    GFP_KERNEL);
>  
>  	if (!dvbdev->intf_devnode)
>  		return -ENOMEM;
> @@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  		return 0;
>  
>  	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
> -				      MEDIA_LNK_FL_ENABLED);
> +				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (!link)
>  		return -ENOMEM;
>  #endif
> @@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
>  			if (strncmp(entity->name, name, strlen(name)))
>  				continue;
>  			link = media_create_intf_link(entity, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	}
>  	if (demux && ca) {
>  		ret = media_create_pad_link(demux, 1, ca,
> -					    0, MEDIA_LNK_FL_ENABLED);
> +					    0, MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return -ENOMEM;
>  	}
> @@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DVR_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  								++dvr_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DEMUX_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  							      ++demux_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	media_device_for_each_intf(intf, mdev) {
>  		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
>  			link = media_create_intf_link(ca, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
>  
>  		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
>  			link = media_create_intf_link(tuner, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  		 */
>  		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
>  			link = media_create_intf_link(demux, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 08af58f..dd994f1 100644
> --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	return ret;
>  }
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index db82ed0..3692bec 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
>  		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
>  					       &state->sd.entity, PAD_CIS,
>  					       MEDIA_LNK_FL_IMMUTABLE |
> -					       MEDIA_LNK_FL_ENABLED);
> +					       MEDIA_LNK_FL_ENABLED,
> +					       GFP_KERNEL);
>  	return ret;
>  }
>  
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index a215efe..8c2e9ad 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
>  					     &last->sd.entity,
>  					     last->sink_pad,
>  					     MEDIA_LNK_FL_ENABLED |
> -					     MEDIA_LNK_FL_IMMUTABLE);
> +					     MEDIA_LNK_FL_IMMUTABLE,
> +					     GFP_KERNEL);
>  		if (rval) {
>  			dev_err(&client->dev,
>  				"media_create_pad_link failed\n");
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index ff18444..fd99683 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
>  			return ret;
>  
>  		ret = media_create_pad_link(input, 0, &sd->entity,
> -					    DEMOD_PAD_IF_INPUT, 0);
> +					    DEMOD_PAD_IF_INPUT, 0,
> +					    GFP_KERNEL);
>  		if (ret < 0) {
>  			media_device_unregister_entity(input);
>  			return ret;
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 66a5392..115435b 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
>   * Links management
>   */
>  
> -static struct media_link *media_add_link(struct list_head *head)
> +static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	link = kzalloc(sizeof(*link), GFP_KERNEL);
> +	link = kzalloc(sizeof(*link), gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> @@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
>  
>  int
>  media_create_pad_link(struct media_entity *source, u16 source_pad,
> -			 struct media_entity *sink, u16 sink_pad, u32 flags)
> +		      struct media_entity *sink, u16 sink_pad, u32 flags,
> +		      gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  	struct media_link *backlink;
> @@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	BUG_ON(source_pad >= source->num_pads);
>  	BUG_ON(sink_pad >= sink->num_pads);
>  
> -	link = media_add_link(&source->links);
> +	link = media_add_link(&source->links, gfpflags);
>  	if (link == NULL)
>  		return -ENOMEM;
>  
> @@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	/* Create the backlink. Backlinks are used to help graph traversal and
>  	 * are not reported to userspace.
>  	 */
> -	backlink = media_add_link(&sink->links);
> +	backlink = media_add_link(&sink->links, gfpflags);
>  	if (backlink == NULL) {
>  		__media_entity_remove_link(source, link);
>  		return -ENOMEM;
> @@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  	/* Trivial case: 1:1 relation */
>  	if (source && sink)
>  		return media_create_pad_link(source, source_pad,
> -					     sink, sink_pad, flags);
> +					     sink, sink_pad, flags, GFP_KERNEL);
>  
>  	/* Worse case scenario: n:n relation */
>  	if (!source && !sink) {
> @@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  					continue;
>  				ret = media_create_pad_link(source, source_pad,
>  							    sink, sink_pad,
> -							    flags);
> +							    flags, GFP_KERNEL);
>  				if (ret)
>  					return ret;
>  				flags &= ~(MEDIA_LNK_FL_ENABLED |
> @@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
>  
>  		if (source)
>  			ret = media_create_pad_link(source, source_pad,
> -						    entity, sink_pad, flags);
> +						    entity, sink_pad, flags,
> +						    GFP_KERNEL);
>  		else
>  			ret = media_create_pad_link(entity, source_pad,
> -						    sink, sink_pad, flags);
> +						    sink, sink_pad, flags,
> +						    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> @@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
>  
>  struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
>  						u32 type, u32 flags,
> -						u32 major, u32 minor)
> +						u32 major, u32 minor,
> +						gfp_t gfpflags)
>  {
>  	struct media_intf_devnode *devnode;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
> +	devnode = kzalloc(sizeof(*devnode), gfpflags);
>  	if (!devnode)
>  		return NULL;
>  
> @@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
>  
>  struct media_link *media_create_intf_link(struct media_entity *entity,
>  					    struct media_interface *intf,
> -					    u32 flags)
> +					    u32 flags, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
> -	link = media_add_link(&intf->links);
> +	link = media_add_link(&intf->links, gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index feb521f..145d90e 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					      FIMC_SD_PAD_SINK_CAM, flags);
> +					      FIMC_SD_PAD_SINK_CAM, flags,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc_lite[i]->subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					       FLITE_SD_PAD_SINK, 0);
> +					       FLITE_SD_PAD_SINK, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
>  		sink = &fimc->ve.vdev.entity;
>  		/* FIMC-LITE's subdev and video node */
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  		/* Link from FIMC-LITE to IS-ISP subdev */
>  		sink = &fmd->fimc_is->isp.subdev.entity;
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> @@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		/* Link from FIMC-IS-ISP subdev to FIMC */
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
> -					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
> +					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		return 0;
>  
>  	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
> -					sink, 0, 0);
> +					sink, 0, 0, GFP_KERNEL);
>  }
>  
>  /**
> @@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  			ret = media_create_pad_link(&sensor->entity, pad,
>  					      &csis->entity, CSIS_PAD_SINK,
>  					      MEDIA_LNK_FL_IMMUTABLE |
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  
> @@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
>  
>  		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
> -					      sink, 0, flags);
> +					      sink, 0, flags, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
> index 5d54e2c..f8d9c84 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -1669,7 +1669,7 @@ static int isp_link_entity(
>  		return -EINVAL;
>  	}
>  
> -	return media_create_pad_link(entity, i, input, pad, flags);
> +	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
>  }
>  
>  static int isp_register_entities(struct isp_device *isp)
> @@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities and video nodes. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_csi2a.video_out.video.entity, 0, 0);
> +			&isp->isp_csi2a.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.video_in.video.entity, 0,
> -			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
> +			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_ccdc.video_out.video.entity, 0, 0);
> +			&isp->isp_ccdc.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.video_in.video.entity, 0,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_prev.video_out.video.entity, 0, 0);
> +			&isp->isp_prev.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.video_in.video.entity, 0,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
> -			&isp->isp_res.video_out.video.entity, 0, 0);
> +			&isp->isp_res.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  
>  	if (ret < 0)
>  		return ret;
> @@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_aewb.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_af.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_hist.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
> index 0b44b9a..a49b4c3 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.c
> +++ b/drivers/media/platform/s3c-camif/camif-core.c
> @@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
>  				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (ret)
>  		return ret;
>  
> @@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  		ret = media_create_pad_link(&camif->subdev.entity, i,
>  				&camif->vp[i - 1].vdev.entity, 0,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	}
>  
>  	return ret;
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 021fe57..f868dec 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&rpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->bru->entity.subdev.entity,
> -					    i, flags);
> +					    i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
>  				    vsp1->bru->entity.source_pad,
>  				    &vsp1->wpf[0]->entity.subdev.entity,
> -				    RWPF_PAD_SINK, flags);
> +				    RWPF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  				    RWPF_PAD_SOURCE,
>  				    &vsp1->lif->entity.subdev.entity,
> -				    LIF_PAD_SINK, flags);
> +				    LIF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 25750a0..7295587 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
>  
>  			ret = media_create_pad_link(&source->subdev.entity,
>  						       source->source_pad,
> -						       entity, pad, flags);
> +						       entity, pad, flags,
> +						    GFP_KERNEL);
>  			if (ret < 0)
>  				return ret;
>  
> @@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->lif->entity.subdev.entity,
> -					    LIF_PAD_SINK, 0);
> +					    LIF_PAD_SINK, 0, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  					    &rpf->entity.subdev.entity,
>  					    RWPF_PAD_SINK,
>  					    MEDIA_LNK_FL_ENABLED |
> -					    MEDIA_LNK_FL_IMMUTABLE);
> +					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&wpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &wpf->video->video.entity, 0,
> -					    flags);
> +					    flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index e795a45..b444db4 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
>  
>  		ret = media_create_pad_link(local, local_pad->index,
>  					       remote, remote_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> @@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
>  
>  		ret = media_create_pad_link(source, source_pad->index,
>  					       sink, sink_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 552ac58..de9ab11 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -251,7 +251,8 @@ create_link:
>  		ret = media_create_pad_link(decoder,
>  					    DEMOD_PAD_AUDIO_OUT,
>  					    mixer, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			dev_err(&dev->usbdev->dev,
>  				"Mixer Pad Link Create Error: %d\n", ret);
> diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
> index ac386bb..d9555dc 100644
> --- a/drivers/media/usb/uvc/uvc_entity.c
> +++ b/drivers/media/usb/uvc/uvc_entity.c
> @@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
>  
>  		remote_pad = remote->num_pads - 1;
>  		ret = media_create_pad_link(source, remote_pad,
> -					       sink, i, flags);
> +					       sink, i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index d8e5994..b0f53a2 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
>  						  intf_type,
>  						  0, VIDEO_MAJOR,
> -						  vdev->minor);
> +						  vdev->minor, GFP_KERNEL);
>  	if (!vdev->intf_devnode) {
>  		media_device_unregister_entity(&vdev->entity);
>  		return -ENOMEM;
> @@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  
>  		link = media_create_intf_link(&vdev->entity,
>  					      &vdev->intf_devnode->intf,
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED,
> +					      GFP_KERNEL);
>  		if (!link) {
>  			media_devnode_remove(vdev->intf_devnode);
>  			media_device_unregister_entity(&vdev->entity);
> diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
> index 06fa5f1..c7514e7 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
>  
>  			link = media_create_intf_link(&sd->entity,
>  						      &vdev->intf_devnode->intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link) {
>  				err = -ENOMEM;
>  				goto clean_up;
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> index 40ee864..b1652f9 100644
> --- a/drivers/media/v4l2-core/v4l2-mc.c
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  				continue;
>  			ret = media_create_pad_link(entity, 0,
>  						    io_v4l, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						    if_vid,
>  						    IF_VID_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
>  						    if_aud,
>  						    IF_AUD_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
> @@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_v4l) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_v4l, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_swradio) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_swradio, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_vbi) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
>  					    io_vbi, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  
>  			ret = media_create_pad_link(entity, 0, tuner,
>  						    TUNER_PAD_RF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		case MEDIA_ENT_F_CONN_SVIDEO:
>  		case MEDIA_ENT_F_CONN_COMPOSITE:
>  			ret = media_create_pad_link(entity, 0, decoder,
>  						    DEMOD_PAD_IF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		default:
>  			continue;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> index 633d645..d1442b9 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> @@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
>  
>  	flags = 0;
>  	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
> -					&ipipeif->subdev.entity, 0, flags);
> +					&ipipeif->subdev.entity, 0, flags,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		goto fail;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> index 9905789..2470655 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> @@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
>  	/* connect isif to video node */
>  	ret = media_create_pad_link(&isif->subdev.entity, 1,
>  				       &isif->video_out.video_dev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  	return 0;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> index a91395c..067f699 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> @@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
>  	/* create link between Resizer Crop----> Resizer A*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
>  				&resizer->resizer_a.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer Crop----> Resizer B*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
>  				&resizer->resizer_b.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer A ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
> -		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer B ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
> -		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> index ec46f36..bee9f5c 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> @@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
>  		if (vpfe_dev->sd[i]->entity.num_pads) {
>  			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
>  				0, &vpfe_dev->vpfe_isif.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  			if (ret < 0)
>  				goto out_resizer_register;
>  		}
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipe.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
>  			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
> diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
> index fb80d2b..933c8a7 100644
> --- a/drivers/staging/media/omap4iss/iss.c
> +++ b/drivers/staging/media/omap4iss/iss.c
> @@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
>  		}
>  
>  		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
> -					       flags);
> +					       flags, GFP_KERNEL);
>  		if (ret < 0)
>  			goto done;
>  	}
> @@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
>  	/* Connect the submodules. */
>  	ret = media_create_pad_link(
>  			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
> +			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
> index aaca39d..4b40132 100644
> --- a/drivers/staging/media/omap4iss/iss_csi2.c
> +++ b/drivers/staging/media/omap4iss/iss_csi2.c
> @@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
>  
>  	/* Connect the CSI2a subdev to the video node. */
>  	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2a->video_out.video.entity, 0, 0);
> +				    &csi2a->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Connect the CSI2b subdev to the video node. */
>  	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2b->video_out.video.entity, 0, 0);
> +				    &csi2b->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
> index 23de833..2f124b0 100644
> --- a/drivers/staging/media/omap4iss/iss_ipipeif.c
> +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
> @@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
>  	/* Connect the IPIPEIF subdev to the video node. */
>  	return media_create_pad_link(&ipipeif->subdev.entity,
>  				     IPIPEIF_PAD_SOURCE_ISIF_SF,
> -				     &ipipeif->video_out.video.entity, 0, 0);
> +				     &ipipeif->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
> index f1d352c..8d5766a 100644
> --- a/drivers/staging/media/omap4iss/iss_resizer.c
> +++ b/drivers/staging/media/omap4iss/iss_resizer.c
> @@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
>  	/* Connect the RESIZER subdev to the video node. */
>  	return media_create_pad_link(&resizer->subdev.entity,
>  				     RESIZER_PAD_SOURCE_MEM,
> -				     &resizer->video_out.video.entity, 0, 0);
> +				     &resizer->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index 6dc9e4e..0665c2d 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   * @sink:	pointer to &media_entity of the sink pad.
>   * @sink_pad:	number of the sink pad in the pads array.
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * Valid values for flags:
>   * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
> @@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   */
>  __must_check int media_create_pad_link(struct media_entity *source,
>  			u16 source_pad, struct media_entity *sink,
> -			u16 sink_pad, u32 flags);
> +			u16 sink_pad, u32 flags, gfp_t gfpflags);
>  
>  /**
>   * media_create_pad_links() - creates a link between two entities.
> @@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
>  struct media_intf_devnode *
>  __must_check media_devnode_create(struct media_device *mdev,
>  				  u32 type, u32 flags,
> -				  u32 major, u32 minor);
> +				  u32 major, u32 minor, gfp_t gfpflags);
>  /**
>   * media_devnode_remove() - removes a device node interface
>   *
>   * @devnode:	pointer to &media_intf_devnode to be freed.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * When a device node interface is removed, all links to it are automatically
>   * removed.
> @@ -901,6 +903,7 @@ struct media_link *
>   * @entity:	pointer to %media_entity
>   * @intf:	pointer to %media_interface
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   *
>   * Valid values for flags:
> @@ -921,7 +924,7 @@ struct media_link *
>   */
>  __must_check media_create_intf_link(struct media_entity *entity,
>  				    struct media_interface *intf,
> -				    u32 flags);
> +				    u32 flags, gfp_t gfpflags);
>  /**
>   * __media_remove_intf_link() - remove a single interface link
>   *
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 93a50d01..f5ac038 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  
>  	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
>  						  MAJOR(pcm_dev->devt),
> -						  MINOR(pcm_dev->devt));
> +						  MINOR(pcm_dev->devt),
> +						  GFP_KERNEL);
>  	if (!mctl->intf_devnode) {
>  		ret = -ENOMEM;
>  		goto unregister_entity;
>  	}
>  	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  						 &mctl->intf_devnode->intf,
> -						 MEDIA_LNK_FL_ENABLED);
> +						 MEDIA_LNK_FL_ENABLED,
> +						 GFP_KERNEL);
>  	if (!mctl->intf_link) {
>  		ret = -ENOMEM;
>  		goto devnode_remove;
> @@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  		case MEDIA_ENT_F_AUDIO_MIXER:
>  			ret = media_create_pad_link(entity, mixer_pad,
>  						    &mctl->media_entity, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				goto remove_intf_link;
>  			break;
> @@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  	if (!ctl_intf) {
>  		ctl_intf = media_devnode_create(mdev, intf_type, 0,
>  						MAJOR(ctl_dev->devt),
> -						MINOR(ctl_dev->devt));
> +						MINOR(ctl_dev->devt),
> +						GFP_KERNEL);
>  		if (!ctl_intf)
>  			return -ENOMEM;
>  		chip->ctl_intf_media_devnode = ctl_intf;
> @@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  
>  		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  							 &ctl_intf->intf,
> -							 MEDIA_LNK_FL_ENABLED);
> +							 MEDIA_LNK_FL_ENABLED,
> +							 GFP_KERNEL);
>  		if (!mctl->intf_link) {
>  			media_device_unregister_entity(&mctl->media_entity);
>  			media_entity_cleanup(&mctl->media_entity);
> -- 
> 2.5.0
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-13  8:30   ` Nicholas Mc Guire
  0 siblings, 0 replies; 26+ messages in thread
From: Nicholas Mc Guire @ 2016-03-13  8:30 UTC (permalink / raw)
  To: Shuah Khan
  Cc: hamohammed.sa, k.kozlowski, alsa-devel, perex, a.hajda,
	prabhakar.csengg, laurent.pinchart, s.nawrocki, devel, crope,
	lixiubo, linux-samsung-soc, tommi.franttila, chehabrafael,
	javier, amitoj1606, kgene, hans.verkuil, linux-arm-kernel,
	navyasri.tech, dan.carpenter, linux-media, mchehab, Julia.Lawall,
	soren.brinkmann, hyun.kwon, gregkh, tiwai, linux-kernel,
	linux-renesas-soc, kyungmin.park, sakari.ailus, g.liakhovetski

On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
>

in two cases (media_add_link,media_devnode_create) it is passing in 
gfpflags but then checking for in_atomic() and in case it is, dumping
stack - so does it make sense in those cases to allow GFP_ATOMIC to be
passed in ? could not figure out why that would be needed (current 
callers in media-entity.c do not seem to be under a spin_lock).

and in a few cases there seems to be a little glitch with indentation 
  dvb_create_media_graph
  __fimc_md_create_fimc_sink_links
  __fimc_md_create_fimc_is_links
  vsp1_create_sink_links
  v4l2_mc_create_media_graph
  vpfe_ipipeif_register_entities

thx!
hofrat
 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> ---
> Ran through kbuild-all compile testing.
> Tested the changes in Win-TV HVR-950Q device
> 
>  drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
>  drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
>  drivers/media/i2c/s5k5baf.c                        |  3 +-
>  drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
>  drivers/media/i2c/tvp5150.c                        |  3 +-
>  drivers/media/media-entity.c                       | 30 ++++++++------
>  drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
>  drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
>  drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
>  drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
>  drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
>  drivers/media/usb/au0828/au0828-core.c             |  3 +-
>  drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
>  drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
>  drivers/media/v4l2-core/v4l2-device.c              |  3 +-
>  drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
>  drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
>  drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
>  drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
>  .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
>  drivers/staging/media/omap4iss/iss.c               | 17 +++++---
>  drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
>  drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
>  drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
>  include/media/media-entity.h                       |  9 +++--
>  sound/usb/media.c                                  | 15 ++++---
>  27 files changed, 170 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
> index e1684c5..57f3e1e 100644
> --- a/drivers/media/dvb-core/dvbdev.c
> +++ b/drivers/media/dvb-core/dvbdev.c
> @@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  
>  	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
>  						    intf_type, 0,
> -						    DVB_MAJOR, minor);
> +						    DVB_MAJOR, minor,
> +						    GFP_KERNEL);
>  
>  	if (!dvbdev->intf_devnode)
>  		return -ENOMEM;
> @@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  		return 0;
>  
>  	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
> -				      MEDIA_LNK_FL_ENABLED);
> +				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (!link)
>  		return -ENOMEM;
>  #endif
> @@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
>  			if (strncmp(entity->name, name, strlen(name)))
>  				continue;
>  			link = media_create_intf_link(entity, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	}
>  	if (demux && ca) {
>  		ret = media_create_pad_link(demux, 1, ca,
> -					    0, MEDIA_LNK_FL_ENABLED);
> +					    0, MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return -ENOMEM;
>  	}
> @@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DVR_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  								++dvr_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DEMUX_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  							      ++demux_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	media_device_for_each_intf(intf, mdev) {
>  		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
>  			link = media_create_intf_link(ca, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
>  
>  		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
>  			link = media_create_intf_link(tuner, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  		 */
>  		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
>  			link = media_create_intf_link(demux, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 08af58f..dd994f1 100644
> --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	return ret;
>  }
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index db82ed0..3692bec 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
>  		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
>  					       &state->sd.entity, PAD_CIS,
>  					       MEDIA_LNK_FL_IMMUTABLE |
> -					       MEDIA_LNK_FL_ENABLED);
> +					       MEDIA_LNK_FL_ENABLED,
> +					       GFP_KERNEL);
>  	return ret;
>  }
>  
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index a215efe..8c2e9ad 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
>  					     &last->sd.entity,
>  					     last->sink_pad,
>  					     MEDIA_LNK_FL_ENABLED |
> -					     MEDIA_LNK_FL_IMMUTABLE);
> +					     MEDIA_LNK_FL_IMMUTABLE,
> +					     GFP_KERNEL);
>  		if (rval) {
>  			dev_err(&client->dev,
>  				"media_create_pad_link failed\n");
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index ff18444..fd99683 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
>  			return ret;
>  
>  		ret = media_create_pad_link(input, 0, &sd->entity,
> -					    DEMOD_PAD_IF_INPUT, 0);
> +					    DEMOD_PAD_IF_INPUT, 0,
> +					    GFP_KERNEL);
>  		if (ret < 0) {
>  			media_device_unregister_entity(input);
>  			return ret;
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 66a5392..115435b 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
>   * Links management
>   */
>  
> -static struct media_link *media_add_link(struct list_head *head)
> +static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	link = kzalloc(sizeof(*link), GFP_KERNEL);
> +	link = kzalloc(sizeof(*link), gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> @@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
>  
>  int
>  media_create_pad_link(struct media_entity *source, u16 source_pad,
> -			 struct media_entity *sink, u16 sink_pad, u32 flags)
> +		      struct media_entity *sink, u16 sink_pad, u32 flags,
> +		      gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  	struct media_link *backlink;
> @@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	BUG_ON(source_pad >= source->num_pads);
>  	BUG_ON(sink_pad >= sink->num_pads);
>  
> -	link = media_add_link(&source->links);
> +	link = media_add_link(&source->links, gfpflags);
>  	if (link == NULL)
>  		return -ENOMEM;
>  
> @@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	/* Create the backlink. Backlinks are used to help graph traversal and
>  	 * are not reported to userspace.
>  	 */
> -	backlink = media_add_link(&sink->links);
> +	backlink = media_add_link(&sink->links, gfpflags);
>  	if (backlink == NULL) {
>  		__media_entity_remove_link(source, link);
>  		return -ENOMEM;
> @@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  	/* Trivial case: 1:1 relation */
>  	if (source && sink)
>  		return media_create_pad_link(source, source_pad,
> -					     sink, sink_pad, flags);
> +					     sink, sink_pad, flags, GFP_KERNEL);
>  
>  	/* Worse case scenario: n:n relation */
>  	if (!source && !sink) {
> @@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  					continue;
>  				ret = media_create_pad_link(source, source_pad,
>  							    sink, sink_pad,
> -							    flags);
> +							    flags, GFP_KERNEL);
>  				if (ret)
>  					return ret;
>  				flags &= ~(MEDIA_LNK_FL_ENABLED |
> @@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
>  
>  		if (source)
>  			ret = media_create_pad_link(source, source_pad,
> -						    entity, sink_pad, flags);
> +						    entity, sink_pad, flags,
> +						    GFP_KERNEL);
>  		else
>  			ret = media_create_pad_link(entity, source_pad,
> -						    sink, sink_pad, flags);
> +						    sink, sink_pad, flags,
> +						    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> @@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
>  
>  struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
>  						u32 type, u32 flags,
> -						u32 major, u32 minor)
> +						u32 major, u32 minor,
> +						gfp_t gfpflags)
>  {
>  	struct media_intf_devnode *devnode;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
> +	devnode = kzalloc(sizeof(*devnode), gfpflags);
>  	if (!devnode)
>  		return NULL;
>  
> @@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
>  
>  struct media_link *media_create_intf_link(struct media_entity *entity,
>  					    struct media_interface *intf,
> -					    u32 flags)
> +					    u32 flags, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
> -	link = media_add_link(&intf->links);
> +	link = media_add_link(&intf->links, gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index feb521f..145d90e 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					      FIMC_SD_PAD_SINK_CAM, flags);
> +					      FIMC_SD_PAD_SINK_CAM, flags,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc_lite[i]->subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					       FLITE_SD_PAD_SINK, 0);
> +					       FLITE_SD_PAD_SINK, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
>  		sink = &fimc->ve.vdev.entity;
>  		/* FIMC-LITE's subdev and video node */
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  		/* Link from FIMC-LITE to IS-ISP subdev */
>  		sink = &fmd->fimc_is->isp.subdev.entity;
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> @@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		/* Link from FIMC-IS-ISP subdev to FIMC */
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
> -					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
> +					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		return 0;
>  
>  	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
> -					sink, 0, 0);
> +					sink, 0, 0, GFP_KERNEL);
>  }
>  
>  /**
> @@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  			ret = media_create_pad_link(&sensor->entity, pad,
>  					      &csis->entity, CSIS_PAD_SINK,
>  					      MEDIA_LNK_FL_IMMUTABLE |
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  
> @@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
>  
>  		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
> -					      sink, 0, flags);
> +					      sink, 0, flags, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
> index 5d54e2c..f8d9c84 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -1669,7 +1669,7 @@ static int isp_link_entity(
>  		return -EINVAL;
>  	}
>  
> -	return media_create_pad_link(entity, i, input, pad, flags);
> +	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
>  }
>  
>  static int isp_register_entities(struct isp_device *isp)
> @@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities and video nodes. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_csi2a.video_out.video.entity, 0, 0);
> +			&isp->isp_csi2a.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.video_in.video.entity, 0,
> -			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
> +			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_ccdc.video_out.video.entity, 0, 0);
> +			&isp->isp_ccdc.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.video_in.video.entity, 0,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_prev.video_out.video.entity, 0, 0);
> +			&isp->isp_prev.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.video_in.video.entity, 0,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
> -			&isp->isp_res.video_out.video.entity, 0, 0);
> +			&isp->isp_res.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  
>  	if (ret < 0)
>  		return ret;
> @@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_aewb.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_af.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_hist.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
> index 0b44b9a..a49b4c3 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.c
> +++ b/drivers/media/platform/s3c-camif/camif-core.c
> @@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
>  				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (ret)
>  		return ret;
>  
> @@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  		ret = media_create_pad_link(&camif->subdev.entity, i,
>  				&camif->vp[i - 1].vdev.entity, 0,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	}
>  
>  	return ret;
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 021fe57..f868dec 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&rpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->bru->entity.subdev.entity,
> -					    i, flags);
> +					    i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
>  				    vsp1->bru->entity.source_pad,
>  				    &vsp1->wpf[0]->entity.subdev.entity,
> -				    RWPF_PAD_SINK, flags);
> +				    RWPF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  				    RWPF_PAD_SOURCE,
>  				    &vsp1->lif->entity.subdev.entity,
> -				    LIF_PAD_SINK, flags);
> +				    LIF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 25750a0..7295587 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
>  
>  			ret = media_create_pad_link(&source->subdev.entity,
>  						       source->source_pad,
> -						       entity, pad, flags);
> +						       entity, pad, flags,
> +						    GFP_KERNEL);
>  			if (ret < 0)
>  				return ret;
>  
> @@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->lif->entity.subdev.entity,
> -					    LIF_PAD_SINK, 0);
> +					    LIF_PAD_SINK, 0, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  					    &rpf->entity.subdev.entity,
>  					    RWPF_PAD_SINK,
>  					    MEDIA_LNK_FL_ENABLED |
> -					    MEDIA_LNK_FL_IMMUTABLE);
> +					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&wpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &wpf->video->video.entity, 0,
> -					    flags);
> +					    flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index e795a45..b444db4 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
>  
>  		ret = media_create_pad_link(local, local_pad->index,
>  					       remote, remote_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> @@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
>  
>  		ret = media_create_pad_link(source, source_pad->index,
>  					       sink, sink_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 552ac58..de9ab11 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -251,7 +251,8 @@ create_link:
>  		ret = media_create_pad_link(decoder,
>  					    DEMOD_PAD_AUDIO_OUT,
>  					    mixer, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			dev_err(&dev->usbdev->dev,
>  				"Mixer Pad Link Create Error: %d\n", ret);
> diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
> index ac386bb..d9555dc 100644
> --- a/drivers/media/usb/uvc/uvc_entity.c
> +++ b/drivers/media/usb/uvc/uvc_entity.c
> @@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
>  
>  		remote_pad = remote->num_pads - 1;
>  		ret = media_create_pad_link(source, remote_pad,
> -					       sink, i, flags);
> +					       sink, i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index d8e5994..b0f53a2 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
>  						  intf_type,
>  						  0, VIDEO_MAJOR,
> -						  vdev->minor);
> +						  vdev->minor, GFP_KERNEL);
>  	if (!vdev->intf_devnode) {
>  		media_device_unregister_entity(&vdev->entity);
>  		return -ENOMEM;
> @@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  
>  		link = media_create_intf_link(&vdev->entity,
>  					      &vdev->intf_devnode->intf,
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED,
> +					      GFP_KERNEL);
>  		if (!link) {
>  			media_devnode_remove(vdev->intf_devnode);
>  			media_device_unregister_entity(&vdev->entity);
> diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
> index 06fa5f1..c7514e7 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
>  
>  			link = media_create_intf_link(&sd->entity,
>  						      &vdev->intf_devnode->intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link) {
>  				err = -ENOMEM;
>  				goto clean_up;
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> index 40ee864..b1652f9 100644
> --- a/drivers/media/v4l2-core/v4l2-mc.c
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  				continue;
>  			ret = media_create_pad_link(entity, 0,
>  						    io_v4l, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						    if_vid,
>  						    IF_VID_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
>  						    if_aud,
>  						    IF_AUD_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
> @@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_v4l) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_v4l, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_swradio) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_swradio, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_vbi) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
>  					    io_vbi, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  
>  			ret = media_create_pad_link(entity, 0, tuner,
>  						    TUNER_PAD_RF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		case MEDIA_ENT_F_CONN_SVIDEO:
>  		case MEDIA_ENT_F_CONN_COMPOSITE:
>  			ret = media_create_pad_link(entity, 0, decoder,
>  						    DEMOD_PAD_IF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		default:
>  			continue;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> index 633d645..d1442b9 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> @@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
>  
>  	flags = 0;
>  	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
> -					&ipipeif->subdev.entity, 0, flags);
> +					&ipipeif->subdev.entity, 0, flags,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		goto fail;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> index 9905789..2470655 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> @@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
>  	/* connect isif to video node */
>  	ret = media_create_pad_link(&isif->subdev.entity, 1,
>  				       &isif->video_out.video_dev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  	return 0;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> index a91395c..067f699 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> @@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
>  	/* create link between Resizer Crop----> Resizer A*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
>  				&resizer->resizer_a.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer Crop----> Resizer B*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
>  				&resizer->resizer_b.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer A ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
> -		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer B ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
> -		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> index ec46f36..bee9f5c 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> @@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
>  		if (vpfe_dev->sd[i]->entity.num_pads) {
>  			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
>  				0, &vpfe_dev->vpfe_isif.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  			if (ret < 0)
>  				goto out_resizer_register;
>  		}
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipe.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
>  			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
> diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
> index fb80d2b..933c8a7 100644
> --- a/drivers/staging/media/omap4iss/iss.c
> +++ b/drivers/staging/media/omap4iss/iss.c
> @@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
>  		}
>  
>  		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
> -					       flags);
> +					       flags, GFP_KERNEL);
>  		if (ret < 0)
>  			goto done;
>  	}
> @@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
>  	/* Connect the submodules. */
>  	ret = media_create_pad_link(
>  			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
> +			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
> index aaca39d..4b40132 100644
> --- a/drivers/staging/media/omap4iss/iss_csi2.c
> +++ b/drivers/staging/media/omap4iss/iss_csi2.c
> @@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
>  
>  	/* Connect the CSI2a subdev to the video node. */
>  	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2a->video_out.video.entity, 0, 0);
> +				    &csi2a->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Connect the CSI2b subdev to the video node. */
>  	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2b->video_out.video.entity, 0, 0);
> +				    &csi2b->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
> index 23de833..2f124b0 100644
> --- a/drivers/staging/media/omap4iss/iss_ipipeif.c
> +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
> @@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
>  	/* Connect the IPIPEIF subdev to the video node. */
>  	return media_create_pad_link(&ipipeif->subdev.entity,
>  				     IPIPEIF_PAD_SOURCE_ISIF_SF,
> -				     &ipipeif->video_out.video.entity, 0, 0);
> +				     &ipipeif->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
> index f1d352c..8d5766a 100644
> --- a/drivers/staging/media/omap4iss/iss_resizer.c
> +++ b/drivers/staging/media/omap4iss/iss_resizer.c
> @@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
>  	/* Connect the RESIZER subdev to the video node. */
>  	return media_create_pad_link(&resizer->subdev.entity,
>  				     RESIZER_PAD_SOURCE_MEM,
> -				     &resizer->video_out.video.entity, 0, 0);
> +				     &resizer->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index 6dc9e4e..0665c2d 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   * @sink:	pointer to &media_entity of the sink pad.
>   * @sink_pad:	number of the sink pad in the pads array.
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * Valid values for flags:
>   * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
> @@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   */
>  __must_check int media_create_pad_link(struct media_entity *source,
>  			u16 source_pad, struct media_entity *sink,
> -			u16 sink_pad, u32 flags);
> +			u16 sink_pad, u32 flags, gfp_t gfpflags);
>  
>  /**
>   * media_create_pad_links() - creates a link between two entities.
> @@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
>  struct media_intf_devnode *
>  __must_check media_devnode_create(struct media_device *mdev,
>  				  u32 type, u32 flags,
> -				  u32 major, u32 minor);
> +				  u32 major, u32 minor, gfp_t gfpflags);
>  /**
>   * media_devnode_remove() - removes a device node interface
>   *
>   * @devnode:	pointer to &media_intf_devnode to be freed.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * When a device node interface is removed, all links to it are automatically
>   * removed.
> @@ -901,6 +903,7 @@ struct media_link *
>   * @entity:	pointer to %media_entity
>   * @intf:	pointer to %media_interface
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   *
>   * Valid values for flags:
> @@ -921,7 +924,7 @@ struct media_link *
>   */
>  __must_check media_create_intf_link(struct media_entity *entity,
>  				    struct media_interface *intf,
> -				    u32 flags);
> +				    u32 flags, gfp_t gfpflags);
>  /**
>   * __media_remove_intf_link() - remove a single interface link
>   *
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 93a50d01..f5ac038 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  
>  	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
>  						  MAJOR(pcm_dev->devt),
> -						  MINOR(pcm_dev->devt));
> +						  MINOR(pcm_dev->devt),
> +						  GFP_KERNEL);
>  	if (!mctl->intf_devnode) {
>  		ret = -ENOMEM;
>  		goto unregister_entity;
>  	}
>  	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  						 &mctl->intf_devnode->intf,
> -						 MEDIA_LNK_FL_ENABLED);
> +						 MEDIA_LNK_FL_ENABLED,
> +						 GFP_KERNEL);
>  	if (!mctl->intf_link) {
>  		ret = -ENOMEM;
>  		goto devnode_remove;
> @@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  		case MEDIA_ENT_F_AUDIO_MIXER:
>  			ret = media_create_pad_link(entity, mixer_pad,
>  						    &mctl->media_entity, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				goto remove_intf_link;
>  			break;
> @@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  	if (!ctl_intf) {
>  		ctl_intf = media_devnode_create(mdev, intf_type, 0,
>  						MAJOR(ctl_dev->devt),
> -						MINOR(ctl_dev->devt));
> +						MINOR(ctl_dev->devt),
> +						GFP_KERNEL);
>  		if (!ctl_intf)
>  			return -ENOMEM;
>  		chip->ctl_intf_media_devnode = ctl_intf;
> @@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  
>  		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  							 &ctl_intf->intf,
> -							 MEDIA_LNK_FL_ENABLED);
> +							 MEDIA_LNK_FL_ENABLED,
> +							 GFP_KERNEL);
>  		if (!mctl->intf_link) {
>  			media_device_unregister_entity(&mctl->media_entity);
>  			media_entity_cleanup(&mctl->media_entity);
> -- 
> 2.5.0
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-13  8:30   ` Nicholas Mc Guire
  0 siblings, 0 replies; 26+ messages in thread
From: Nicholas Mc Guire @ 2016-03-13  8:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
>

in two cases (media_add_link,media_devnode_create) it is passing in 
gfpflags but then checking for in_atomic() and in case it is, dumping
stack - so does it make sense in those cases to allow GFP_ATOMIC to be
passed in ? could not figure out why that would be needed (current 
callers in media-entity.c do not seem to be under a spin_lock).

and in a few cases there seems to be a little glitch with indentation 
  dvb_create_media_graph
  __fimc_md_create_fimc_sink_links
  __fimc_md_create_fimc_is_links
  vsp1_create_sink_links
  v4l2_mc_create_media_graph
  vpfe_ipipeif_register_entities

thx!
hofrat
 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> ---
> Ran through kbuild-all compile testing.
> Tested the changes in Win-TV HVR-950Q device
> 
>  drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
>  drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
>  drivers/media/i2c/s5k5baf.c                        |  3 +-
>  drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
>  drivers/media/i2c/tvp5150.c                        |  3 +-
>  drivers/media/media-entity.c                       | 30 ++++++++------
>  drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
>  drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
>  drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
>  drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
>  drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
>  drivers/media/usb/au0828/au0828-core.c             |  3 +-
>  drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
>  drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
>  drivers/media/v4l2-core/v4l2-device.c              |  3 +-
>  drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
>  drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
>  drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
>  drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
>  .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
>  drivers/staging/media/omap4iss/iss.c               | 17 +++++---
>  drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
>  drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
>  drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
>  include/media/media-entity.h                       |  9 +++--
>  sound/usb/media.c                                  | 15 ++++---
>  27 files changed, 170 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
> index e1684c5..57f3e1e 100644
> --- a/drivers/media/dvb-core/dvbdev.c
> +++ b/drivers/media/dvb-core/dvbdev.c
> @@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  
>  	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
>  						    intf_type, 0,
> -						    DVB_MAJOR, minor);
> +						    DVB_MAJOR, minor,
> +						    GFP_KERNEL);
>  
>  	if (!dvbdev->intf_devnode)
>  		return -ENOMEM;
> @@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  		return 0;
>  
>  	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
> -				      MEDIA_LNK_FL_ENABLED);
> +				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (!link)
>  		return -ENOMEM;
>  #endif
> @@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
>  			if (strncmp(entity->name, name, strlen(name)))
>  				continue;
>  			link = media_create_intf_link(entity, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	}
>  	if (demux && ca) {
>  		ret = media_create_pad_link(demux, 1, ca,
> -					    0, MEDIA_LNK_FL_ENABLED);
> +					    0, MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return -ENOMEM;
>  	}
> @@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DVR_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  								++dvr_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DEMUX_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  							      ++demux_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	media_device_for_each_intf(intf, mdev) {
>  		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
>  			link = media_create_intf_link(ca, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
>  
>  		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
>  			link = media_create_intf_link(tuner, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  		 */
>  		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
>  			link = media_create_intf_link(demux, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 08af58f..dd994f1 100644
> --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	return ret;
>  }
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index db82ed0..3692bec 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
>  		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
>  					       &state->sd.entity, PAD_CIS,
>  					       MEDIA_LNK_FL_IMMUTABLE |
> -					       MEDIA_LNK_FL_ENABLED);
> +					       MEDIA_LNK_FL_ENABLED,
> +					       GFP_KERNEL);
>  	return ret;
>  }
>  
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index a215efe..8c2e9ad 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
>  					     &last->sd.entity,
>  					     last->sink_pad,
>  					     MEDIA_LNK_FL_ENABLED |
> -					     MEDIA_LNK_FL_IMMUTABLE);
> +					     MEDIA_LNK_FL_IMMUTABLE,
> +					     GFP_KERNEL);
>  		if (rval) {
>  			dev_err(&client->dev,
>  				"media_create_pad_link failed\n");
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index ff18444..fd99683 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
>  			return ret;
>  
>  		ret = media_create_pad_link(input, 0, &sd->entity,
> -					    DEMOD_PAD_IF_INPUT, 0);
> +					    DEMOD_PAD_IF_INPUT, 0,
> +					    GFP_KERNEL);
>  		if (ret < 0) {
>  			media_device_unregister_entity(input);
>  			return ret;
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 66a5392..115435b 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
>   * Links management
>   */
>  
> -static struct media_link *media_add_link(struct list_head *head)
> +static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	link = kzalloc(sizeof(*link), GFP_KERNEL);
> +	link = kzalloc(sizeof(*link), gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> @@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
>  
>  int
>  media_create_pad_link(struct media_entity *source, u16 source_pad,
> -			 struct media_entity *sink, u16 sink_pad, u32 flags)
> +		      struct media_entity *sink, u16 sink_pad, u32 flags,
> +		      gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  	struct media_link *backlink;
> @@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	BUG_ON(source_pad >= source->num_pads);
>  	BUG_ON(sink_pad >= sink->num_pads);
>  
> -	link = media_add_link(&source->links);
> +	link = media_add_link(&source->links, gfpflags);
>  	if (link == NULL)
>  		return -ENOMEM;
>  
> @@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	/* Create the backlink. Backlinks are used to help graph traversal and
>  	 * are not reported to userspace.
>  	 */
> -	backlink = media_add_link(&sink->links);
> +	backlink = media_add_link(&sink->links, gfpflags);
>  	if (backlink == NULL) {
>  		__media_entity_remove_link(source, link);
>  		return -ENOMEM;
> @@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  	/* Trivial case: 1:1 relation */
>  	if (source && sink)
>  		return media_create_pad_link(source, source_pad,
> -					     sink, sink_pad, flags);
> +					     sink, sink_pad, flags, GFP_KERNEL);
>  
>  	/* Worse case scenario: n:n relation */
>  	if (!source && !sink) {
> @@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  					continue;
>  				ret = media_create_pad_link(source, source_pad,
>  							    sink, sink_pad,
> -							    flags);
> +							    flags, GFP_KERNEL);
>  				if (ret)
>  					return ret;
>  				flags &= ~(MEDIA_LNK_FL_ENABLED |
> @@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
>  
>  		if (source)
>  			ret = media_create_pad_link(source, source_pad,
> -						    entity, sink_pad, flags);
> +						    entity, sink_pad, flags,
> +						    GFP_KERNEL);
>  		else
>  			ret = media_create_pad_link(entity, source_pad,
> -						    sink, sink_pad, flags);
> +						    sink, sink_pad, flags,
> +						    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> @@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
>  
>  struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
>  						u32 type, u32 flags,
> -						u32 major, u32 minor)
> +						u32 major, u32 minor,
> +						gfp_t gfpflags)
>  {
>  	struct media_intf_devnode *devnode;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
> +	devnode = kzalloc(sizeof(*devnode), gfpflags);
>  	if (!devnode)
>  		return NULL;
>  
> @@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
>  
>  struct media_link *media_create_intf_link(struct media_entity *entity,
>  					    struct media_interface *intf,
> -					    u32 flags)
> +					    u32 flags, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
> -	link = media_add_link(&intf->links);
> +	link = media_add_link(&intf->links, gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index feb521f..145d90e 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					      FIMC_SD_PAD_SINK_CAM, flags);
> +					      FIMC_SD_PAD_SINK_CAM, flags,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc_lite[i]->subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					       FLITE_SD_PAD_SINK, 0);
> +					       FLITE_SD_PAD_SINK, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
>  		sink = &fimc->ve.vdev.entity;
>  		/* FIMC-LITE's subdev and video node */
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  		/* Link from FIMC-LITE to IS-ISP subdev */
>  		sink = &fmd->fimc_is->isp.subdev.entity;
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> @@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		/* Link from FIMC-IS-ISP subdev to FIMC */
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
> -					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
> +					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		return 0;
>  
>  	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
> -					sink, 0, 0);
> +					sink, 0, 0, GFP_KERNEL);
>  }
>  
>  /**
> @@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  			ret = media_create_pad_link(&sensor->entity, pad,
>  					      &csis->entity, CSIS_PAD_SINK,
>  					      MEDIA_LNK_FL_IMMUTABLE |
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  
> @@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
>  
>  		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
> -					      sink, 0, flags);
> +					      sink, 0, flags, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
> index 5d54e2c..f8d9c84 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -1669,7 +1669,7 @@ static int isp_link_entity(
>  		return -EINVAL;
>  	}
>  
> -	return media_create_pad_link(entity, i, input, pad, flags);
> +	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
>  }
>  
>  static int isp_register_entities(struct isp_device *isp)
> @@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities and video nodes. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_csi2a.video_out.video.entity, 0, 0);
> +			&isp->isp_csi2a.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.video_in.video.entity, 0,
> -			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
> +			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_ccdc.video_out.video.entity, 0, 0);
> +			&isp->isp_ccdc.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.video_in.video.entity, 0,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_prev.video_out.video.entity, 0, 0);
> +			&isp->isp_prev.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.video_in.video.entity, 0,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
> -			&isp->isp_res.video_out.video.entity, 0, 0);
> +			&isp->isp_res.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  
>  	if (ret < 0)
>  		return ret;
> @@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_aewb.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_af.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_hist.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
> index 0b44b9a..a49b4c3 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.c
> +++ b/drivers/media/platform/s3c-camif/camif-core.c
> @@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
>  				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (ret)
>  		return ret;
>  
> @@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  		ret = media_create_pad_link(&camif->subdev.entity, i,
>  				&camif->vp[i - 1].vdev.entity, 0,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	}
>  
>  	return ret;
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 021fe57..f868dec 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&rpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->bru->entity.subdev.entity,
> -					    i, flags);
> +					    i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
>  				    vsp1->bru->entity.source_pad,
>  				    &vsp1->wpf[0]->entity.subdev.entity,
> -				    RWPF_PAD_SINK, flags);
> +				    RWPF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  				    RWPF_PAD_SOURCE,
>  				    &vsp1->lif->entity.subdev.entity,
> -				    LIF_PAD_SINK, flags);
> +				    LIF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 25750a0..7295587 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
>  
>  			ret = media_create_pad_link(&source->subdev.entity,
>  						       source->source_pad,
> -						       entity, pad, flags);
> +						       entity, pad, flags,
> +						    GFP_KERNEL);
>  			if (ret < 0)
>  				return ret;
>  
> @@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->lif->entity.subdev.entity,
> -					    LIF_PAD_SINK, 0);
> +					    LIF_PAD_SINK, 0, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  					    &rpf->entity.subdev.entity,
>  					    RWPF_PAD_SINK,
>  					    MEDIA_LNK_FL_ENABLED |
> -					    MEDIA_LNK_FL_IMMUTABLE);
> +					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&wpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &wpf->video->video.entity, 0,
> -					    flags);
> +					    flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index e795a45..b444db4 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
>  
>  		ret = media_create_pad_link(local, local_pad->index,
>  					       remote, remote_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> @@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
>  
>  		ret = media_create_pad_link(source, source_pad->index,
>  					       sink, sink_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 552ac58..de9ab11 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -251,7 +251,8 @@ create_link:
>  		ret = media_create_pad_link(decoder,
>  					    DEMOD_PAD_AUDIO_OUT,
>  					    mixer, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			dev_err(&dev->usbdev->dev,
>  				"Mixer Pad Link Create Error: %d\n", ret);
> diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
> index ac386bb..d9555dc 100644
> --- a/drivers/media/usb/uvc/uvc_entity.c
> +++ b/drivers/media/usb/uvc/uvc_entity.c
> @@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
>  
>  		remote_pad = remote->num_pads - 1;
>  		ret = media_create_pad_link(source, remote_pad,
> -					       sink, i, flags);
> +					       sink, i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index d8e5994..b0f53a2 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
>  						  intf_type,
>  						  0, VIDEO_MAJOR,
> -						  vdev->minor);
> +						  vdev->minor, GFP_KERNEL);
>  	if (!vdev->intf_devnode) {
>  		media_device_unregister_entity(&vdev->entity);
>  		return -ENOMEM;
> @@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  
>  		link = media_create_intf_link(&vdev->entity,
>  					      &vdev->intf_devnode->intf,
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED,
> +					      GFP_KERNEL);
>  		if (!link) {
>  			media_devnode_remove(vdev->intf_devnode);
>  			media_device_unregister_entity(&vdev->entity);
> diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
> index 06fa5f1..c7514e7 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
>  
>  			link = media_create_intf_link(&sd->entity,
>  						      &vdev->intf_devnode->intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link) {
>  				err = -ENOMEM;
>  				goto clean_up;
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> index 40ee864..b1652f9 100644
> --- a/drivers/media/v4l2-core/v4l2-mc.c
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  				continue;
>  			ret = media_create_pad_link(entity, 0,
>  						    io_v4l, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						    if_vid,
>  						    IF_VID_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
>  						    if_aud,
>  						    IF_AUD_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
> @@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_v4l) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_v4l, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_swradio) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_swradio, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_vbi) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
>  					    io_vbi, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  
>  			ret = media_create_pad_link(entity, 0, tuner,
>  						    TUNER_PAD_RF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		case MEDIA_ENT_F_CONN_SVIDEO:
>  		case MEDIA_ENT_F_CONN_COMPOSITE:
>  			ret = media_create_pad_link(entity, 0, decoder,
>  						    DEMOD_PAD_IF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		default:
>  			continue;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> index 633d645..d1442b9 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> @@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
>  
>  	flags = 0;
>  	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
> -					&ipipeif->subdev.entity, 0, flags);
> +					&ipipeif->subdev.entity, 0, flags,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		goto fail;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> index 9905789..2470655 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> @@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
>  	/* connect isif to video node */
>  	ret = media_create_pad_link(&isif->subdev.entity, 1,
>  				       &isif->video_out.video_dev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  	return 0;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> index a91395c..067f699 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> @@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
>  	/* create link between Resizer Crop----> Resizer A*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
>  				&resizer->resizer_a.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer Crop----> Resizer B*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
>  				&resizer->resizer_b.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer A ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
> -		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer B ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
> -		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> index ec46f36..bee9f5c 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> @@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
>  		if (vpfe_dev->sd[i]->entity.num_pads) {
>  			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
>  				0, &vpfe_dev->vpfe_isif.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  			if (ret < 0)
>  				goto out_resizer_register;
>  		}
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipe.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
>  			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
> diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
> index fb80d2b..933c8a7 100644
> --- a/drivers/staging/media/omap4iss/iss.c
> +++ b/drivers/staging/media/omap4iss/iss.c
> @@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
>  		}
>  
>  		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
> -					       flags);
> +					       flags, GFP_KERNEL);
>  		if (ret < 0)
>  			goto done;
>  	}
> @@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
>  	/* Connect the submodules. */
>  	ret = media_create_pad_link(
>  			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
> +			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
> index aaca39d..4b40132 100644
> --- a/drivers/staging/media/omap4iss/iss_csi2.c
> +++ b/drivers/staging/media/omap4iss/iss_csi2.c
> @@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
>  
>  	/* Connect the CSI2a subdev to the video node. */
>  	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2a->video_out.video.entity, 0, 0);
> +				    &csi2a->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Connect the CSI2b subdev to the video node. */
>  	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2b->video_out.video.entity, 0, 0);
> +				    &csi2b->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
> index 23de833..2f124b0 100644
> --- a/drivers/staging/media/omap4iss/iss_ipipeif.c
> +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
> @@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
>  	/* Connect the IPIPEIF subdev to the video node. */
>  	return media_create_pad_link(&ipipeif->subdev.entity,
>  				     IPIPEIF_PAD_SOURCE_ISIF_SF,
> -				     &ipipeif->video_out.video.entity, 0, 0);
> +				     &ipipeif->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
> index f1d352c..8d5766a 100644
> --- a/drivers/staging/media/omap4iss/iss_resizer.c
> +++ b/drivers/staging/media/omap4iss/iss_resizer.c
> @@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
>  	/* Connect the RESIZER subdev to the video node. */
>  	return media_create_pad_link(&resizer->subdev.entity,
>  				     RESIZER_PAD_SOURCE_MEM,
> -				     &resizer->video_out.video.entity, 0, 0);
> +				     &resizer->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index 6dc9e4e..0665c2d 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   * @sink:	pointer to &media_entity of the sink pad.
>   * @sink_pad:	number of the sink pad in the pads array.
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * Valid values for flags:
>   * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
> @@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   */
>  __must_check int media_create_pad_link(struct media_entity *source,
>  			u16 source_pad, struct media_entity *sink,
> -			u16 sink_pad, u32 flags);
> +			u16 sink_pad, u32 flags, gfp_t gfpflags);
>  
>  /**
>   * media_create_pad_links() - creates a link between two entities.
> @@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
>  struct media_intf_devnode *
>  __must_check media_devnode_create(struct media_device *mdev,
>  				  u32 type, u32 flags,
> -				  u32 major, u32 minor);
> +				  u32 major, u32 minor, gfp_t gfpflags);
>  /**
>   * media_devnode_remove() - removes a device node interface
>   *
>   * @devnode:	pointer to &media_intf_devnode to be freed.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * When a device node interface is removed, all links to it are automatically
>   * removed.
> @@ -901,6 +903,7 @@ struct media_link *
>   * @entity:	pointer to %media_entity
>   * @intf:	pointer to %media_interface
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   *
>   * Valid values for flags:
> @@ -921,7 +924,7 @@ struct media_link *
>   */
>  __must_check media_create_intf_link(struct media_entity *entity,
>  				    struct media_interface *intf,
> -				    u32 flags);
> +				    u32 flags, gfp_t gfpflags);
>  /**
>   * __media_remove_intf_link() - remove a single interface link
>   *
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 93a50d01..f5ac038 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  
>  	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
>  						  MAJOR(pcm_dev->devt),
> -						  MINOR(pcm_dev->devt));
> +						  MINOR(pcm_dev->devt),
> +						  GFP_KERNEL);
>  	if (!mctl->intf_devnode) {
>  		ret = -ENOMEM;
>  		goto unregister_entity;
>  	}
>  	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  						 &mctl->intf_devnode->intf,
> -						 MEDIA_LNK_FL_ENABLED);
> +						 MEDIA_LNK_FL_ENABLED,
> +						 GFP_KERNEL);
>  	if (!mctl->intf_link) {
>  		ret = -ENOMEM;
>  		goto devnode_remove;
> @@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  		case MEDIA_ENT_F_AUDIO_MIXER:
>  			ret = media_create_pad_link(entity, mixer_pad,
>  						    &mctl->media_entity, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				goto remove_intf_link;
>  			break;
> @@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  	if (!ctl_intf) {
>  		ctl_intf = media_devnode_create(mdev, intf_type, 0,
>  						MAJOR(ctl_dev->devt),
> -						MINOR(ctl_dev->devt));
> +						MINOR(ctl_dev->devt),
> +						GFP_KERNEL);
>  		if (!ctl_intf)
>  			return -ENOMEM;
>  		chip->ctl_intf_media_devnode = ctl_intf;
> @@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  
>  		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  							 &ctl_intf->intf,
> -							 MEDIA_LNK_FL_ENABLED);
> +							 MEDIA_LNK_FL_ENABLED,
> +							 GFP_KERNEL);
>  		if (!mctl->intf_link) {
>  			media_device_unregister_entity(&mctl->media_entity);
>  			media_entity_cleanup(&mctl->media_entity);
> -- 
> 2.5.0
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-13  1:48 ` Shuah Khan
@ 2016-03-13 11:50   ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-13 11:50 UTC (permalink / raw)
  To: Shuah Khan
  Cc: kyungmin.park, a.hajda, sakari.ailus, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Em Sat, 12 Mar 2016 18:48:09 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

Patches look OK to me[1], provided that a followup patch is
changes some of the callers to use GFP_ATOMIC.

I'll wait for such patch before merging this one.

Regards,
Mauro

[1] but see Nicholas comments about indentation.

> ---
> Ran through kbuild-all compile testing.
> Tested the changes in Win-TV HVR-950Q device
> 
>  drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
>  drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
>  drivers/media/i2c/s5k5baf.c                        |  3 +-
>  drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
>  drivers/media/i2c/tvp5150.c                        |  3 +-
>  drivers/media/media-entity.c                       | 30 ++++++++------
>  drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
>  drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
>  drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
>  drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
>  drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
>  drivers/media/usb/au0828/au0828-core.c             |  3 +-
>  drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
>  drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
>  drivers/media/v4l2-core/v4l2-device.c              |  3 +-
>  drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
>  drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
>  drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
>  drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
>  .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
>  drivers/staging/media/omap4iss/iss.c               | 17 +++++---
>  drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
>  drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
>  drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
>  include/media/media-entity.h                       |  9 +++--
>  sound/usb/media.c                                  | 15 ++++---
>  27 files changed, 170 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
> index e1684c5..57f3e1e 100644
> --- a/drivers/media/dvb-core/dvbdev.c
> +++ b/drivers/media/dvb-core/dvbdev.c
> @@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  
>  	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
>  						    intf_type, 0,
> -						    DVB_MAJOR, minor);
> +						    DVB_MAJOR, minor,
> +						    GFP_KERNEL);
>  
>  	if (!dvbdev->intf_devnode)
>  		return -ENOMEM;
> @@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  		return 0;
>  
>  	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
> -				      MEDIA_LNK_FL_ENABLED);
> +				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (!link)
>  		return -ENOMEM;
>  #endif
> @@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
>  			if (strncmp(entity->name, name, strlen(name)))
>  				continue;
>  			link = media_create_intf_link(entity, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	}
>  	if (demux && ca) {
>  		ret = media_create_pad_link(demux, 1, ca,
> -					    0, MEDIA_LNK_FL_ENABLED);
> +					    0, MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return -ENOMEM;
>  	}
> @@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DVR_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  								++dvr_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DEMUX_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  							      ++demux_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	media_device_for_each_intf(intf, mdev) {
>  		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
>  			link = media_create_intf_link(ca, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
>  
>  		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
>  			link = media_create_intf_link(tuner, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  		 */
>  		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
>  			link = media_create_intf_link(demux, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 08af58f..dd994f1 100644
> --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	return ret;
>  }
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index db82ed0..3692bec 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
>  		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
>  					       &state->sd.entity, PAD_CIS,
>  					       MEDIA_LNK_FL_IMMUTABLE |
> -					       MEDIA_LNK_FL_ENABLED);
> +					       MEDIA_LNK_FL_ENABLED,
> +					       GFP_KERNEL);
>  	return ret;
>  }
>  
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index a215efe..8c2e9ad 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
>  					     &last->sd.entity,
>  					     last->sink_pad,
>  					     MEDIA_LNK_FL_ENABLED |
> -					     MEDIA_LNK_FL_IMMUTABLE);
> +					     MEDIA_LNK_FL_IMMUTABLE,
> +					     GFP_KERNEL);
>  		if (rval) {
>  			dev_err(&client->dev,
>  				"media_create_pad_link failed\n");
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index ff18444..fd99683 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
>  			return ret;
>  
>  		ret = media_create_pad_link(input, 0, &sd->entity,
> -					    DEMOD_PAD_IF_INPUT, 0);
> +					    DEMOD_PAD_IF_INPUT, 0,
> +					    GFP_KERNEL);
>  		if (ret < 0) {
>  			media_device_unregister_entity(input);
>  			return ret;
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 66a5392..115435b 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
>   * Links management
>   */
>  
> -static struct media_link *media_add_link(struct list_head *head)
> +static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	link = kzalloc(sizeof(*link), GFP_KERNEL);
> +	link = kzalloc(sizeof(*link), gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> @@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
>  
>  int
>  media_create_pad_link(struct media_entity *source, u16 source_pad,
> -			 struct media_entity *sink, u16 sink_pad, u32 flags)
> +		      struct media_entity *sink, u16 sink_pad, u32 flags,
> +		      gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  	struct media_link *backlink;
> @@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	BUG_ON(source_pad >= source->num_pads);
>  	BUG_ON(sink_pad >= sink->num_pads);
>  
> -	link = media_add_link(&source->links);
> +	link = media_add_link(&source->links, gfpflags);
>  	if (link == NULL)
>  		return -ENOMEM;
>  
> @@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	/* Create the backlink. Backlinks are used to help graph traversal and
>  	 * are not reported to userspace.
>  	 */
> -	backlink = media_add_link(&sink->links);
> +	backlink = media_add_link(&sink->links, gfpflags);
>  	if (backlink == NULL) {
>  		__media_entity_remove_link(source, link);
>  		return -ENOMEM;
> @@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  	/* Trivial case: 1:1 relation */
>  	if (source && sink)
>  		return media_create_pad_link(source, source_pad,
> -					     sink, sink_pad, flags);
> +					     sink, sink_pad, flags, GFP_KERNEL);
>  
>  	/* Worse case scenario: n:n relation */
>  	if (!source && !sink) {
> @@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  					continue;
>  				ret = media_create_pad_link(source, source_pad,
>  							    sink, sink_pad,
> -							    flags);
> +							    flags, GFP_KERNEL);
>  				if (ret)
>  					return ret;
>  				flags &= ~(MEDIA_LNK_FL_ENABLED |
> @@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
>  
>  		if (source)
>  			ret = media_create_pad_link(source, source_pad,
> -						    entity, sink_pad, flags);
> +						    entity, sink_pad, flags,
> +						    GFP_KERNEL);
>  		else
>  			ret = media_create_pad_link(entity, source_pad,
> -						    sink, sink_pad, flags);
> +						    sink, sink_pad, flags,
> +						    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> @@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
>  
>  struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
>  						u32 type, u32 flags,
> -						u32 major, u32 minor)
> +						u32 major, u32 minor,
> +						gfp_t gfpflags)
>  {
>  	struct media_intf_devnode *devnode;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
> +	devnode = kzalloc(sizeof(*devnode), gfpflags);
>  	if (!devnode)
>  		return NULL;
>  
> @@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
>  
>  struct media_link *media_create_intf_link(struct media_entity *entity,
>  					    struct media_interface *intf,
> -					    u32 flags)
> +					    u32 flags, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
> -	link = media_add_link(&intf->links);
> +	link = media_add_link(&intf->links, gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index feb521f..145d90e 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					      FIMC_SD_PAD_SINK_CAM, flags);
> +					      FIMC_SD_PAD_SINK_CAM, flags,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc_lite[i]->subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					       FLITE_SD_PAD_SINK, 0);
> +					       FLITE_SD_PAD_SINK, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
>  		sink = &fimc->ve.vdev.entity;
>  		/* FIMC-LITE's subdev and video node */
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  		/* Link from FIMC-LITE to IS-ISP subdev */
>  		sink = &fmd->fimc_is->isp.subdev.entity;
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> @@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		/* Link from FIMC-IS-ISP subdev to FIMC */
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
> -					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
> +					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		return 0;
>  
>  	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
> -					sink, 0, 0);
> +					sink, 0, 0, GFP_KERNEL);
>  }
>  
>  /**
> @@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  			ret = media_create_pad_link(&sensor->entity, pad,
>  					      &csis->entity, CSIS_PAD_SINK,
>  					      MEDIA_LNK_FL_IMMUTABLE |
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  
> @@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
>  
>  		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
> -					      sink, 0, flags);
> +					      sink, 0, flags, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
> index 5d54e2c..f8d9c84 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -1669,7 +1669,7 @@ static int isp_link_entity(
>  		return -EINVAL;
>  	}
>  
> -	return media_create_pad_link(entity, i, input, pad, flags);
> +	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
>  }
>  
>  static int isp_register_entities(struct isp_device *isp)
> @@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities and video nodes. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_csi2a.video_out.video.entity, 0, 0);
> +			&isp->isp_csi2a.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.video_in.video.entity, 0,
> -			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
> +			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_ccdc.video_out.video.entity, 0, 0);
> +			&isp->isp_ccdc.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.video_in.video.entity, 0,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_prev.video_out.video.entity, 0, 0);
> +			&isp->isp_prev.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.video_in.video.entity, 0,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
> -			&isp->isp_res.video_out.video.entity, 0, 0);
> +			&isp->isp_res.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  
>  	if (ret < 0)
>  		return ret;
> @@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_aewb.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_af.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_hist.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
> index 0b44b9a..a49b4c3 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.c
> +++ b/drivers/media/platform/s3c-camif/camif-core.c
> @@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
>  				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (ret)
>  		return ret;
>  
> @@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  		ret = media_create_pad_link(&camif->subdev.entity, i,
>  				&camif->vp[i - 1].vdev.entity, 0,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	}
>  
>  	return ret;
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 021fe57..f868dec 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&rpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->bru->entity.subdev.entity,
> -					    i, flags);
> +					    i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
>  				    vsp1->bru->entity.source_pad,
>  				    &vsp1->wpf[0]->entity.subdev.entity,
> -				    RWPF_PAD_SINK, flags);
> +				    RWPF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  				    RWPF_PAD_SOURCE,
>  				    &vsp1->lif->entity.subdev.entity,
> -				    LIF_PAD_SINK, flags);
> +				    LIF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 25750a0..7295587 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
>  
>  			ret = media_create_pad_link(&source->subdev.entity,
>  						       source->source_pad,
> -						       entity, pad, flags);
> +						       entity, pad, flags,
> +						    GFP_KERNEL);
>  			if (ret < 0)
>  				return ret;
>  
> @@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->lif->entity.subdev.entity,
> -					    LIF_PAD_SINK, 0);
> +					    LIF_PAD_SINK, 0, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  					    &rpf->entity.subdev.entity,
>  					    RWPF_PAD_SINK,
>  					    MEDIA_LNK_FL_ENABLED |
> -					    MEDIA_LNK_FL_IMMUTABLE);
> +					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&wpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &wpf->video->video.entity, 0,
> -					    flags);
> +					    flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index e795a45..b444db4 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
>  
>  		ret = media_create_pad_link(local, local_pad->index,
>  					       remote, remote_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> @@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
>  
>  		ret = media_create_pad_link(source, source_pad->index,
>  					       sink, sink_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 552ac58..de9ab11 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -251,7 +251,8 @@ create_link:
>  		ret = media_create_pad_link(decoder,
>  					    DEMOD_PAD_AUDIO_OUT,
>  					    mixer, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			dev_err(&dev->usbdev->dev,
>  				"Mixer Pad Link Create Error: %d\n", ret);
> diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
> index ac386bb..d9555dc 100644
> --- a/drivers/media/usb/uvc/uvc_entity.c
> +++ b/drivers/media/usb/uvc/uvc_entity.c
> @@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
>  
>  		remote_pad = remote->num_pads - 1;
>  		ret = media_create_pad_link(source, remote_pad,
> -					       sink, i, flags);
> +					       sink, i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index d8e5994..b0f53a2 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
>  						  intf_type,
>  						  0, VIDEO_MAJOR,
> -						  vdev->minor);
> +						  vdev->minor, GFP_KERNEL);
>  	if (!vdev->intf_devnode) {
>  		media_device_unregister_entity(&vdev->entity);
>  		return -ENOMEM;
> @@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  
>  		link = media_create_intf_link(&vdev->entity,
>  					      &vdev->intf_devnode->intf,
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED,
> +					      GFP_KERNEL);
>  		if (!link) {
>  			media_devnode_remove(vdev->intf_devnode);
>  			media_device_unregister_entity(&vdev->entity);
> diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
> index 06fa5f1..c7514e7 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
>  
>  			link = media_create_intf_link(&sd->entity,
>  						      &vdev->intf_devnode->intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link) {
>  				err = -ENOMEM;
>  				goto clean_up;
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> index 40ee864..b1652f9 100644
> --- a/drivers/media/v4l2-core/v4l2-mc.c
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  				continue;
>  			ret = media_create_pad_link(entity, 0,
>  						    io_v4l, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						    if_vid,
>  						    IF_VID_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
>  						    if_aud,
>  						    IF_AUD_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
> @@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_v4l) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_v4l, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_swradio) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_swradio, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_vbi) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
>  					    io_vbi, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  
>  			ret = media_create_pad_link(entity, 0, tuner,
>  						    TUNER_PAD_RF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		case MEDIA_ENT_F_CONN_SVIDEO:
>  		case MEDIA_ENT_F_CONN_COMPOSITE:
>  			ret = media_create_pad_link(entity, 0, decoder,
>  						    DEMOD_PAD_IF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		default:
>  			continue;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> index 633d645..d1442b9 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> @@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
>  
>  	flags = 0;
>  	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
> -					&ipipeif->subdev.entity, 0, flags);
> +					&ipipeif->subdev.entity, 0, flags,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		goto fail;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> index 9905789..2470655 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> @@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
>  	/* connect isif to video node */
>  	ret = media_create_pad_link(&isif->subdev.entity, 1,
>  				       &isif->video_out.video_dev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  	return 0;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> index a91395c..067f699 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> @@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
>  	/* create link between Resizer Crop----> Resizer A*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
>  				&resizer->resizer_a.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer Crop----> Resizer B*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
>  				&resizer->resizer_b.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer A ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
> -		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer B ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
> -		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> index ec46f36..bee9f5c 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> @@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
>  		if (vpfe_dev->sd[i]->entity.num_pads) {
>  			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
>  				0, &vpfe_dev->vpfe_isif.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  			if (ret < 0)
>  				goto out_resizer_register;
>  		}
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipe.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
>  			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
> diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
> index fb80d2b..933c8a7 100644
> --- a/drivers/staging/media/omap4iss/iss.c
> +++ b/drivers/staging/media/omap4iss/iss.c
> @@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
>  		}
>  
>  		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
> -					       flags);
> +					       flags, GFP_KERNEL);
>  		if (ret < 0)
>  			goto done;
>  	}
> @@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
>  	/* Connect the submodules. */
>  	ret = media_create_pad_link(
>  			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
> +			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
> index aaca39d..4b40132 100644
> --- a/drivers/staging/media/omap4iss/iss_csi2.c
> +++ b/drivers/staging/media/omap4iss/iss_csi2.c
> @@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
>  
>  	/* Connect the CSI2a subdev to the video node. */
>  	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2a->video_out.video.entity, 0, 0);
> +				    &csi2a->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Connect the CSI2b subdev to the video node. */
>  	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2b->video_out.video.entity, 0, 0);
> +				    &csi2b->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
> index 23de833..2f124b0 100644
> --- a/drivers/staging/media/omap4iss/iss_ipipeif.c
> +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
> @@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
>  	/* Connect the IPIPEIF subdev to the video node. */
>  	return media_create_pad_link(&ipipeif->subdev.entity,
>  				     IPIPEIF_PAD_SOURCE_ISIF_SF,
> -				     &ipipeif->video_out.video.entity, 0, 0);
> +				     &ipipeif->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
> index f1d352c..8d5766a 100644
> --- a/drivers/staging/media/omap4iss/iss_resizer.c
> +++ b/drivers/staging/media/omap4iss/iss_resizer.c
> @@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
>  	/* Connect the RESIZER subdev to the video node. */
>  	return media_create_pad_link(&resizer->subdev.entity,
>  				     RESIZER_PAD_SOURCE_MEM,
> -				     &resizer->video_out.video.entity, 0, 0);
> +				     &resizer->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index 6dc9e4e..0665c2d 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   * @sink:	pointer to &media_entity of the sink pad.
>   * @sink_pad:	number of the sink pad in the pads array.
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * Valid values for flags:
>   * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
> @@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   */
>  __must_check int media_create_pad_link(struct media_entity *source,
>  			u16 source_pad, struct media_entity *sink,
> -			u16 sink_pad, u32 flags);
> +			u16 sink_pad, u32 flags, gfp_t gfpflags);
>  
>  /**
>   * media_create_pad_links() - creates a link between two entities.
> @@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
>  struct media_intf_devnode *
>  __must_check media_devnode_create(struct media_device *mdev,
>  				  u32 type, u32 flags,
> -				  u32 major, u32 minor);
> +				  u32 major, u32 minor, gfp_t gfpflags);
>  /**
>   * media_devnode_remove() - removes a device node interface
>   *
>   * @devnode:	pointer to &media_intf_devnode to be freed.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * When a device node interface is removed, all links to it are automatically
>   * removed.
> @@ -901,6 +903,7 @@ struct media_link *
>   * @entity:	pointer to %media_entity
>   * @intf:	pointer to %media_interface
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   *
>   * Valid values for flags:
> @@ -921,7 +924,7 @@ struct media_link *
>   */
>  __must_check media_create_intf_link(struct media_entity *entity,
>  				    struct media_interface *intf,
> -				    u32 flags);
> +				    u32 flags, gfp_t gfpflags);
>  /**
>   * __media_remove_intf_link() - remove a single interface link
>   *
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 93a50d01..f5ac038 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  
>  	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
>  						  MAJOR(pcm_dev->devt),
> -						  MINOR(pcm_dev->devt));
> +						  MINOR(pcm_dev->devt),
> +						  GFP_KERNEL);
>  	if (!mctl->intf_devnode) {
>  		ret = -ENOMEM;
>  		goto unregister_entity;
>  	}
>  	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  						 &mctl->intf_devnode->intf,
> -						 MEDIA_LNK_FL_ENABLED);
> +						 MEDIA_LNK_FL_ENABLED,
> +						 GFP_KERNEL);
>  	if (!mctl->intf_link) {
>  		ret = -ENOMEM;
>  		goto devnode_remove;
> @@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  		case MEDIA_ENT_F_AUDIO_MIXER:
>  			ret = media_create_pad_link(entity, mixer_pad,
>  						    &mctl->media_entity, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				goto remove_intf_link;
>  			break;
> @@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  	if (!ctl_intf) {
>  		ctl_intf = media_devnode_create(mdev, intf_type, 0,
>  						MAJOR(ctl_dev->devt),
> -						MINOR(ctl_dev->devt));
> +						MINOR(ctl_dev->devt),
> +						GFP_KERNEL);
>  		if (!ctl_intf)
>  			return -ENOMEM;
>  		chip->ctl_intf_media_devnode = ctl_intf;
> @@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  
>  		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  							 &ctl_intf->intf,
> -							 MEDIA_LNK_FL_ENABLED);
> +							 MEDIA_LNK_FL_ENABLED,
> +							 GFP_KERNEL);
>  		if (!mctl->intf_link) {
>  			media_device_unregister_entity(&mctl->media_entity);
>  			media_entity_cleanup(&mctl->media_entity);


-- 
Thanks,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-13 11:50   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-13 11:50 UTC (permalink / raw)
  To: linux-arm-kernel

Em Sat, 12 Mar 2016 18:48:09 -0700
Shuah Khan <shuahkh@osg.samsung.com> escreveu:

> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

Patches look OK to me[1], provided that a followup patch is
changes some of the callers to use GFP_ATOMIC.

I'll wait for such patch before merging this one.

Regards,
Mauro

[1] but see Nicholas comments about indentation.

> ---
> Ran through kbuild-all compile testing.
> Tested the changes in Win-TV HVR-950Q device
> 
>  drivers/media/dvb-core/dvbdev.c                    | 26 +++++++-----
>  drivers/media/i2c/s5c73m3/s5c73m3-core.c           |  6 ++-
>  drivers/media/i2c/s5k5baf.c                        |  3 +-
>  drivers/media/i2c/smiapp/smiapp-core.c             |  3 +-
>  drivers/media/i2c/tvp5150.c                        |  3 +-
>  drivers/media/media-entity.c                       | 30 ++++++++------
>  drivers/media/platform/exynos4-is/media-dev.c      | 19 +++++----
>  drivers/media/platform/omap3isp/isp.c              | 47 ++++++++++++++--------
>  drivers/media/platform/s3c-camif/camif-core.c      |  4 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             |  6 +--
>  drivers/media/platform/vsp1/vsp1_drv.c             |  9 +++--
>  drivers/media/platform/xilinx/xilinx-vipp.c        |  4 +-
>  drivers/media/usb/au0828/au0828-core.c             |  3 +-
>  drivers/media/usb/uvc/uvc_entity.c                 |  2 +-
>  drivers/media/v4l2-core/v4l2-dev.c                 |  5 ++-
>  drivers/media/v4l2-core/v4l2-device.c              |  3 +-
>  drivers/media/v4l2-core/v4l2-mc.c                  | 25 +++++++-----
>  drivers/staging/media/davinci_vpfe/dm365_ipipeif.c |  3 +-
>  drivers/staging/media/davinci_vpfe/dm365_isif.c    |  2 +-
>  drivers/staging/media/davinci_vpfe/dm365_resizer.c | 10 +++--
>  .../staging/media/davinci_vpfe/vpfe_mc_capture.c   | 10 ++---
>  drivers/staging/media/omap4iss/iss.c               | 17 +++++---
>  drivers/staging/media/omap4iss/iss_csi2.c          |  6 ++-
>  drivers/staging/media/omap4iss/iss_ipipeif.c       |  3 +-
>  drivers/staging/media/omap4iss/iss_resizer.c       |  3 +-
>  include/media/media-entity.h                       |  9 +++--
>  sound/usb/media.c                                  | 15 ++++---
>  27 files changed, 170 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
> index e1684c5..57f3e1e 100644
> --- a/drivers/media/dvb-core/dvbdev.c
> +++ b/drivers/media/dvb-core/dvbdev.c
> @@ -399,7 +399,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  
>  	dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev,
>  						    intf_type, 0,
> -						    DVB_MAJOR, minor);
> +						    DVB_MAJOR, minor,
> +						    GFP_KERNEL);
>  
>  	if (!dvbdev->intf_devnode)
>  		return -ENOMEM;
> @@ -416,7 +417,7 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
>  		return 0;
>  
>  	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
> -				      MEDIA_LNK_FL_ENABLED);
> +				      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (!link)
>  		return -ENOMEM;
>  #endif
> @@ -558,7 +559,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
>  			if (strncmp(entity->name, name, strlen(name)))
>  				continue;
>  			link = media_create_intf_link(entity, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -680,7 +682,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	}
>  	if (demux && ca) {
>  		ret = media_create_pad_link(demux, 1, ca,
> -					    0, MEDIA_LNK_FL_ENABLED);
> +					    0, MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return -ENOMEM;
>  	}
> @@ -693,7 +696,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DVR_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  								++dvr_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -701,7 +705,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  				    strlen(DEMUX_TSOUT))) {
>  					ret = media_create_pad_link(demux,
>  							      ++demux_pad,
> -							    entity, 0, 0);
> +							    entity, 0, 0,
> +								GFP_KERNEL);
>  					if (ret)
>  						return ret;
>  				}
> @@ -713,14 +718,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  	media_device_for_each_intf(intf, mdev) {
>  		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
>  			link = media_create_intf_link(ca, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
>  
>  		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
>  			link = media_create_intf_link(tuner, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> @@ -732,7 +739,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
>  		 */
>  		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
>  			link = media_create_intf_link(demux, intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link)
>  				return -ENOMEM;
>  		}
> diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> index 08af58f..dd994f1 100644
> --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
> @@ -1484,11 +1484,13 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_ISP_PAD, &state->oif_sd.entity, OIF_ISP_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	ret = media_create_pad_link(&state->sensor_sd.entity,
>  			S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
> -			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
> +			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
> +			GFP_KERNEL);
>  
>  	return ret;
>  }
> diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
> index db82ed0..3692bec 100644
> --- a/drivers/media/i2c/s5k5baf.c
> +++ b/drivers/media/i2c/s5k5baf.c
> @@ -1759,7 +1759,8 @@ static int s5k5baf_registered(struct v4l2_subdev *sd)
>  		ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS,
>  					       &state->sd.entity, PAD_CIS,
>  					       MEDIA_LNK_FL_IMMUTABLE |
> -					       MEDIA_LNK_FL_ENABLED);
> +					       MEDIA_LNK_FL_ENABLED,
> +					       GFP_KERNEL);
>  	return ret;
>  }
>  
> diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
> index a215efe..8c2e9ad 100644
> --- a/drivers/media/i2c/smiapp/smiapp-core.c
> +++ b/drivers/media/i2c/smiapp/smiapp-core.c
> @@ -2508,7 +2508,8 @@ static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
>  					     &last->sd.entity,
>  					     last->sink_pad,
>  					     MEDIA_LNK_FL_ENABLED |
> -					     MEDIA_LNK_FL_IMMUTABLE);
> +					     MEDIA_LNK_FL_IMMUTABLE,
> +					     GFP_KERNEL);
>  		if (rval) {
>  			dev_err(&client->dev,
>  				"media_create_pad_link failed\n");
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index ff18444..fd99683 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -1197,7 +1197,8 @@ static int tvp5150_registered_async(struct v4l2_subdev *sd)
>  			return ret;
>  
>  		ret = media_create_pad_link(input, 0, &sd->entity,
> -					    DEMOD_PAD_IF_INPUT, 0);
> +					    DEMOD_PAD_IF_INPUT, 0,
> +					    GFP_KERNEL);
>  		if (ret < 0) {
>  			media_device_unregister_entity(input);
>  			return ret;
> diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
> index 66a5392..115435b 100644
> --- a/drivers/media/media-entity.c
> +++ b/drivers/media/media-entity.c
> @@ -566,14 +566,14 @@ EXPORT_SYMBOL_GPL(media_entity_put);
>   * Links management
>   */
>  
> -static struct media_link *media_add_link(struct list_head *head)
> +static struct media_link *media_add_link(struct list_head *head, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	link = kzalloc(sizeof(*link), GFP_KERNEL);
> +	link = kzalloc(sizeof(*link), gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> @@ -615,7 +615,8 @@ static void __media_entity_remove_link(struct media_entity *entity,
>  
>  int
>  media_create_pad_link(struct media_entity *source, u16 source_pad,
> -			 struct media_entity *sink, u16 sink_pad, u32 flags)
> +		      struct media_entity *sink, u16 sink_pad, u32 flags,
> +		      gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  	struct media_link *backlink;
> @@ -624,7 +625,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	BUG_ON(source_pad >= source->num_pads);
>  	BUG_ON(sink_pad >= sink->num_pads);
>  
> -	link = media_add_link(&source->links);
> +	link = media_add_link(&source->links, gfpflags);
>  	if (link == NULL)
>  		return -ENOMEM;
>  
> @@ -639,7 +640,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
>  	/* Create the backlink. Backlinks are used to help graph traversal and
>  	 * are not reported to userspace.
>  	 */
> -	backlink = media_add_link(&sink->links);
> +	backlink = media_add_link(&sink->links, gfpflags);
>  	if (backlink == NULL) {
>  		__media_entity_remove_link(source, link);
>  		return -ENOMEM;
> @@ -682,7 +683,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  	/* Trivial case: 1:1 relation */
>  	if (source && sink)
>  		return media_create_pad_link(source, source_pad,
> -					     sink, sink_pad, flags);
> +					     sink, sink_pad, flags, GFP_KERNEL);
>  
>  	/* Worse case scenario: n:n relation */
>  	if (!source && !sink) {
> @@ -696,7 +697,7 @@ int media_create_pad_links(const struct media_device *mdev,
>  					continue;
>  				ret = media_create_pad_link(source, source_pad,
>  							    sink, sink_pad,
> -							    flags);
> +							    flags, GFP_KERNEL);
>  				if (ret)
>  					return ret;
>  				flags &= ~(MEDIA_LNK_FL_ENABLED |
> @@ -718,10 +719,12 @@ int media_create_pad_links(const struct media_device *mdev,
>  
>  		if (source)
>  			ret = media_create_pad_link(source, source_pad,
> -						    entity, sink_pad, flags);
> +						    entity, sink_pad, flags,
> +						    GFP_KERNEL);
>  		else
>  			ret = media_create_pad_link(entity, source_pad,
> -						    sink, sink_pad, flags);
> +						    sink, sink_pad, flags,
> +						    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  		flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> @@ -890,14 +893,15 @@ static void media_interface_init(struct media_device *mdev,
>  
>  struct media_intf_devnode *media_devnode_create(struct media_device *mdev,
>  						u32 type, u32 flags,
> -						u32 major, u32 minor)
> +						u32 major, u32 minor,
> +						gfp_t gfpflags)
>  {
>  	struct media_intf_devnode *devnode;
>  
>  	if (in_atomic())
>  		dump_stack();
>  
> -	devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
> +	devnode = kzalloc(sizeof(*devnode), gfpflags);
>  	if (!devnode)
>  		return NULL;
>  
> @@ -921,11 +925,11 @@ EXPORT_SYMBOL_GPL(media_devnode_remove);
>  
>  struct media_link *media_create_intf_link(struct media_entity *entity,
>  					    struct media_interface *intf,
> -					    u32 flags)
> +					    u32 flags, gfp_t gfpflags)
>  {
>  	struct media_link *link;
>  
> -	link = media_add_link(&intf->links);
> +	link = media_add_link(&intf->links, gfpflags);
>  	if (link == NULL)
>  		return NULL;
>  
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index feb521f..145d90e 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -798,7 +798,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					      FIMC_SD_PAD_SINK_CAM, flags);
> +					      FIMC_SD_PAD_SINK_CAM, flags,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -818,7 +819,8 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  
>  		sink = &fmd->fimc_lite[i]->subdev.entity;
>  		ret = media_create_pad_link(source, pad, sink,
> -					       FLITE_SD_PAD_SINK, 0);
> +					       FLITE_SD_PAD_SINK, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  
> @@ -850,13 +852,13 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
>  		sink = &fimc->ve.vdev.entity;
>  		/* FIMC-LITE's subdev and video node */
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_DMA,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  		/* Link from FIMC-LITE to IS-ISP subdev */
>  		sink = &fmd->fimc_is->isp.subdev.entity;
>  		ret = media_create_pad_link(source, FLITE_SD_PAD_SOURCE_ISP,
> -					       sink, 0, 0);
> +					       sink, 0, 0, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> @@ -880,7 +882,8 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		/* Link from FIMC-IS-ISP subdev to FIMC */
>  		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
>  		ret = media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
> -					       sink, FIMC_SD_PAD_SINK_FIFO, 0);
> +					       sink, FIMC_SD_PAD_SINK_FIFO, 0,
> +					    GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -893,7 +896,7 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
>  		return 0;
>  
>  	return media_create_pad_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
> -					sink, 0, 0);
> +					sink, 0, 0, GFP_KERNEL);
>  }
>  
>  /**
> @@ -944,7 +947,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  			ret = media_create_pad_link(&sensor->entity, pad,
>  					      &csis->entity, CSIS_PAD_SINK,
>  					      MEDIA_LNK_FL_IMMUTABLE |
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  
> @@ -996,7 +999,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  		sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity;
>  
>  		ret = media_create_pad_link(source, FIMC_SD_PAD_SOURCE,
> -					      sink, 0, flags);
> +					      sink, 0, flags, GFP_KERNEL);
>  		if (ret)
>  			break;
>  	}
> diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
> index 5d54e2c..f8d9c84 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -1669,7 +1669,7 @@ static int isp_link_entity(
>  		return -EINVAL;
>  	}
>  
> -	return media_create_pad_link(entity, i, input, pad, flags);
> +	return media_create_pad_link(entity, i, input, pad, flags, GFP_KERNEL);
>  }
>  
>  static int isp_register_entities(struct isp_device *isp)
> @@ -1748,43 +1748,50 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities and video nodes. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_csi2a.video_out.video.entity, 0, 0);
> +			&isp->isp_csi2a.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.video_in.video.entity, 0,
> -			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0);
> +			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_ccdc.video_out.video.entity, 0, 0);
> +			&isp->isp_ccdc.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.video_in.video.entity, 0,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_prev.video_out.video.entity, 0, 0);
> +			&isp->isp_prev.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.video_in.video.entity, 0,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_res.subdev.entity, RESZ_PAD_SOURCE,
> -			&isp->isp_res.video_out.video.entity, 0, 0);
> +			&isp->isp_res.video_out.video.entity, 0, 0,
> +			GFP_KERNEL);
>  
>  	if (ret < 0)
>  		return ret;
> @@ -1792,52 +1799,60 @@ static int isp_create_links(struct isp_device *isp)
>  	/* Create links between entities. */
>  	ret = media_create_pad_link(
>  			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
> -			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
> +			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
> -			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
> +			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
> -			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
> +			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_aewb.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_af.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
>  			&isp->isp_hist.subdev.entity, 0,
> -			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
> +			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
> index 0b44b9a..a49b4c3 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.c
> +++ b/drivers/media/platform/s3c-camif/camif-core.c
> @@ -266,7 +266,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  	ret = media_create_pad_link(&camif->sensor.sd->entity, 0,
>  				&camif->subdev.entity, CAMIF_SD_PAD_SINK,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	if (ret)
>  		return ret;
>  
> @@ -274,7 +274,7 @@ static int camif_create_media_links(struct camif_dev *camif)
>  		ret = media_create_pad_link(&camif->subdev.entity, i,
>  				&camif->vp[i - 1].vdev.entity, 0,
>  				MEDIA_LNK_FL_IMMUTABLE |
> -				MEDIA_LNK_FL_ENABLED);
> +				MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  	}
>  
>  	return ret;
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 021fe57..f868dec 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -525,7 +525,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&rpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->bru->entity.subdev.entity,
> -					    i, flags);
> +					    i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -536,7 +536,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->bru->entity.subdev.entity,
>  				    vsp1->bru->entity.source_pad,
>  				    &vsp1->wpf[0]->entity.subdev.entity,
> -				    RWPF_PAD_SINK, flags);
> +				    RWPF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -546,7 +546,7 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  				    RWPF_PAD_SOURCE,
>  				    &vsp1->lif->entity.subdev.entity,
> -				    LIF_PAD_SINK, flags);
> +				    LIF_PAD_SINK, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 25750a0..7295587 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -125,7 +125,8 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
>  
>  			ret = media_create_pad_link(&source->subdev.entity,
>  						       source->source_pad,
> -						       entity, pad, flags);
> +						       entity, pad, flags,
> +						    GFP_KERNEL);
>  			if (ret < 0)
>  				return ret;
>  
> @@ -157,7 +158,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &vsp1->lif->entity.subdev.entity,
> -					    LIF_PAD_SINK, 0);
> +					    LIF_PAD_SINK, 0, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -169,7 +170,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  					    &rpf->entity.subdev.entity,
>  					    RWPF_PAD_SINK,
>  					    MEDIA_LNK_FL_ENABLED |
> -					    MEDIA_LNK_FL_IMMUTABLE);
> +					    MEDIA_LNK_FL_IMMUTABLE, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -188,7 +189,7 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
>  		ret = media_create_pad_link(&wpf->entity.subdev.entity,
>  					    RWPF_PAD_SOURCE,
>  					    &wpf->video->video.entity, 0,
> -					    flags);
> +					    flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index e795a45..b444db4 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -158,7 +158,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev,
>  
>  		ret = media_create_pad_link(local, local_pad->index,
>  					       remote, remote_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> @@ -272,7 +272,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
>  
>  		ret = media_create_pad_link(source, source_pad->index,
>  					       sink, sink_pad->index,
> -					       link_flags);
> +					       link_flags, GFP_KERNEL);
>  		if (ret < 0) {
>  			dev_err(xdev->dev,
>  				"failed to create %s:%u -> %s:%u link\n",
> diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
> index 552ac58..de9ab11 100644
> --- a/drivers/media/usb/au0828/au0828-core.c
> +++ b/drivers/media/usb/au0828/au0828-core.c
> @@ -251,7 +251,8 @@ create_link:
>  		ret = media_create_pad_link(decoder,
>  					    DEMOD_PAD_AUDIO_OUT,
>  					    mixer, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED,
> +					    GFP_KERNEL);
>  		if (ret)
>  			dev_err(&dev->usbdev->dev,
>  				"Mixer Pad Link Create Error: %d\n", ret);
> diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
> index ac386bb..d9555dc 100644
> --- a/drivers/media/usb/uvc/uvc_entity.c
> +++ b/drivers/media/usb/uvc/uvc_entity.c
> @@ -53,7 +53,7 @@ static int uvc_mc_create_links(struct uvc_video_chain *chain,
>  
>  		remote_pad = remote->num_pads - 1;
>  		ret = media_create_pad_link(source, remote_pad,
> -					       sink, i, flags);
> +					       sink, i, flags, GFP_KERNEL);
>  		if (ret < 0)
>  			return ret;
>  	}
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index d8e5994..b0f53a2 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -786,7 +786,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
>  						  intf_type,
>  						  0, VIDEO_MAJOR,
> -						  vdev->minor);
> +						  vdev->minor, GFP_KERNEL);
>  	if (!vdev->intf_devnode) {
>  		media_device_unregister_entity(&vdev->entity);
>  		return -ENOMEM;
> @@ -797,7 +797,8 @@ static int video_register_media_controller(struct video_device *vdev, int type)
>  
>  		link = media_create_intf_link(&vdev->entity,
>  					      &vdev->intf_devnode->intf,
> -					      MEDIA_LNK_FL_ENABLED);
> +					      MEDIA_LNK_FL_ENABLED,
> +					      GFP_KERNEL);
>  		if (!link) {
>  			media_devnode_remove(vdev->intf_devnode);
>  			media_device_unregister_entity(&vdev->entity);
> diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c
> index 06fa5f1..c7514e7 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -266,7 +266,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
>  
>  			link = media_create_intf_link(&sd->entity,
>  						      &vdev->intf_devnode->intf,
> -						      MEDIA_LNK_FL_ENABLED);
> +						      MEDIA_LNK_FL_ENABLED,
> +						      GFP_KERNEL);
>  			if (!link) {
>  				err = -ENOMEM;
>  				goto clean_up;
> diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
> index 40ee864..b1652f9 100644
> --- a/drivers/media/v4l2-core/v4l2-mc.c
> +++ b/drivers/media/v4l2-core/v4l2-mc.c
> @@ -92,7 +92,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  				continue;
>  			ret = media_create_pad_link(entity, 0,
>  						    io_v4l, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -110,18 +111,21 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						    if_vid,
>  						    IF_VID_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  			ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
>  			ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT,
>  						decoder, DEMOD_PAD_IF_INPUT,
> -						MEDIA_LNK_FL_ENABLED);
> +						MEDIA_LNK_FL_ENABLED,
> +						GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		}
> @@ -130,7 +134,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  			ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT,
>  						    if_aud,
>  						    IF_AUD_DEC_PAD_IF_INPUT,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				return ret;
>  		} else {
> @@ -143,7 +148,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_v4l) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_v4l, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -151,7 +156,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_swradio) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
>  					io_swradio, 0,
> -					MEDIA_LNK_FL_ENABLED);
> +					MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -159,7 +164,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  	if (io_vbi) {
>  		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
>  					    io_vbi, 0,
> -					    MEDIA_LNK_FL_ENABLED);
> +					    MEDIA_LNK_FL_ENABLED, GFP_KERNEL);
>  		if (ret)
>  			return ret;
>  	}
> @@ -174,13 +179,13 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
>  
>  			ret = media_create_pad_link(entity, 0, tuner,
>  						    TUNER_PAD_RF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		case MEDIA_ENT_F_CONN_SVIDEO:
>  		case MEDIA_ENT_F_CONN_COMPOSITE:
>  			ret = media_create_pad_link(entity, 0, decoder,
>  						    DEMOD_PAD_IF_INPUT,
> -						    flags);
> +						    flags, GFP_KERNEL);
>  			break;
>  		default:
>  			continue;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> index 633d645..d1442b9 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
> @@ -977,7 +977,8 @@ vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
>  
>  	flags = 0;
>  	ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
> -					&ipipeif->subdev.entity, 0, flags);
> +					&ipipeif->subdev.entity, 0, flags,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		goto fail;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> index 9905789..2470655 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c
> @@ -1824,7 +1824,7 @@ int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
>  	/* connect isif to video node */
>  	ret = media_create_pad_link(&isif->subdev.entity, 1,
>  				       &isif->video_out.video_dev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  	return 0;
> diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> index a91395c..067f699 100644
> --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
> @@ -1833,26 +1833,28 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer,
>  	/* create link between Resizer Crop----> Resizer A*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1,
>  				&resizer->resizer_a.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer Crop----> Resizer B*/
>  	ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2,
>  				&resizer->resizer_b.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer A ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1,
> -		&resizer->resizer_a.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_a.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
>  	/* create link between Resizer B ----> video out */
>  	ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1,
> -		&resizer->resizer_b.video_out.video_dev.entity, 0, flags);
> +		&resizer->resizer_b.video_out.video_dev.entity, 0, flags,
> +		GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_create_link;
>  
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> index ec46f36..bee9f5c 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c
> @@ -447,32 +447,32 @@ static int vpfe_register_entities(struct vpfe_device *vpfe_dev)
>  		if (vpfe_dev->sd[i]->entity.num_pads) {
>  			ret = media_create_pad_link(&vpfe_dev->sd[i]->entity,
>  				0, &vpfe_dev->vpfe_isif.subdev.entity,
> -				0, flags);
> +				0, flags, GFP_KERNEL);
>  			if (ret < 0)
>  				goto out_resizer_register;
>  		}
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipeif.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  				       &vpfe_dev->vpfe_ipipe.subdev.entity,
> -				       0, flags);
> +				       0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity,
>  			1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
>  	ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1,
>  			&vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity,
> -			0, flags);
> +			0, flags, GFP_KERNEL);
>  	if (ret < 0)
>  		goto out_resizer_register;
>  
> diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
> index fb80d2b..933c8a7 100644
> --- a/drivers/staging/media/omap4iss/iss.c
> +++ b/drivers/staging/media/omap4iss/iss.c
> @@ -1065,7 +1065,7 @@ static int iss_register_entities(struct iss_device *iss)
>  		}
>  
>  		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
> -					       flags);
> +					       flags, GFP_KERNEL);
>  		if (ret < 0)
>  			goto done;
>  	}
> @@ -1110,31 +1110,36 @@ static int iss_create_links(struct iss_device *iss)
>  	/* Connect the submodules. */
>  	ret = media_create_pad_link(
>  			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
> -			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
> +			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
> -			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
> +			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	ret = media_create_pad_link(
>  			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
> -			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
> +			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0,
> +			GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
> index aaca39d..4b40132 100644
> --- a/drivers/staging/media/omap4iss/iss_csi2.c
> +++ b/drivers/staging/media/omap4iss/iss_csi2.c
> @@ -1352,13 +1352,15 @@ int omap4iss_csi2_create_links(struct iss_device *iss)
>  
>  	/* Connect the CSI2a subdev to the video node. */
>  	ret = media_create_pad_link(&csi2a->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2a->video_out.video.entity, 0, 0);
> +				    &csi2a->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Connect the CSI2b subdev to the video node. */
>  	ret = media_create_pad_link(&csi2b->subdev.entity, CSI2_PAD_SOURCE,
> -				    &csi2b->video_out.video.entity, 0, 0);
> +				    &csi2b->video_out.video.entity, 0, 0,
> +				    GFP_KERNEL);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
> index 23de833..2f124b0 100644
> --- a/drivers/staging/media/omap4iss/iss_ipipeif.c
> +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c
> @@ -827,7 +827,8 @@ int omap4iss_ipipeif_create_links(struct iss_device *iss)
>  	/* Connect the IPIPEIF subdev to the video node. */
>  	return media_create_pad_link(&ipipeif->subdev.entity,
>  				     IPIPEIF_PAD_SOURCE_ISIF_SF,
> -				     &ipipeif->video_out.video.entity, 0, 0);
> +				     &ipipeif->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
> index f1d352c..8d5766a 100644
> --- a/drivers/staging/media/omap4iss/iss_resizer.c
> +++ b/drivers/staging/media/omap4iss/iss_resizer.c
> @@ -869,7 +869,8 @@ int omap4iss_resizer_create_links(struct iss_device *iss)
>  	/* Connect the RESIZER subdev to the video node. */
>  	return media_create_pad_link(&resizer->subdev.entity,
>  				     RESIZER_PAD_SOURCE_MEM,
> -				     &resizer->video_out.video.entity, 0, 0);
> +				     &resizer->video_out.video.entity, 0, 0,
> +				     GFP_KERNEL);
>  }
>  
>  /*
> diff --git a/include/media/media-entity.h b/include/media/media-entity.h
> index 6dc9e4e..0665c2d 100644
> --- a/include/media/media-entity.h
> +++ b/include/media/media-entity.h
> @@ -595,6 +595,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   * @sink:	pointer to &media_entity of the sink pad.
>   * @sink_pad:	number of the sink pad in the pads array.
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * Valid values for flags:
>   * A %MEDIA_LNK_FL_ENABLED flag indicates that the link is enabled and can be
> @@ -613,7 +614,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {};
>   */
>  __must_check int media_create_pad_link(struct media_entity *source,
>  			u16 source_pad, struct media_entity *sink,
> -			u16 sink_pad, u32 flags);
> +			u16 sink_pad, u32 flags, gfp_t gfpflags);
>  
>  /**
>   * media_create_pad_links() - creates a link between two entities.
> @@ -883,11 +884,12 @@ void __media_entity_pipeline_stop(struct media_entity *entity);
>  struct media_intf_devnode *
>  __must_check media_devnode_create(struct media_device *mdev,
>  				  u32 type, u32 flags,
> -				  u32 major, u32 minor);
> +				  u32 major, u32 minor, gfp_t gfpflags);
>  /**
>   * media_devnode_remove() - removes a device node interface
>   *
>   * @devnode:	pointer to &media_intf_devnode to be freed.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   * When a device node interface is removed, all links to it are automatically
>   * removed.
> @@ -901,6 +903,7 @@ struct media_link *
>   * @entity:	pointer to %media_entity
>   * @intf:	pointer to %media_interface
>   * @flags:	Link flags, as defined in include/uapi/linux/media.h.
> + * @gfpflags:	Get Free Page (GFP) flags, as defined in include/linux/gfp.h
>   *
>   *
>   * Valid values for flags:
> @@ -921,7 +924,7 @@ struct media_link *
>   */
>  __must_check media_create_intf_link(struct media_entity *entity,
>  				    struct media_interface *intf,
> -				    u32 flags);
> +				    u32 flags, gfp_t gfpflags);
>  /**
>   * __media_remove_intf_link() - remove a single interface link
>   *
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 93a50d01..f5ac038 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -88,14 +88,16 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  
>  	mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
>  						  MAJOR(pcm_dev->devt),
> -						  MINOR(pcm_dev->devt));
> +						  MINOR(pcm_dev->devt),
> +						  GFP_KERNEL);
>  	if (!mctl->intf_devnode) {
>  		ret = -ENOMEM;
>  		goto unregister_entity;
>  	}
>  	mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  						 &mctl->intf_devnode->intf,
> -						 MEDIA_LNK_FL_ENABLED);
> +						 MEDIA_LNK_FL_ENABLED,
> +						 GFP_KERNEL);
>  	if (!mctl->intf_link) {
>  		ret = -ENOMEM;
>  		goto devnode_remove;
> @@ -107,7 +109,8 @@ int media_snd_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
>  		case MEDIA_ENT_F_AUDIO_MIXER:
>  			ret = media_create_pad_link(entity, mixer_pad,
>  						    &mctl->media_entity, 0,
> -						    MEDIA_LNK_FL_ENABLED);
> +						    MEDIA_LNK_FL_ENABLED,
> +						    GFP_KERNEL);
>  			if (ret)
>  				goto remove_intf_link;
>  			break;
> @@ -180,7 +183,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  	if (!ctl_intf) {
>  		ctl_intf = media_devnode_create(mdev, intf_type, 0,
>  						MAJOR(ctl_dev->devt),
> -						MINOR(ctl_dev->devt));
> +						MINOR(ctl_dev->devt),
> +						GFP_KERNEL);
>  		if (!ctl_intf)
>  			return -ENOMEM;
>  		chip->ctl_intf_media_devnode = ctl_intf;
> @@ -213,7 +217,8 @@ int media_snd_mixer_init(struct snd_usb_audio *chip)
>  
>  		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
>  							 &ctl_intf->intf,
> -							 MEDIA_LNK_FL_ENABLED);
> +							 MEDIA_LNK_FL_ENABLED,
> +							 GFP_KERNEL);
>  		if (!mctl->intf_link) {
>  			media_device_unregister_entity(&mctl->media_entity);
>  			media_entity_cleanup(&mctl->media_entity);


-- 
Thanks,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-13  1:48 ` Shuah Khan
@ 2016-03-14  7:22   ` Sakari Ailus
  -1 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-14  7:22 UTC (permalink / raw)
  To: Shuah Khan
  Cc: mchehab, kyungmin.park, a.hajda, s.nawrocki, kgene, k.kozlowski,
	laurent.pinchart, hyun.kwon, soren.brinkmann, gregkh, perex,
	tiwai, hans.verkuil, lixiubo, javier, g.liakhovetski,
	chehabrafael, crope, tommi.franttila, dan.carpenter,
	prabhakar.csengg, hamohammed.sa, der.herr, navyasri.tech,
	Julia.Lawall, amitoj1606, linux-media, linux-kernel,
	linux-arm-kernel, linux-samsung-soc, linux-renesas-soc, devel,
	alsa-devel

Hi Shuah,

On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

What's the use case for calling the above functions in an atomic context?

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14  7:22   ` Sakari Ailus
  0 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-14  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shuah,

On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> media_devnode_create(), and media_add_link() that could get called
> in atomic context to allow callers to pass in the right flags for
> memory allocation.
> 
> tree-wide driver changes for media_*() GFP flags change:
> Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> media_create_intf_link() and media_devnode_create().
> 
> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

What's the use case for calling the above functions in an atomic context?

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-14  7:22   ` Sakari Ailus
@ 2016-03-14 10:13     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-14 10:13 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Em Mon, 14 Mar 2016 09:22:37 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Shuah,
> 
> On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > media_devnode_create(), and media_add_link() that could get called
> > in atomic context to allow callers to pass in the right flags for
> > memory allocation.
> > 
> > tree-wide driver changes for media_*() GFP flags change:
> > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > media_create_intf_link() and media_devnode_create().
> > 
> > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> 
> What's the use case for calling the above functions in an atomic context?
> 

ALSA code seems to do a lot of stuff at atomic context. That's what
happens on my test machine when au0828 gets probed before
snd-usb-audio:
	http://pastebin.com/LEX5LD5K

It seems that ALSA USB probe routine (usb_audio_probe) happens in
atomic context.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14 10:13     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-14 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

Em Mon, 14 Mar 2016 09:22:37 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Shuah,
> 
> On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > media_devnode_create(), and media_add_link() that could get called
> > in atomic context to allow callers to pass in the right flags for
> > memory allocation.
> > 
> > tree-wide driver changes for media_*() GFP flags change:
> > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > media_create_intf_link() and media_devnode_create().
> > 
> > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> 
> What's the use case for calling the above functions in an atomic context?
> 

ALSA code seems to do a lot of stuff at atomic context. That's what
happens on my test machine when au0828 gets probed before
snd-usb-audio:
	http://pastebin.com/LEX5LD5K

It seems that ALSA USB probe routine (usb_audio_probe) happens in
atomic context.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-14 10:13     ` Mauro Carvalho Chehab
  (?)
@ 2016-03-14 10:33       ` Takashi Iwai
  -1 siblings, 0 replies; 26+ messages in thread
From: Takashi Iwai @ 2016-03-14 10:33 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Sakari Ailus, alsa-devel, hans.verkuil, lixiubo, devel,
	amitoj1606, chehabrafael, hamohammed.sa, navyasri.tech,
	prabhakar.csengg, g.liakhovetski, der.herr, laurent.pinchart,
	crope, tommi.franttila, kgene, gregkh, Julia.Lawall,
	linux-arm-kernel, dan.carpenter, javier, Shuah Khan, perex,
	a.hajda, k.kozlowski, kyungmin.park, s.nawrocki, linux-kernel,
	linux-media, linux-renesas-soc, linux-samsung-soc, hyun.kwon,
	soren.brinkmann

On Mon, 14 Mar 2016 11:13:58 +0100,
Mauro Carvalho Chehab wrote:
> 
> Em Mon, 14 Mar 2016 09:22:37 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Shuah,
> > 
> > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > media_devnode_create(), and media_add_link() that could get called
> > > in atomic context to allow callers to pass in the right flags for
> > > memory allocation.
> > > 
> > > tree-wide driver changes for media_*() GFP flags change:
> > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > media_create_intf_link() and media_devnode_create().
> > > 
> > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> > 
> > What's the use case for calling the above functions in an atomic context?
> > 
> 
> ALSA code seems to do a lot of stuff at atomic context. That's what
> happens on my test machine when au0828 gets probed before
> snd-usb-audio:
> 	http://pastebin.com/LEX5LD5K
> 
> It seems that ALSA USB probe routine (usb_audio_probe) happens in
> atomic context.

No, usb_audio_probe() doesn't take a lock.  But
media_device_register_entity() seems taking a spinlock, instead.


Takashi

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14 10:33       ` Takashi Iwai
  0 siblings, 0 replies; 26+ messages in thread
From: Takashi Iwai @ 2016-03-14 10:33 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: hamohammed.sa, alsa-devel, k.kozlowski, Shuah Khan, a.hajda,
	prabhakar.csengg, laurent.pinchart, s.nawrocki, devel, crope,
	lixiubo, linux-samsung-soc, chehabrafael, javier, kgene,
	der.herr, soren.brinkmann, hans.verkuil, navyasri.tech,
	dan.carpenter, linux-media, tommi.franttila, Julia.Lawall, perex,
	linux-arm-kernel, hyun.kwon, gregkh, linux-kernel,
	linux-renesas-soc, kyungmin.park, Sakari Ailus, g.liakhovetski

On Mon, 14 Mar 2016 11:13:58 +0100,
Mauro Carvalho Chehab wrote:
> 
> Em Mon, 14 Mar 2016 09:22:37 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Shuah,
> > 
> > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > media_devnode_create(), and media_add_link() that could get called
> > > in atomic context to allow callers to pass in the right flags for
> > > memory allocation.
> > > 
> > > tree-wide driver changes for media_*() GFP flags change:
> > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > media_create_intf_link() and media_devnode_create().
> > > 
> > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> > 
> > What's the use case for calling the above functions in an atomic context?
> > 
> 
> ALSA code seems to do a lot of stuff at atomic context. That's what
> happens on my test machine when au0828 gets probed before
> snd-usb-audio:
> 	http://pastebin.com/LEX5LD5K
> 
> It seems that ALSA USB probe routine (usb_audio_probe) happens in
> atomic context.

No, usb_audio_probe() doesn't take a lock.  But
media_device_register_entity() seems taking a spinlock, instead.


Takashi

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14 10:33       ` Takashi Iwai
  0 siblings, 0 replies; 26+ messages in thread
From: Takashi Iwai @ 2016-03-14 10:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 14 Mar 2016 11:13:58 +0100,
Mauro Carvalho Chehab wrote:
> 
> Em Mon, 14 Mar 2016 09:22:37 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Shuah,
> > 
> > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > media_devnode_create(), and media_add_link() that could get called
> > > in atomic context to allow callers to pass in the right flags for
> > > memory allocation.
> > > 
> > > tree-wide driver changes for media_*() GFP flags change:
> > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > media_create_intf_link() and media_devnode_create().
> > > 
> > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> > 
> > What's the use case for calling the above functions in an atomic context?
> > 
> 
> ALSA code seems to do a lot of stuff at atomic context. That's what
> happens on my test machine when au0828 gets probed before
> snd-usb-audio:
> 	http://pastebin.com/LEX5LD5K
> 
> It seems that ALSA USB probe routine (usb_audio_probe) happens in
> atomic context.

No, usb_audio_probe() doesn't take a lock.  But
media_device_register_entity() seems taking a spinlock, instead.


Takashi

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-14 10:13     ` Mauro Carvalho Chehab
@ 2016-03-14 10:52       ` Sakari Ailus
  -1 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-14 10:52 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Hi Mauro,

On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:
> Em Mon, 14 Mar 2016 09:22:37 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Shuah,
> > 
> > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > media_devnode_create(), and media_add_link() that could get called
> > > in atomic context to allow callers to pass in the right flags for
> > > memory allocation.
> > > 
> > > tree-wide driver changes for media_*() GFP flags change:
> > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > media_create_intf_link() and media_devnode_create().
> > > 
> > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> > 
> > What's the use case for calling the above functions in an atomic context?
> > 
> 
> ALSA code seems to do a lot of stuff at atomic context. That's what
> happens on my test machine when au0828 gets probed before
> snd-usb-audio:
> 	http://pastebin.com/LEX5LD5K
> 
> It seems that ALSA USB probe routine (usb_audio_probe) happens in
> atomic context.

usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
cannot be called in atomic context.

In the above log, what I did notice, though, was that because *we* grab
mdev->lock spinlock in media_device_register_entity(), we may not sleep
which is what the notify() callback implementation in au0828 driver does
(for memory allocation).

Could we instead replace mdev->lock by a mutex?

If there is no pressing need to implement atomic memory allocation I simply
wouldn't do it, especially in device initialisation where an allocation
failure will lead to probe failure as well.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14 10:52       ` Sakari Ailus
  0 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-14 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mauro,

On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:
> Em Mon, 14 Mar 2016 09:22:37 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Shuah,
> > 
> > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > media_devnode_create(), and media_add_link() that could get called
> > > in atomic context to allow callers to pass in the right flags for
> > > memory allocation.
> > > 
> > > tree-wide driver changes for media_*() GFP flags change:
> > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > media_create_intf_link() and media_devnode_create().
> > > 
> > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>  
> > 
> > What's the use case for calling the above functions in an atomic context?
> > 
> 
> ALSA code seems to do a lot of stuff at atomic context. That's what
> happens on my test machine when au0828 gets probed before
> snd-usb-audio:
> 	http://pastebin.com/LEX5LD5K
> 
> It seems that ALSA USB probe routine (usb_audio_probe) happens in
> atomic context.

usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
cannot be called in atomic context.

In the above log, what I did notice, though, was that because *we* grab
mdev->lock spinlock in media_device_register_entity(), we may not sleep
which is what the notify() callback implementation in au0828 driver does
(for memory allocation).

Could we instead replace mdev->lock by a mutex?

If there is no pressing need to implement atomic memory allocation I simply
wouldn't do it, especially in device initialisation where an allocation
failure will lead to probe failure as well.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-14 10:52       ` Sakari Ailus
@ 2016-03-14 11:46         ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-14 11:46 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Em Mon, 14 Mar 2016 12:52:54 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:
> > Em Mon, 14 Mar 2016 09:22:37 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Shuah,
> > > 
> > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:  
> > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > media_devnode_create(), and media_add_link() that could get called
> > > > in atomic context to allow callers to pass in the right flags for
> > > > memory allocation.
> > > > 
> > > > tree-wide driver changes for media_*() GFP flags change:
> > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > media_create_intf_link() and media_devnode_create().
> > > > 
> > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>    
> > > 
> > > What's the use case for calling the above functions in an atomic context?
> > >   
> > 
> > ALSA code seems to do a lot of stuff at atomic context. That's what
> > happens on my test machine when au0828 gets probed before
> > snd-usb-audio:
> > 	http://pastebin.com/LEX5LD5K
> > 
> > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > atomic context.  
> 
> usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> cannot be called in atomic context.
> 
> In the above log, what I did notice, though, was that because *we* grab
> mdev->lock spinlock in media_device_register_entity(), we may not sleep
> which is what the notify() callback implementation in au0828 driver does
> (for memory allocation).

True. After looking into the code, the problem is that the notify
callbacks are called with the spinlock hold. I don't see any reason
to do that.

> Could we instead replace mdev->lock by a mutex?

We changed the code to use a spinlock for a reason: this fixed some
troubles in the past with the code locking (can't remember the problem,
but this was documented at the kernel logs and at the ML). Yet, the code
under the spinlock never sleeps, so this is fine.

Yet, in the future, we'll need to do a review of all the locking schema,
in order to better support dynamic graph changes.

> If there is no pressing need to implement atomic memory allocation I simply
> wouldn't do it, especially in device initialisation where an allocation
> failure will lead to probe failure as well.

The fix for this issue should be simple. See the enclosed code. Btw.
it probably makes sense to add some code here to avoid starving the
stack, as a notify callback could try to create an entity, with,
in turn, would call the notify callback again.

I'll run some tests here to double check if it fixes the issue.

---

[media] media-device: Don't call notify callbacks holding a spinlock

The notify routines may sleep. So, they can't be called in spinlock
context. Also, they may want to call other media routines that might
be spinning the spinlock, like creating a link.

This fixes the following bug:

[ 1839.510587] BUG: sleeping function called from invalid context at mm/slub.c:1289
[ 1839.510881] in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
[ 1839.511157] 4 locks held by modprobe/3479:
[ 1839.511415]  #0:  (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
[ 1839.512381]  #1:  (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
[ 1839.512388]  #2:  (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
[ 1839.512401]  #3:  (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
[ 1839.512412] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
[ 1839.512415] Hardware name:                  /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
[ 1839.512417]  0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
[ 1839.512422]  ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
[ 1839.512427]  ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
[ 1839.512432] Call Trace:
[ 1839.512436]  [<ffffffff81933901>] dump_stack+0x85/0xc4
[ 1839.512440]  [<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
[ 1839.512443]  [<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
[ 1839.512446]  [<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
[ 1839.512451]  [<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
[ 1839.512455]  [<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
[ 1839.512459]  [<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
[ 1839.512463]  [<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
[ 1839.512467]  [<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
[ 1839.512471]  [<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]

(untested)

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 6ba6e8f982fc..fc3c199e5500 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -587,14 +587,15 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
 			       &entity->pads[i].graph_obj);
 
+	spin_unlock(&mdev->lock);
+
 	/* invoke entity_notify callbacks */
 	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
 		(notify)->notify(entity, notify->notify_data);
 	}
 
-	spin_unlock(&mdev->lock);
-
 	mutex_lock(&mdev->graph_mutex);
+
 	if (mdev->entity_internal_idx_max
 	    >= mdev->pm_count_walk.ent_enum.idx_max) {
 		struct media_entity_graph new = { .top = 0 };

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14 11:46         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-14 11:46 UTC (permalink / raw)
  To: linux-arm-kernel

Em Mon, 14 Mar 2016 12:52:54 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:
> > Em Mon, 14 Mar 2016 09:22:37 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Shuah,
> > > 
> > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:  
> > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > media_devnode_create(), and media_add_link() that could get called
> > > > in atomic context to allow callers to pass in the right flags for
> > > > memory allocation.
> > > > 
> > > > tree-wide driver changes for media_*() GFP flags change:
> > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > media_create_intf_link() and media_devnode_create().
> > > > 
> > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>    
> > > 
> > > What's the use case for calling the above functions in an atomic context?
> > >   
> > 
> > ALSA code seems to do a lot of stuff at atomic context. That's what
> > happens on my test machine when au0828 gets probed before
> > snd-usb-audio:
> > 	http://pastebin.com/LEX5LD5K
> > 
> > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > atomic context.  
> 
> usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> cannot be called in atomic context.
> 
> In the above log, what I did notice, though, was that because *we* grab
> mdev->lock spinlock in media_device_register_entity(), we may not sleep
> which is what the notify() callback implementation in au0828 driver does
> (for memory allocation).

True. After looking into the code, the problem is that the notify
callbacks are called with the spinlock hold. I don't see any reason
to do that.

> Could we instead replace mdev->lock by a mutex?

We changed the code to use a spinlock for a reason: this fixed some
troubles in the past with the code locking (can't remember the problem,
but this was documented at the kernel logs and at the ML). Yet, the code
under the spinlock never sleeps, so this is fine.

Yet, in the future, we'll need to do a review of all the locking schema,
in order to better support dynamic graph changes.

> If there is no pressing need to implement atomic memory allocation I simply
> wouldn't do it, especially in device initialisation where an allocation
> failure will lead to probe failure as well.

The fix for this issue should be simple. See the enclosed code. Btw.
it probably makes sense to add some code here to avoid starving the
stack, as a notify callback could try to create an entity, with,
in turn, would call the notify callback again.

I'll run some tests here to double check if it fixes the issue.

---

[media] media-device: Don't call notify callbacks holding a spinlock

The notify routines may sleep. So, they can't be called in spinlock
context. Also, they may want to call other media routines that might
be spinning the spinlock, like creating a link.

This fixes the following bug:

[ 1839.510587] BUG: sleeping function called from invalid context at mm/slub.c:1289
[ 1839.510881] in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
[ 1839.511157] 4 locks held by modprobe/3479:
[ 1839.511415]  #0:  (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
[ 1839.512381]  #1:  (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
[ 1839.512388]  #2:  (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
[ 1839.512401]  #3:  (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
[ 1839.512412] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
[ 1839.512415] Hardware name:                  /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
[ 1839.512417]  0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
[ 1839.512422]  ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
[ 1839.512427]  ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
[ 1839.512432] Call Trace:
[ 1839.512436]  [<ffffffff81933901>] dump_stack+0x85/0xc4
[ 1839.512440]  [<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
[ 1839.512443]  [<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
[ 1839.512446]  [<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
[ 1839.512451]  [<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
[ 1839.512455]  [<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
[ 1839.512459]  [<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
[ 1839.512463]  [<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
[ 1839.512467]  [<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
[ 1839.512471]  [<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]

(untested)

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 6ba6e8f982fc..fc3c199e5500 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -587,14 +587,15 @@ int __must_check media_device_register_entity(struct media_device *mdev,
 		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
 			       &entity->pads[i].graph_obj);
 
+	spin_unlock(&mdev->lock);
+
 	/* invoke entity_notify callbacks */
 	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
 		(notify)->notify(entity, notify->notify_data);
 	}
 
-	spin_unlock(&mdev->lock);
-
 	mutex_lock(&mdev->graph_mutex);
+
 	if (mdev->entity_internal_idx_max
 	    >= mdev->pm_count_walk.ent_enum.idx_max) {
 		struct media_entity_graph new = { .top = 0 };

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-14 11:46         ` Mauro Carvalho Chehab
@ 2016-03-14 12:09           ` Sakari Ailus
  -1 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-14 12:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Hi Mauro,

On Mon, Mar 14, 2016 at 08:46:33AM -0300, Mauro Carvalho Chehab wrote:
> Em Mon, 14 Mar 2016 12:52:54 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Mauro,
> > 
> > On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:
> > > Em Mon, 14 Mar 2016 09:22:37 +0200
> > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > >   
> > > > Hi Shuah,
> > > > 
> > > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:  
> > > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > > media_devnode_create(), and media_add_link() that could get called
> > > > > in atomic context to allow callers to pass in the right flags for
> > > > > memory allocation.
> > > > > 
> > > > > tree-wide driver changes for media_*() GFP flags change:
> > > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > > media_create_intf_link() and media_devnode_create().
> > > > > 
> > > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>    
> > > > 
> > > > What's the use case for calling the above functions in an atomic context?
> > > >   
> > > 
> > > ALSA code seems to do a lot of stuff at atomic context. That's what
> > > happens on my test machine when au0828 gets probed before
> > > snd-usb-audio:
> > > 	http://pastebin.com/LEX5LD5K
> > > 
> > > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > > atomic context.  
> > 
> > usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> > cannot be called in atomic context.
> > 
> > In the above log, what I did notice, though, was that because *we* grab
> > mdev->lock spinlock in media_device_register_entity(), we may not sleep
> > which is what the notify() callback implementation in au0828 driver does
> > (for memory allocation).
> 
> True. After looking into the code, the problem is that the notify
> callbacks are called with the spinlock hold. I don't see any reason
> to do that.

Notify callbacks, perhaps not, but the list is still protected by the
spinlock. It perhaps is not likely that another process would change it but
I don't think we can rely on that.

> 
> > Could we instead replace mdev->lock by a mutex?
> 
> We changed the code to use a spinlock for a reason: this fixed some
> troubles in the past with the code locking (can't remember the problem,
> but this was documented at the kernel logs and at the ML). Yet, the code
> under the spinlock never sleeps, so this is fine.

struct media_device.lock was added by this patch:

commit 53e269c102fbaf77e7dc526b1606ad4a48e57200
Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date:   Wed Dec 9 08:40:00 2009 -0300

    [media] media: Entities, pads and links

    As video hardware pipelines become increasingly complex and
    configurable, the current hardware description through v4l2 subdevices
    reaches its limits. In addition to enumerating and configuring
    subdevices, video camera drivers need a way to discover and modify at
    runtime how those subdevices are connected. This is done through new
    elements called entities, pads and links.

...

    Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
    Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
    Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

I think it was always a spinlock, for the reason you stated above as well:
it did not need to sleep. But if there is a need to sleep, I think we should
consider changing that.

> 
> Yet, in the future, we'll need to do a review of all the locking schema,
> in order to better support dynamic graph changes.

Agreed. I think more fine grained locking should be considered. The media
graph mutex will become a bottleneck at some point, especially if we make
the media devices system wide at some point.

> 
> > If there is no pressing need to implement atomic memory allocation I simply
> > wouldn't do it, especially in device initialisation where an allocation
> > failure will lead to probe failure as well.
> 
> The fix for this issue should be simple. See the enclosed code. Btw.
> it probably makes sense to add some code here to avoid starving the
> stack, as a notify callback could try to create an entity, with,
> in turn, would call the notify callback again.
> 
> I'll run some tests here to double check if it fixes the issue.
> 
> ---
> 
> [media] media-device: Don't call notify callbacks holding a spinlock
> 
> The notify routines may sleep. So, they can't be called in spinlock
> context. Also, they may want to call other media routines that might
> be spinning the spinlock, like creating a link.
> 
> This fixes the following bug:
> 
> [ 1839.510587] BUG: sleeping function called from invalid context at mm/slub.c:1289
> [ 1839.510881] in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
> [ 1839.511157] 4 locks held by modprobe/3479:
> [ 1839.511415]  #0:  (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
> [ 1839.512381]  #1:  (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
> [ 1839.512388]  #2:  (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
> [ 1839.512401]  #3:  (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
> [ 1839.512412] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
> [ 1839.512415] Hardware name:                  /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
> [ 1839.512417]  0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
> [ 1839.512422]  ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
> [ 1839.512427]  ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
> [ 1839.512432] Call Trace:
> [ 1839.512436]  [<ffffffff81933901>] dump_stack+0x85/0xc4
> [ 1839.512440]  [<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
> [ 1839.512443]  [<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
> [ 1839.512446]  [<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
> [ 1839.512451]  [<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
> [ 1839.512455]  [<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
> [ 1839.512459]  [<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
> [ 1839.512463]  [<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
> [ 1839.512467]  [<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
> [ 1839.512471]  [<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]
> 
> (untested)
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> 
> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> index 6ba6e8f982fc..fc3c199e5500 100644
> --- a/drivers/media/media-device.c
> +++ b/drivers/media/media-device.c
> @@ -587,14 +587,15 @@ int __must_check media_device_register_entity(struct media_device *mdev,
>  		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
>  			       &entity->pads[i].graph_obj);
>  
> +	spin_unlock(&mdev->lock);
> +
>  	/* invoke entity_notify callbacks */
>  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
>  		(notify)->notify(entity, notify->notify_data);
>  	}
>  
> -	spin_unlock(&mdev->lock);
> -
>  	mutex_lock(&mdev->graph_mutex);
> +
>  	if (mdev->entity_internal_idx_max
>  	    >= mdev->pm_count_walk.ent_enum.idx_max) {
>  		struct media_entity_graph new = { .top = 0 };
> 

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-14 12:09           ` Sakari Ailus
  0 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-14 12:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mauro,

On Mon, Mar 14, 2016 at 08:46:33AM -0300, Mauro Carvalho Chehab wrote:
> Em Mon, 14 Mar 2016 12:52:54 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Mauro,
> > 
> > On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:
> > > Em Mon, 14 Mar 2016 09:22:37 +0200
> > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > >   
> > > > Hi Shuah,
> > > > 
> > > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:  
> > > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > > media_devnode_create(), and media_add_link() that could get called
> > > > > in atomic context to allow callers to pass in the right flags for
> > > > > memory allocation.
> > > > > 
> > > > > tree-wide driver changes for media_*() GFP flags change:
> > > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > > media_create_intf_link() and media_devnode_create().
> > > > > 
> > > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>    
> > > > 
> > > > What's the use case for calling the above functions in an atomic context?
> > > >   
> > > 
> > > ALSA code seems to do a lot of stuff at atomic context. That's what
> > > happens on my test machine when au0828 gets probed before
> > > snd-usb-audio:
> > > 	http://pastebin.com/LEX5LD5K
> > > 
> > > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > > atomic context.  
> > 
> > usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> > cannot be called in atomic context.
> > 
> > In the above log, what I did notice, though, was that because *we* grab
> > mdev->lock spinlock in media_device_register_entity(), we may not sleep
> > which is what the notify() callback implementation in au0828 driver does
> > (for memory allocation).
> 
> True. After looking into the code, the problem is that the notify
> callbacks are called with the spinlock hold. I don't see any reason
> to do that.

Notify callbacks, perhaps not, but the list is still protected by the
spinlock. It perhaps is not likely that another process would change it but
I don't think we can rely on that.

> 
> > Could we instead replace mdev->lock by a mutex?
> 
> We changed the code to use a spinlock for a reason: this fixed some
> troubles in the past with the code locking (can't remember the problem,
> but this was documented at the kernel logs and at the ML). Yet, the code
> under the spinlock never sleeps, so this is fine.

struct media_device.lock was added by this patch:

commit 53e269c102fbaf77e7dc526b1606ad4a48e57200
Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date:   Wed Dec 9 08:40:00 2009 -0300

    [media] media: Entities, pads and links

    As video hardware pipelines become increasingly complex and
    configurable, the current hardware description through v4l2 subdevices
    reaches its limits. In addition to enumerating and configuring
    subdevices, video camera drivers need a way to discover and modify at
    runtime how those subdevices are connected. This is done through new
    elements called entities, pads and links.

...

    Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
    Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
    Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

I think it was always a spinlock, for the reason you stated above as well:
it did not need to sleep. But if there is a need to sleep, I think we should
consider changing that.

> 
> Yet, in the future, we'll need to do a review of all the locking schema,
> in order to better support dynamic graph changes.

Agreed. I think more fine grained locking should be considered. The media
graph mutex will become a bottleneck at some point, especially if we make
the media devices system wide at some point.

> 
> > If there is no pressing need to implement atomic memory allocation I simply
> > wouldn't do it, especially in device initialisation where an allocation
> > failure will lead to probe failure as well.
> 
> The fix for this issue should be simple. See the enclosed code. Btw.
> it probably makes sense to add some code here to avoid starving the
> stack, as a notify callback could try to create an entity, with,
> in turn, would call the notify callback again.
> 
> I'll run some tests here to double check if it fixes the issue.
> 
> ---
> 
> [media] media-device: Don't call notify callbacks holding a spinlock
> 
> The notify routines may sleep. So, they can't be called in spinlock
> context. Also, they may want to call other media routines that might
> be spinning the spinlock, like creating a link.
> 
> This fixes the following bug:
> 
> [ 1839.510587] BUG: sleeping function called from invalid context at mm/slub.c:1289
> [ 1839.510881] in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
> [ 1839.511157] 4 locks held by modprobe/3479:
> [ 1839.511415]  #0:  (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
> [ 1839.512381]  #1:  (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
> [ 1839.512388]  #2:  (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
> [ 1839.512401]  #3:  (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
> [ 1839.512412] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
> [ 1839.512415] Hardware name:                  /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
> [ 1839.512417]  0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
> [ 1839.512422]  ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
> [ 1839.512427]  ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
> [ 1839.512432] Call Trace:
> [ 1839.512436]  [<ffffffff81933901>] dump_stack+0x85/0xc4
> [ 1839.512440]  [<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
> [ 1839.512443]  [<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
> [ 1839.512446]  [<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
> [ 1839.512451]  [<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
> [ 1839.512455]  [<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
> [ 1839.512459]  [<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
> [ 1839.512463]  [<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
> [ 1839.512467]  [<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
> [ 1839.512471]  [<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]
> 
> (untested)
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> 
> diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> index 6ba6e8f982fc..fc3c199e5500 100644
> --- a/drivers/media/media-device.c
> +++ b/drivers/media/media-device.c
> @@ -587,14 +587,15 @@ int __must_check media_device_register_entity(struct media_device *mdev,
>  		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
>  			       &entity->pads[i].graph_obj);
>  
> +	spin_unlock(&mdev->lock);
> +
>  	/* invoke entity_notify callbacks */
>  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
>  		(notify)->notify(entity, notify->notify_data);
>  	}
>  
> -	spin_unlock(&mdev->lock);
> -
>  	mutex_lock(&mdev->graph_mutex);
> +
>  	if (mdev->entity_internal_idx_max
>  	    >= mdev->pm_count_walk.ent_enum.idx_max) {
>  		struct media_entity_graph new = { .top = 0 };
> 

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-14 12:09           ` Sakari Ailus
@ 2016-03-15 15:55             ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-15 15:55 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Em Mon, 14 Mar 2016 14:09:09 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> On Mon, Mar 14, 2016 at 08:46:33AM -0300, Mauro Carvalho Chehab wrote:
> > Em Mon, 14 Mar 2016 12:52:54 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Mauro,
> > > 
> > > On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:  
> > > > Em Mon, 14 Mar 2016 09:22:37 +0200
> > > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > > >     
> > > > > Hi Shuah,
> > > > > 
> > > > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:    
> > > > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > > > media_devnode_create(), and media_add_link() that could get called
> > > > > > in atomic context to allow callers to pass in the right flags for
> > > > > > memory allocation.
> > > > > > 
> > > > > > tree-wide driver changes for media_*() GFP flags change:
> > > > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > > > media_create_intf_link() and media_devnode_create().
> > > > > > 
> > > > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>      
> > > > > 
> > > > > What's the use case for calling the above functions in an atomic context?
> > > > >     
> > > > 
> > > > ALSA code seems to do a lot of stuff at atomic context. That's what
> > > > happens on my test machine when au0828 gets probed before
> > > > snd-usb-audio:
> > > > 	http://pastebin.com/LEX5LD5K
> > > > 
> > > > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > > > atomic context.    
> > > 
> > > usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> > > cannot be called in atomic context.
> > > 
> > > In the above log, what I did notice, though, was that because *we* grab
> > > mdev->lock spinlock in media_device_register_entity(), we may not sleep
> > > which is what the notify() callback implementation in au0828 driver does
> > > (for memory allocation).  
> > 
> > True. After looking into the code, the problem is that the notify
> > callbacks are called with the spinlock hold. I don't see any reason
> > to do that.  
> 
> Notify callbacks, perhaps not, but the list is still protected by the
> spinlock. It perhaps is not likely that another process would change it but
> I don't think we can rely on that.

I can see only 2 risks protected by the lock:

1) mdev gets freed while an entity is being created. This is a problem
   with the current memory protection schema we're using. I guess the
   only way to fix it is to use kref for mdev/entities/interfaces/links/pads.
   This change doesn't make it better or worse.
   Also, I don't think we have such risk with the current devices.

2) a notifier may be inserted or removed by another driver, while the
   loop is running.

To avoid (2), I see 3 alternatives:

a) keep the loop as proposed on this patch. As the list is navigated using 
list_for_each_entry_safe(), I guess[1] it should be safe to remove/add
new notify callbacks there while the loop is running by some other process. 

[1] It *is* safe if the change were done inside the loop - but I'm not
100% sure that it is safe if some other CPU touches the notify list.

b) Unlock/relock the spinlock every time:

	/* previous code that locks mdev->lock spinlock */

 	/* invoke entity_notify callbacks */
 	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
		spin_unlock(&mdev->lock);
 		(notify)->notify(entity, notify->notify_data);
		spin_lock(&mdev->lock);
 	}
 
	spin_unlock(&mdev->lock);

c) use a separate lock for the notify list -this seems to be an overkill.

d) Protect it with the graph traversal mutex. That sounds the worse idea,
   IMHO, as we'll be abusing the lock.

> 
> >   
> > > Could we instead replace mdev->lock by a mutex?  
> > 
> > We changed the code to use a spinlock for a reason: this fixed some
> > troubles in the past with the code locking (can't remember the problem,
> > but this was documented at the kernel logs and at the ML). Yet, the code
> > under the spinlock never sleeps, so this is fine.  
> 
> struct media_device.lock was added by this patch:
> 
> commit 53e269c102fbaf77e7dc526b1606ad4a48e57200
> Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Date:   Wed Dec 9 08:40:00 2009 -0300
> 
>     [media] media: Entities, pads and links
> 
>     As video hardware pipelines become increasingly complex and
>     configurable, the current hardware description through v4l2 subdevices
>     reaches its limits. In addition to enumerating and configuring
>     subdevices, video camera drivers need a way to discover and modify at
>     runtime how those subdevices are connected. This is done through new
>     elements called entities, pads and links.
> 
> ...
> 
>     Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>     Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
>     Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
>     Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> 
> I think it was always a spinlock, for the reason you stated above as well:
> it did not need to sleep. But if there is a need to sleep, I think we should
> consider changing that.

True, but there were some places that were using the graph_mutex
instead of the spinlock. 

> 
> > 
> > Yet, in the future, we'll need to do a review of all the locking schema,
> > in order to better support dynamic graph changes.  
> 
> Agreed. I think more fine grained locking should be considered. The media
> graph mutex will become a bottleneck at some point, especially if we make
> the media devices system wide at some point.

Yes. I guess we should protect the memory allocated stuff with a kref,
and try to use RCS on most places, but we need more discussions and
more tests to implement a solution that would be reliable even if the
callers don't behave well.

> >   
> > > If there is no pressing need to implement atomic memory allocation I simply
> > > wouldn't do it, especially in device initialisation where an allocation
> > > failure will lead to probe failure as well.  
> > 
> > The fix for this issue should be simple. See the enclosed code. Btw.
> > it probably makes sense to add some code here to avoid starving the
> > stack, as a notify callback could try to create an entity, with,
> > in turn, would call the notify callback again.
> > 
> > I'll run some tests here to double check if it fixes the issue.
> > 
> > ---
> > 
> > [media] media-device: Don't call notify callbacks holding a spinlock
> > 
> > The notify routines may sleep. So, they can't be called in spinlock
> > context. Also, they may want to call other media routines that might
> > be spinning the spinlock, like creating a link.
> > 
> > This fixes the following bug:
> > 
> > [ 1839.510587] BUG: sleeping function called from invalid context at mm/slub.c:1289
> > [ 1839.510881] in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
> > [ 1839.511157] 4 locks held by modprobe/3479:
> > [ 1839.511415]  #0:  (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
> > [ 1839.512381]  #1:  (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
> > [ 1839.512388]  #2:  (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
> > [ 1839.512401]  #3:  (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
> > [ 1839.512412] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
> > [ 1839.512415] Hardware name:                  /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
> > [ 1839.512417]  0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
> > [ 1839.512422]  ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
> > [ 1839.512427]  ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
> > [ 1839.512432] Call Trace:
> > [ 1839.512436]  [<ffffffff81933901>] dump_stack+0x85/0xc4
> > [ 1839.512440]  [<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
> > [ 1839.512443]  [<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
> > [ 1839.512446]  [<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
> > [ 1839.512451]  [<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
> > [ 1839.512455]  [<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
> > [ 1839.512459]  [<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
> > [ 1839.512463]  [<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
> > [ 1839.512467]  [<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
> > [ 1839.512471]  [<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]
> > 
> > (untested)
> > 
> > Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> > 
> > diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> > index 6ba6e8f982fc..fc3c199e5500 100644
> > --- a/drivers/media/media-device.c
> > +++ b/drivers/media/media-device.c
> > @@ -587,14 +587,15 @@ int __must_check media_device_register_entity(struct media_device *mdev,
> >  		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
> >  			       &entity->pads[i].graph_obj);
> >  
> > +	spin_unlock(&mdev->lock);
> > +
> >  	/* invoke entity_notify callbacks */
> >  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> >  		(notify)->notify(entity, notify->notify_data);
> >  	}
> >  
> > -	spin_unlock(&mdev->lock);
> > -
> >  	mutex_lock(&mdev->graph_mutex);
> > +
> >  	if (mdev->entity_internal_idx_max  
> >  	    >= mdev->pm_count_walk.ent_enum.idx_max) {  
> >  		struct media_entity_graph new = { .top = 0 };
> >   
> 


-- 
Thanks,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-15 15:55             ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-15 15:55 UTC (permalink / raw)
  To: linux-arm-kernel

Em Mon, 14 Mar 2016 14:09:09 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> On Mon, Mar 14, 2016 at 08:46:33AM -0300, Mauro Carvalho Chehab wrote:
> > Em Mon, 14 Mar 2016 12:52:54 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Mauro,
> > > 
> > > On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:  
> > > > Em Mon, 14 Mar 2016 09:22:37 +0200
> > > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > > >     
> > > > > Hi Shuah,
> > > > > 
> > > > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:    
> > > > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > > > media_devnode_create(), and media_add_link() that could get called
> > > > > > in atomic context to allow callers to pass in the right flags for
> > > > > > memory allocation.
> > > > > > 
> > > > > > tree-wide driver changes for media_*() GFP flags change:
> > > > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > > > media_create_intf_link() and media_devnode_create().
> > > > > > 
> > > > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>      
> > > > > 
> > > > > What's the use case for calling the above functions in an atomic context?
> > > > >     
> > > > 
> > > > ALSA code seems to do a lot of stuff at atomic context. That's what
> > > > happens on my test machine when au0828 gets probed before
> > > > snd-usb-audio:
> > > > 	http://pastebin.com/LEX5LD5K
> > > > 
> > > > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > > > atomic context.    
> > > 
> > > usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> > > cannot be called in atomic context.
> > > 
> > > In the above log, what I did notice, though, was that because *we* grab
> > > mdev->lock spinlock in media_device_register_entity(), we may not sleep
> > > which is what the notify() callback implementation in au0828 driver does
> > > (for memory allocation).  
> > 
> > True. After looking into the code, the problem is that the notify
> > callbacks are called with the spinlock hold. I don't see any reason
> > to do that.  
> 
> Notify callbacks, perhaps not, but the list is still protected by the
> spinlock. It perhaps is not likely that another process would change it but
> I don't think we can rely on that.

I can see only 2 risks protected by the lock:

1) mdev gets freed while an entity is being created. This is a problem
   with the current memory protection schema we're using. I guess the
   only way to fix it is to use kref for mdev/entities/interfaces/links/pads.
   This change doesn't make it better or worse.
   Also, I don't think we have such risk with the current devices.

2) a notifier may be inserted or removed by another driver, while the
   loop is running.

To avoid (2), I see 3 alternatives:

a) keep the loop as proposed on this patch. As the list is navigated using 
list_for_each_entry_safe(), I guess[1] it should be safe to remove/add
new notify callbacks there while the loop is running by some other process. 

[1] It *is* safe if the change were done inside the loop - but I'm not
100% sure that it is safe if some other CPU touches the notify list.

b) Unlock/relock the spinlock every time:

	/* previous code that locks mdev->lock spinlock */

 	/* invoke entity_notify callbacks */
 	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
		spin_unlock(&mdev->lock);
 		(notify)->notify(entity, notify->notify_data);
		spin_lock(&mdev->lock);
 	}
 
	spin_unlock(&mdev->lock);

c) use a separate lock for the notify list -this seems to be an overkill.

d) Protect it with the graph traversal mutex. That sounds the worse idea,
   IMHO, as we'll be abusing the lock.

> 
> >   
> > > Could we instead replace mdev->lock by a mutex?  
> > 
> > We changed the code to use a spinlock for a reason: this fixed some
> > troubles in the past with the code locking (can't remember the problem,
> > but this was documented at the kernel logs and at the ML). Yet, the code
> > under the spinlock never sleeps, so this is fine.  
> 
> struct media_device.lock was added by this patch:
> 
> commit 53e269c102fbaf77e7dc526b1606ad4a48e57200
> Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Date:   Wed Dec 9 08:40:00 2009 -0300
> 
>     [media] media: Entities, pads and links
> 
>     As video hardware pipelines become increasingly complex and
>     configurable, the current hardware description through v4l2 subdevices
>     reaches its limits. In addition to enumerating and configuring
>     subdevices, video camera drivers need a way to discover and modify at
>     runtime how those subdevices are connected. This is done through new
>     elements called entities, pads and links.
> 
> ...
> 
>     Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>     Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
>     Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
>     Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> 
> I think it was always a spinlock, for the reason you stated above as well:
> it did not need to sleep. But if there is a need to sleep, I think we should
> consider changing that.

True, but there were some places that were using the graph_mutex
instead of the spinlock. 

> 
> > 
> > Yet, in the future, we'll need to do a review of all the locking schema,
> > in order to better support dynamic graph changes.  
> 
> Agreed. I think more fine grained locking should be considered. The media
> graph mutex will become a bottleneck at some point, especially if we make
> the media devices system wide at some point.

Yes. I guess we should protect the memory allocated stuff with a kref,
and try to use RCS on most places, but we need more discussions and
more tests to implement a solution that would be reliable even if the
callers don't behave well.

> >   
> > > If there is no pressing need to implement atomic memory allocation I simply
> > > wouldn't do it, especially in device initialisation where an allocation
> > > failure will lead to probe failure as well.  
> > 
> > The fix for this issue should be simple. See the enclosed code. Btw.
> > it probably makes sense to add some code here to avoid starving the
> > stack, as a notify callback could try to create an entity, with,
> > in turn, would call the notify callback again.
> > 
> > I'll run some tests here to double check if it fixes the issue.
> > 
> > ---
> > 
> > [media] media-device: Don't call notify callbacks holding a spinlock
> > 
> > The notify routines may sleep. So, they can't be called in spinlock
> > context. Also, they may want to call other media routines that might
> > be spinning the spinlock, like creating a link.
> > 
> > This fixes the following bug:
> > 
> > [ 1839.510587] BUG: sleeping function called from invalid context at mm/slub.c:1289
> > [ 1839.510881] in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
> > [ 1839.511157] 4 locks held by modprobe/3479:
> > [ 1839.511415]  #0:  (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
> > [ 1839.512381]  #1:  (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
> > [ 1839.512388]  #2:  (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
> > [ 1839.512401]  #3:  (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
> > [ 1839.512412] CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
> > [ 1839.512415] Hardware name:                  /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
> > [ 1839.512417]  0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
> > [ 1839.512422]  ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
> > [ 1839.512427]  ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
> > [ 1839.512432] Call Trace:
> > [ 1839.512436]  [<ffffffff81933901>] dump_stack+0x85/0xc4
> > [ 1839.512440]  [<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
> > [ 1839.512443]  [<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
> > [ 1839.512446]  [<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
> > [ 1839.512451]  [<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
> > [ 1839.512455]  [<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
> > [ 1839.512459]  [<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
> > [ 1839.512463]  [<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
> > [ 1839.512467]  [<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
> > [ 1839.512471]  [<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]
> > 
> > (untested)
> > 
> > Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
> > 
> > diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
> > index 6ba6e8f982fc..fc3c199e5500 100644
> > --- a/drivers/media/media-device.c
> > +++ b/drivers/media/media-device.c
> > @@ -587,14 +587,15 @@ int __must_check media_device_register_entity(struct media_device *mdev,
> >  		media_gobj_create(mdev, MEDIA_GRAPH_PAD,
> >  			       &entity->pads[i].graph_obj);
> >  
> > +	spin_unlock(&mdev->lock);
> > +
> >  	/* invoke entity_notify callbacks */
> >  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> >  		(notify)->notify(entity, notify->notify_data);
> >  	}
> >  
> > -	spin_unlock(&mdev->lock);
> > -
> >  	mutex_lock(&mdev->graph_mutex);
> > +
> >  	if (mdev->entity_internal_idx_max  
> >  	    >= mdev->pm_count_walk.ent_enum.idx_max) {  
> >  		struct media_entity_graph new = { .top = 0 };
> >   
> 


-- 
Thanks,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-15 15:55             ` Mauro Carvalho Chehab
@ 2016-03-16  8:28               ` Sakari Ailus
  -1 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-16  8:28 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Hi Mauro,

On Tue, Mar 15, 2016 at 12:55:35PM -0300, Mauro Carvalho Chehab wrote:
> Em Mon, 14 Mar 2016 14:09:09 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Mauro,
> > 
> > On Mon, Mar 14, 2016 at 08:46:33AM -0300, Mauro Carvalho Chehab wrote:
> > > Em Mon, 14 Mar 2016 12:52:54 +0200
> > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > >   
> > > > Hi Mauro,
> > > > 
> > > > On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:  
> > > > > Em Mon, 14 Mar 2016 09:22:37 +0200
> > > > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > > > >     
> > > > > > Hi Shuah,
> > > > > > 
> > > > > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:    
> > > > > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > > > > media_devnode_create(), and media_add_link() that could get called
> > > > > > > in atomic context to allow callers to pass in the right flags for
> > > > > > > memory allocation.
> > > > > > > 
> > > > > > > tree-wide driver changes for media_*() GFP flags change:
> > > > > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > > > > media_create_intf_link() and media_devnode_create().
> > > > > > > 
> > > > > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>      
> > > > > > 
> > > > > > What's the use case for calling the above functions in an atomic context?
> > > > > >     
> > > > > 
> > > > > ALSA code seems to do a lot of stuff at atomic context. That's what
> > > > > happens on my test machine when au0828 gets probed before
> > > > > snd-usb-audio:
> > > > > 	http://pastebin.com/LEX5LD5K
> > > > > 
> > > > > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > > > > atomic context.    
> > > > 
> > > > usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> > > > cannot be called in atomic context.
> > > > 
> > > > In the above log, what I did notice, though, was that because *we* grab
> > > > mdev->lock spinlock in media_device_register_entity(), we may not sleep
> > > > which is what the notify() callback implementation in au0828 driver does
> > > > (for memory allocation).  
> > > 
> > > True. After looking into the code, the problem is that the notify
> > > callbacks are called with the spinlock hold. I don't see any reason
> > > to do that.  
> > 
> > Notify callbacks, perhaps not, but the list is still protected by the
> > spinlock. It perhaps is not likely that another process would change it but
> > I don't think we can rely on that.
> 
> I can see only 2 risks protected by the lock:
> 
> 1) mdev gets freed while an entity is being created. This is a problem
>    with the current memory protection schema we're using. I guess the
>    only way to fix it is to use kref for mdev/entities/interfaces/links/pads.
>    This change doesn't make it better or worse.
>    Also, I don't think we have such risk with the current devices.
> 
> 2) a notifier may be inserted or removed by another driver, while the
>    loop is running.
> 
> To avoid (2), I see 3 alternatives:
> 
> a) keep the loop as proposed on this patch. As the list is navigated using 
> list_for_each_entry_safe(), I guess[1] it should be safe to remove/add
> new notify callbacks there while the loop is running by some other process. 

list_for_each_entry_safe() does not protect against concurrent access, only
against adding and removing list entries by the same user. List access
serialisation is still needed, whether you use _safe() functions or not.

> 
> [1] It *is* safe if the change were done inside the loop - but I'm not
> 100% sure that it is safe if some other CPU touches the notify list.

Indeed.

> 
> b) Unlock/relock the spinlock every time:
> 
> 	/* previous code that locks mdev->lock spinlock */
> 
>  	/* invoke entity_notify callbacks */
>  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> 		spin_unlock(&mdev->lock);
>  		(notify)->notify(entity, notify->notify_data);
> 		spin_lock(&mdev->lock);
>  	}
>  
> 	spin_unlock(&mdev->lock);
> 
> c) use a separate lock for the notify list -this seems to be an overkill.
> 
> d) Protect it with the graph traversal mutex. That sounds the worse idea,
>    IMHO, as we'll be abusing the lock.

I'd simply replace the spinlock with a mutex here. As we want to get rid of
the graph mutex anyway in the long run, let's not mix the two as they're
well separated now. As long as the mutex users do not sleep (i.e. the
notify() callback) the mutex is about as fast to use as the spinlock.

> 
> > 
> > >   
> > > > Could we instead replace mdev->lock by a mutex?  
> > > 
> > > We changed the code to use a spinlock for a reason: this fixed some
> > > troubles in the past with the code locking (can't remember the problem,
> > > but this was documented at the kernel logs and at the ML). Yet, the code
> > > under the spinlock never sleeps, so this is fine.  
> > 
> > struct media_device.lock was added by this patch:
> > 
> > commit 53e269c102fbaf77e7dc526b1606ad4a48e57200
> > Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Date:   Wed Dec 9 08:40:00 2009 -0300
> > 
> >     [media] media: Entities, pads and links
> > 
> >     As video hardware pipelines become increasingly complex and
> >     configurable, the current hardware description through v4l2 subdevices
> >     reaches its limits. In addition to enumerating and configuring
> >     subdevices, video camera drivers need a way to discover and modify at
> >     runtime how those subdevices are connected. This is done through new
> >     elements called entities, pads and links.
> > 
> > ...
> > 
> >     Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >     Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
> >     Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
> >     Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> > 
> > I think it was always a spinlock, for the reason you stated above as well:
> > it did not need to sleep. But if there is a need to sleep, I think we should
> > consider changing that.
> 
> True, but there were some places that were using the graph_mutex
> instead of the spinlock. 

Hmm. If it's used to serialise access to the same data, it's most likely a
bug.

> 
> > 
> > > 
> > > Yet, in the future, we'll need to do a review of all the locking schema,
> > > in order to better support dynamic graph changes.  
> > 
> > Agreed. I think more fine grained locking should be considered. The media
> > graph mutex will become a bottleneck at some point, especially if we make
> > the media devices system wide at some point.
> 
> Yes. I guess we should protect the memory allocated stuff with a kref,
> and try to use RCS on most places, but we need more discussions and
> more tests to implement a solution that would be reliable even if the
> callers don't behave well.

Yes.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-16  8:28               ` Sakari Ailus
  0 siblings, 0 replies; 26+ messages in thread
From: Sakari Ailus @ 2016-03-16  8:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mauro,

On Tue, Mar 15, 2016 at 12:55:35PM -0300, Mauro Carvalho Chehab wrote:
> Em Mon, 14 Mar 2016 14:09:09 +0200
> Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> 
> > Hi Mauro,
> > 
> > On Mon, Mar 14, 2016 at 08:46:33AM -0300, Mauro Carvalho Chehab wrote:
> > > Em Mon, 14 Mar 2016 12:52:54 +0200
> > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > >   
> > > > Hi Mauro,
> > > > 
> > > > On Mon, Mar 14, 2016 at 07:13:58AM -0300, Mauro Carvalho Chehab wrote:  
> > > > > Em Mon, 14 Mar 2016 09:22:37 +0200
> > > > > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> > > > >     
> > > > > > Hi Shuah,
> > > > > > 
> > > > > > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:    
> > > > > > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > > > > > media_devnode_create(), and media_add_link() that could get called
> > > > > > > in atomic context to allow callers to pass in the right flags for
> > > > > > > memory allocation.
> > > > > > > 
> > > > > > > tree-wide driver changes for media_*() GFP flags change:
> > > > > > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > > > > > media_create_intf_link() and media_devnode_create().
> > > > > > > 
> > > > > > > Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
> > > > > > > Suggested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>      
> > > > > > 
> > > > > > What's the use case for calling the above functions in an atomic context?
> > > > > >     
> > > > > 
> > > > > ALSA code seems to do a lot of stuff at atomic context. That's what
> > > > > happens on my test machine when au0828 gets probed before
> > > > > snd-usb-audio:
> > > > > 	http://pastebin.com/LEX5LD5K
> > > > > 
> > > > > It seems that ALSA USB probe routine (usb_audio_probe) happens in
> > > > > atomic context.    
> > > > 
> > > > usb_audio_probe() grabs a mutex (register_mutex) on its own. It certainly
> > > > cannot be called in atomic context.
> > > > 
> > > > In the above log, what I did notice, though, was that because *we* grab
> > > > mdev->lock spinlock in media_device_register_entity(), we may not sleep
> > > > which is what the notify() callback implementation in au0828 driver does
> > > > (for memory allocation).  
> > > 
> > > True. After looking into the code, the problem is that the notify
> > > callbacks are called with the spinlock hold. I don't see any reason
> > > to do that.  
> > 
> > Notify callbacks, perhaps not, but the list is still protected by the
> > spinlock. It perhaps is not likely that another process would change it but
> > I don't think we can rely on that.
> 
> I can see only 2 risks protected by the lock:
> 
> 1) mdev gets freed while an entity is being created. This is a problem
>    with the current memory protection schema we're using. I guess the
>    only way to fix it is to use kref for mdev/entities/interfaces/links/pads.
>    This change doesn't make it better or worse.
>    Also, I don't think we have such risk with the current devices.
> 
> 2) a notifier may be inserted or removed by another driver, while the
>    loop is running.
> 
> To avoid (2), I see 3 alternatives:
> 
> a) keep the loop as proposed on this patch. As the list is navigated using 
> list_for_each_entry_safe(), I guess[1] it should be safe to remove/add
> new notify callbacks there while the loop is running by some other process. 

list_for_each_entry_safe() does not protect against concurrent access, only
against adding and removing list entries by the same user. List access
serialisation is still needed, whether you use _safe() functions or not.

> 
> [1] It *is* safe if the change were done inside the loop - but I'm not
> 100% sure that it is safe if some other CPU touches the notify list.

Indeed.

> 
> b) Unlock/relock the spinlock every time:
> 
> 	/* previous code that locks mdev->lock spinlock */
> 
>  	/* invoke entity_notify callbacks */
>  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> 		spin_unlock(&mdev->lock);
>  		(notify)->notify(entity, notify->notify_data);
> 		spin_lock(&mdev->lock);
>  	}
>  
> 	spin_unlock(&mdev->lock);
> 
> c) use a separate lock for the notify list -this seems to be an overkill.
> 
> d) Protect it with the graph traversal mutex. That sounds the worse idea,
>    IMHO, as we'll be abusing the lock.

I'd simply replace the spinlock with a mutex here. As we want to get rid of
the graph mutex anyway in the long run, let's not mix the two as they're
well separated now. As long as the mutex users do not sleep (i.e. the
notify() callback) the mutex is about as fast to use as the spinlock.

> 
> > 
> > >   
> > > > Could we instead replace mdev->lock by a mutex?  
> > > 
> > > We changed the code to use a spinlock for a reason: this fixed some
> > > troubles in the past with the code locking (can't remember the problem,
> > > but this was documented at the kernel logs and at the ML). Yet, the code
> > > under the spinlock never sleeps, so this is fine.  
> > 
> > struct media_device.lock was added by this patch:
> > 
> > commit 53e269c102fbaf77e7dc526b1606ad4a48e57200
> > Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Date:   Wed Dec 9 08:40:00 2009 -0300
> > 
> >     [media] media: Entities, pads and links
> > 
> >     As video hardware pipelines become increasingly complex and
> >     configurable, the current hardware description through v4l2 subdevices
> >     reaches its limits. In addition to enumerating and configuring
> >     subdevices, video camera drivers need a way to discover and modify at
> >     runtime how those subdevices are connected. This is done through new
> >     elements called entities, pads and links.
> > 
> > ...
> > 
> >     Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >     Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
> >     Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
> >     Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> > 
> > I think it was always a spinlock, for the reason you stated above as well:
> > it did not need to sleep. But if there is a need to sleep, I think we should
> > consider changing that.
> 
> True, but there were some places that were using the graph_mutex
> instead of the spinlock. 

Hmm. If it's used to serialise access to the same data, it's most likely a
bug.

> 
> > 
> > > 
> > > Yet, in the future, we'll need to do a review of all the locking schema,
> > > in order to better support dynamic graph changes.  
> > 
> > Agreed. I think more fine grained locking should be considered. The media
> > graph mutex will become a bottleneck at some point, especially if we make
> > the media devices system wide at some point.
> 
> Yes. I guess we should protect the memory allocated stuff with a kref,
> and try to use RCS on most places, but we need more discussions and
> more tests to implement a solution that would be reliable even if the
> callers don't behave well.

Yes.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context
  2016-03-16  8:28               ` Sakari Ailus
@ 2016-03-16 12:02                 ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-16 12:02 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Shuah Khan, kyungmin.park, a.hajda, s.nawrocki, kgene,
	k.kozlowski, laurent.pinchart, hyun.kwon, soren.brinkmann,
	gregkh, perex, tiwai, hans.verkuil, lixiubo, javier,
	g.liakhovetski, chehabrafael, crope, tommi.franttila,
	dan.carpenter, prabhakar.csengg, hamohammed.sa, der.herr,
	navyasri.tech, Julia.Lawall, amitoj1606, linux-media,
	linux-kernel, linux-arm-kernel, linux-samsung-soc,
	linux-renesas-soc, devel, alsa-devel

Em Wed, 16 Mar 2016 10:28:35 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> On Tue, Mar 15, 2016 at 12:55:35PM -0300, Mauro Carvalho Chehab wrote:
> > Em Mon, 14 Mar 2016 14:09:09 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Mauro,
> > > 

...

> > > Notify callbacks, perhaps not, but the list is still protected by the
> > > spinlock. It perhaps is not likely that another process would change it but
> > > I don't think we can rely on that.  
> > 
> > I can see only 2 risks protected by the lock:
> > 
> > 1) mdev gets freed while an entity is being created. This is a problem
> >    with the current memory protection schema we're using. I guess the
> >    only way to fix it is to use kref for mdev/entities/interfaces/links/pads.
> >    This change doesn't make it better or worse.
> >    Also, I don't think we have such risk with the current devices.
> > 
> > 2) a notifier may be inserted or removed by another driver, while the
> >    loop is running.
> > 
> > To avoid (2), I see 3 alternatives:
> > 
> > a) keep the loop as proposed on this patch. As the list is navigated using 
> > list_for_each_entry_safe(), I guess[1] it should be safe to remove/add
> > new notify callbacks there while the loop is running by some other process.   
> 
> list_for_each_entry_safe() does not protect against concurrent access, only
> against adding and removing list entries by the same user. List access
> serialisation is still needed, whether you use _safe() functions or not.
> 
> > 
> > [1] It *is* safe if the change were done inside the loop - but I'm not
> > 100% sure that it is safe if some other CPU touches the notify list.  
> 
> Indeed.
> 
> > 
> > b) Unlock/relock the spinlock every time:
> > 
> > 	/* previous code that locks mdev->lock spinlock */
> > 
> >  	/* invoke entity_notify callbacks */
> >  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> > 		spin_unlock(&mdev->lock);
> >  		(notify)->notify(entity, notify->notify_data);
> > 		spin_lock(&mdev->lock);
> >  	}
> >  
> > 	spin_unlock(&mdev->lock);
> > 
> > c) use a separate lock for the notify list -this seems to be an overkill.
> > 
> > d) Protect it with the graph traversal mutex. That sounds the worse idea,
> >    IMHO, as we'll be abusing the lock.  
> 
> I'd simply replace the spinlock with a mutex here. As we want to get rid of
> the graph mutex anyway in the long run, let's not mix the two as they're
> well separated now. As long as the mutex users do not sleep (i.e. the
> notify() callback) the mutex is about as fast to use as the spinlock.

It could work. I added such patch on an experimental branch, where
I'm addressing a few troubles with au0828 unbind logic:
	https://git.linuxtv.org/mchehab/experimental.git/log/?h=au0828-unbind-fixes

The patch itself is at:
	https://git.linuxtv.org/mchehab/experimental.git/commit/?h=au0828-unbind-fixes&id=dba4d41bdfa6bb8dc51cb0f692102919b2b7c8b4

At least for au0828, it seems to work fine.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] media: add GFP flag to media_*() that could get called in atomic context
@ 2016-03-16 12:02                 ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 26+ messages in thread
From: Mauro Carvalho Chehab @ 2016-03-16 12:02 UTC (permalink / raw)
  To: linux-arm-kernel

Em Wed, 16 Mar 2016 10:28:35 +0200
Sakari Ailus <sakari.ailus@iki.fi> escreveu:

> Hi Mauro,
> 
> On Tue, Mar 15, 2016 at 12:55:35PM -0300, Mauro Carvalho Chehab wrote:
> > Em Mon, 14 Mar 2016 14:09:09 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> escreveu:
> >   
> > > Hi Mauro,
> > > 

...

> > > Notify callbacks, perhaps not, but the list is still protected by the
> > > spinlock. It perhaps is not likely that another process would change it but
> > > I don't think we can rely on that.  
> > 
> > I can see only 2 risks protected by the lock:
> > 
> > 1) mdev gets freed while an entity is being created. This is a problem
> >    with the current memory protection schema we're using. I guess the
> >    only way to fix it is to use kref for mdev/entities/interfaces/links/pads.
> >    This change doesn't make it better or worse.
> >    Also, I don't think we have such risk with the current devices.
> > 
> > 2) a notifier may be inserted or removed by another driver, while the
> >    loop is running.
> > 
> > To avoid (2), I see 3 alternatives:
> > 
> > a) keep the loop as proposed on this patch. As the list is navigated using 
> > list_for_each_entry_safe(), I guess[1] it should be safe to remove/add
> > new notify callbacks there while the loop is running by some other process.   
> 
> list_for_each_entry_safe() does not protect against concurrent access, only
> against adding and removing list entries by the same user. List access
> serialisation is still needed, whether you use _safe() functions or not.
> 
> > 
> > [1] It *is* safe if the change were done inside the loop - but I'm not
> > 100% sure that it is safe if some other CPU touches the notify list.  
> 
> Indeed.
> 
> > 
> > b) Unlock/relock the spinlock every time:
> > 
> > 	/* previous code that locks mdev->lock spinlock */
> > 
> >  	/* invoke entity_notify callbacks */
> >  	list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
> > 		spin_unlock(&mdev->lock);
> >  		(notify)->notify(entity, notify->notify_data);
> > 		spin_lock(&mdev->lock);
> >  	}
> >  
> > 	spin_unlock(&mdev->lock);
> > 
> > c) use a separate lock for the notify list -this seems to be an overkill.
> > 
> > d) Protect it with the graph traversal mutex. That sounds the worse idea,
> >    IMHO, as we'll be abusing the lock.  
> 
> I'd simply replace the spinlock with a mutex here. As we want to get rid of
> the graph mutex anyway in the long run, let's not mix the two as they're
> well separated now. As long as the mutex users do not sleep (i.e. the
> notify() callback) the mutex is about as fast to use as the spinlock.

It could work. I added such patch on an experimental branch, where
I'm addressing a few troubles with au0828 unbind logic:
	https://git.linuxtv.org/mchehab/experimental.git/log/?h=au0828-unbind-fixes

The patch itself is at:
	https://git.linuxtv.org/mchehab/experimental.git/commit/?h=au0828-unbind-fixes&id=dba4d41bdfa6bb8dc51cb0f692102919b2b7c8b4

At least for au0828, it seems to work fine.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2016-03-16 12:02 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-13  1:48 [PATCH] media: add GFP flag to media_*() that could get called in atomic context Shuah Khan
2016-03-13  1:48 ` Shuah Khan
2016-03-13  8:30 ` Nicholas Mc Guire
2016-03-13  8:30   ` Nicholas Mc Guire
2016-03-13  8:30   ` Nicholas Mc Guire
2016-03-13 11:50 ` Mauro Carvalho Chehab
2016-03-13 11:50   ` Mauro Carvalho Chehab
2016-03-14  7:22 ` Sakari Ailus
2016-03-14  7:22   ` Sakari Ailus
2016-03-14 10:13   ` Mauro Carvalho Chehab
2016-03-14 10:13     ` Mauro Carvalho Chehab
2016-03-14 10:33     ` Takashi Iwai
2016-03-14 10:33       ` Takashi Iwai
2016-03-14 10:33       ` Takashi Iwai
2016-03-14 10:52     ` Sakari Ailus
2016-03-14 10:52       ` Sakari Ailus
2016-03-14 11:46       ` Mauro Carvalho Chehab
2016-03-14 11:46         ` Mauro Carvalho Chehab
2016-03-14 12:09         ` Sakari Ailus
2016-03-14 12:09           ` Sakari Ailus
2016-03-15 15:55           ` Mauro Carvalho Chehab
2016-03-15 15:55             ` Mauro Carvalho Chehab
2016-03-16  8:28             ` Sakari Ailus
2016-03-16  8:28               ` Sakari Ailus
2016-03-16 12:02               ` Mauro Carvalho Chehab
2016-03-16 12:02                 ` Mauro Carvalho Chehab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.