···116116 return ret;117117}118118119119+struct platform_object {120120+ struct platform_device pdev;121121+ char name[1];122122+};123123+119124/**120120- * platform_device_register - add a platform-level device125125+ * platform_device_put126126+ * @pdev: platform device to free127127+ *128128+ * Free all memory associated with a platform device. This function129129+ * must _only_ be externally called in error cases. All other usage130130+ * is a bug.131131+ */132132+void platform_device_put(struct platform_device *pdev)133133+{134134+ if (pdev)135135+ put_device(&pdev->dev);136136+}137137+EXPORT_SYMBOL_GPL(platform_device_put);138138+139139+static void platform_device_release(struct device *dev)140140+{141141+ struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev);142142+143143+ kfree(pa->pdev.dev.platform_data);144144+ kfree(pa->pdev.resource);145145+ kfree(pa);146146+}147147+148148+/**149149+ * platform_device_alloc150150+ * @name: base name of the device we're adding151151+ * @id: instance id152152+ *153153+ * Create a platform device object which can have other objects attached154154+ * to it, and which will have attached objects freed when it is released.155155+ */156156+struct platform_device *platform_device_alloc(const char *name, unsigned int id)157157+{158158+ struct platform_object *pa;159159+160160+ pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);161161+ if (pa) {162162+ strcpy(pa->name, name);163163+ pa->pdev.name = pa->name;164164+ pa->pdev.id = id;165165+ device_initialize(&pa->pdev.dev);166166+ pa->pdev.dev.release = platform_device_release;167167+ }168168+169169+ return pa ? &pa->pdev : NULL; 170170+}171171+EXPORT_SYMBOL_GPL(platform_device_alloc);172172+173173+/**174174+ * platform_device_add_resources175175+ * @pdev: platform device allocated by platform_device_alloc to add resources to176176+ * @res: set of resources that needs to be allocated for the device177177+ * @num: number of resources178178+ *179179+ * Add a copy of the resources to the platform device. The memory180180+ * associated with the resources will be freed when the platform181181+ * device is released.182182+ */183183+int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num)184184+{185185+ struct resource *r;186186+187187+ r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL);188188+ if (r) {189189+ memcpy(r, res, sizeof(struct resource) * num);190190+ pdev->resource = r;191191+ pdev->num_resources = num;192192+ }193193+ return r ? 0 : -ENOMEM;194194+}195195+EXPORT_SYMBOL_GPL(platform_device_add_resources);196196+197197+/**198198+ * platform_device_add_data199199+ * @pdev: platform device allocated by platform_device_alloc to add resources to200200+ * @data: platform specific data for this platform device201201+ * @size: size of platform specific data202202+ *203203+ * Add a copy of platform specific data to the platform device's platform_data204204+ * pointer. The memory associated with the platform data will be freed205205+ * when the platform device is released.206206+ */207207+int platform_device_add_data(struct platform_device *pdev, void *data, size_t size)208208+{209209+ void *d;210210+211211+ d = kmalloc(size, GFP_KERNEL);212212+ if (d) {213213+ memcpy(d, data, size);214214+ pdev->dev.platform_data = d;215215+ }216216+ return d ? 0 : -ENOMEM;217217+}218218+EXPORT_SYMBOL_GPL(platform_device_add_data);219219+220220+/**221221+ * platform_device_add - add a platform device to device hierarchy121222 * @pdev: platform device we're adding122223 *224224+ * This is part 2 of platform_device_register(), though may be called225225+ * separately _iff_ pdev was allocated by platform_device_alloc().123226 */124124-int platform_device_register(struct platform_device * pdev)227227+int platform_device_add(struct platform_device *pdev)125228{126229 int i, ret = 0;127230···277174 release_resource(&pdev->resource[i]);278175 return ret;279176}177177+EXPORT_SYMBOL_GPL(platform_device_add);178178+179179+/**180180+ * platform_device_register - add a platform-level device181181+ * @pdev: platform device we're adding182182+ *183183+ */184184+int platform_device_register(struct platform_device * pdev)185185+{186186+ device_initialize(&pdev->dev);187187+ return platform_device_add(pdev);188188+}280189281190/**282191 * platform_device_unregister - remove a platform-level device···312197 }313198}314199315315-struct platform_object {316316- struct platform_device pdev;317317- struct resource resources[0];318318-};319319-320320-static void platform_device_release_simple(struct device *dev)321321-{322322- struct platform_device *pdev = to_platform_device(dev);323323-324324- kfree(container_of(pdev, struct platform_object, pdev));325325-}326326-327200/**328201 * platform_device_register_simple329202 * @name: base name of the device we're adding···328225struct platform_device *platform_device_register_simple(char *name, unsigned int id,329226 struct resource *res, unsigned int num)330227{331331- struct platform_object *pobj;228228+ struct platform_device *pdev;332229 int retval;333230334334- pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL);335335- if (!pobj) {231231+ pdev = platform_device_alloc(name, id);232232+ if (!pdev) {336233 retval = -ENOMEM;337234 goto error;338235 }339236340340- pobj->pdev.name = name;341341- pobj->pdev.id = id;342342- pobj->pdev.dev.release = platform_device_release_simple;343343-344237 if (num) {345345- memcpy(pobj->resources, res, sizeof(struct resource) * num);346346- pobj->pdev.resource = pobj->resources;347347- pobj->pdev.num_resources = num;238238+ retval = platform_device_add_resources(pdev, res, num);239239+ if (retval)240240+ goto error;348241 }349242350350- retval = platform_device_register(&pobj->pdev);243243+ retval = platform_device_add(pdev);351244 if (retval)352245 goto error;353246354354- return &pobj->pdev;247247+ return pdev;355248356249error:357357- kfree(pobj);250250+ platform_device_put(pdev);358251 return ERR_PTR(retval);359252}360253
+7-17
drivers/net/depca.c
···14701470** ISA bus I/O device probe14711471*/1472147214731473-static void depca_platform_release (struct device *device)14741474-{14751475- struct platform_device *pldev;14761476-14771477- /* free device */14781478- pldev = to_platform_device (device);14791479- kfree (pldev);14801480-}14811481-14821473static void __init depca_platform_probe (void)14831474{14841475 int i;···14821491 * line, use it (if valid) */14831492 if (io && io != depca_io_ports[i].iobase)14841493 continue;14851485-14861486- if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL)))14941494+14951495+ pldev = platform_device_alloc(depca_string, i);14961496+ if (!pldev)14871497 continue;1488149814891489- memset (pldev, 0, sizeof (*pldev));14901490- pldev->name = depca_string;14911491- pldev->id = i;14921499 pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;14931493- pldev->dev.release = depca_platform_release;14941500 depca_io_ports[i].device = pldev;1495150114961496- if (platform_device_register (pldev)) {14971497- kfree (pldev);15021502+ if (platform_device_add(pldev)) {15031503+ platform_device_put(pldev);14981504 depca_io_ports[i].device = NULL;14991505 continue;15001506 }···15031515 * allocated structure */1504151615051517 depca_io_ports[i].device = NULL;15181518+ pldev->dev.platform_data = NULL;15061519 platform_device_unregister (pldev);15071520 }15081521 }···2101211221022113 for (i = 0; depca_io_ports[i].iobase; i++) {21032114 if (depca_io_ports[i].device) {21152115+ depca_io_ports[i].device->dev.platform_data = NULL;21042116 platform_device_unregister (depca_io_ports[i].device);21052117 depca_io_ports[i].device = NULL;21062118 }