brintos

brintos / linux-shallow public Read only

0
0
Text · 22.2 KiB · f98f5a2 Raw
981 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2015-2017 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>4 */5#include <linux/kernel.h>6#include <linux/device.h>7#include <linux/module.h>8#include <linux/slab.h>9#include <linux/sysfs.h>10 11#include "siox.h"12 13/*14 * The lowest bit in the SIOX status word signals if the in-device watchdog is15 * ok. If the bit is set, the device is functional.16 *17 * On writing the watchdog timer is reset when this bit toggles.18 */19#define SIOX_STATUS_WDG			0x0120 21/*22 * Bits 1 to 3 of the status word read as the bitwise negation of what was23 * clocked in before. The value clocked in is changed in each cycle and so24 * allows to detect transmit/receive problems.25 */26#define SIOX_STATUS_COUNTER		0x0e27 28/*29 * Each Siox-Device has a 4 bit type number that is neither 0 nor 15. This is30 * available in the upper nibble of the read status.31 *32 * On write these bits are DC.33 */34#define SIOX_STATUS_TYPE		0xf035 36#define CREATE_TRACE_POINTS37#include <trace/events/siox.h>38 39static bool siox_is_registered;40 41static void siox_master_lock(struct siox_master *smaster)42{43	mutex_lock(&smaster->lock);44}45 46static void siox_master_unlock(struct siox_master *smaster)47{48	mutex_unlock(&smaster->lock);49}50 51static inline u8 siox_status_clean(u8 status_read, u8 status_written)52{53	/*54	 * bits 3:1 of status sample the respective bit in the status55	 * byte written in the previous cycle but inverted. So if you wrote the56	 * status word as 0xa before (counter = 0b101), it is expected to get57	 * back the counter bits as 0b010.58	 *59	 * So given the last status written this function toggles the there60	 * unset counter bits in the read value such that the counter bits in61	 * the return value are all zero iff the bits were read as expected to62	 * simplify error detection.63	 */64 65	return status_read ^ (~status_written & 0xe);66}67 68static bool siox_device_counter_error(struct siox_device *sdevice,69				      u8 status_clean)70{71	return (status_clean & SIOX_STATUS_COUNTER) != 0;72}73 74static bool siox_device_type_error(struct siox_device *sdevice, u8 status_clean)75{76	u8 statustype = (status_clean & SIOX_STATUS_TYPE) >> 4;77 78	/*79	 * If the device knows which value the type bits should have, check80	 * against this value otherwise just rule out the invalid values 0b000081	 * and 0b1111.82	 */83	if (sdevice->statustype) {84		if (statustype != sdevice->statustype)85			return true;86	} else {87		switch (statustype) {88		case 0:89		case 0xf:90			return true;91		}92	}93 94	return false;95}96 97static bool siox_device_wdg_error(struct siox_device *sdevice, u8 status_clean)98{99	return (status_clean & SIOX_STATUS_WDG) == 0;100}101 102/*103 * If there is a type or counter error the device is called "unsynced".104 */105bool siox_device_synced(struct siox_device *sdevice)106{107	if (siox_device_type_error(sdevice, sdevice->status_read_clean))108		return false;109 110	return !siox_device_counter_error(sdevice, sdevice->status_read_clean);111 112}113EXPORT_SYMBOL_GPL(siox_device_synced);114 115/*116 * A device is called "connected" if it is synced and the watchdog is not117 * asserted.118 */119bool siox_device_connected(struct siox_device *sdevice)120{121	if (!siox_device_synced(sdevice))122		return false;123 124	return !siox_device_wdg_error(sdevice, sdevice->status_read_clean);125}126EXPORT_SYMBOL_GPL(siox_device_connected);127 128static void siox_poll(struct siox_master *smaster)129{130	struct siox_device *sdevice;131	size_t i = smaster->setbuf_len;132	unsigned int devno = 0;133	int unsync_error = 0;134 135	smaster->last_poll = jiffies;136 137	/*138	 * The counter bits change in each second cycle, the watchdog bit139	 * toggles each time.140	 * The counter bits hold values from [0, 6]. 7 would be possible141	 * theoretically but the protocol designer considered that a bad idea142	 * for reasons unknown today. (Maybe that's because then the status read143	 * back has only zeros in the counter bits then which might be confused144	 * with a stuck-at-0 error. But for the same reason (with s/0/1/) 0145	 * could be skipped.)146	 */147	if (++smaster->status > 0x0d)148		smaster->status = 0;149 150	memset(smaster->buf, 0, smaster->setbuf_len);151 152	/* prepare data pushed out to devices in buf[0..setbuf_len) */153	list_for_each_entry(sdevice, &smaster->devices, node) {154		struct siox_driver *sdriver =155			to_siox_driver(sdevice->dev.driver);156		sdevice->status_written = smaster->status;157 158		i -= sdevice->inbytes;159 160		/*161		 * If the device or a previous one is unsynced, don't pet the162		 * watchdog. This is done to ensure that the device is kept in163		 * reset when something is wrong.164		 */165		if (!siox_device_synced(sdevice))166			unsync_error = 1;167 168		if (sdriver && !unsync_error)169			sdriver->set_data(sdevice, sdevice->status_written,170					  &smaster->buf[i + 1]);171		else172			/*173			 * Don't trigger watchdog if there is no driver or a174			 * sync problem175			 */176			sdevice->status_written &= ~SIOX_STATUS_WDG;177 178		smaster->buf[i] = sdevice->status_written;179 180		trace_siox_set_data(smaster, sdevice, devno, i);181 182		devno++;183	}184 185	smaster->pushpull(smaster, smaster->setbuf_len, smaster->buf,186			  smaster->getbuf_len,187			  smaster->buf + smaster->setbuf_len);188 189	unsync_error = 0;190 191	/* interpret data pulled in from devices in buf[setbuf_len..] */192	devno = 0;193	i = smaster->setbuf_len;194	list_for_each_entry(sdevice, &smaster->devices, node) {195		struct siox_driver *sdriver =196			to_siox_driver(sdevice->dev.driver);197		u8 status = smaster->buf[i + sdevice->outbytes - 1];198		u8 status_clean;199		u8 prev_status_clean = sdevice->status_read_clean;200		bool synced = true;201		bool connected = true;202 203		if (!siox_device_synced(sdevice))204			unsync_error = 1;205 206		/*207		 * If the watchdog bit wasn't toggled in this cycle, report the208		 * watchdog as active to give a consistent view for drivers and209		 * sysfs consumers.210		 */211		if (!sdriver || unsync_error)212			status &= ~SIOX_STATUS_WDG;213 214		status_clean =215			siox_status_clean(status,216					  sdevice->status_written_lastcycle);217 218		/* Check counter and type bits */219		if (siox_device_counter_error(sdevice, status_clean) ||220		    siox_device_type_error(sdevice, status_clean)) {221			bool prev_error;222 223			synced = false;224 225			/* only report a new error if the last cycle was ok */226			prev_error =227				siox_device_counter_error(sdevice,228							  prev_status_clean) ||229				siox_device_type_error(sdevice,230						       prev_status_clean);231 232			if (!prev_error) {233				sdevice->status_errors++;234				sysfs_notify_dirent(sdevice->status_errors_kn);235			}236		}237 238		/* If the device is unsynced report the watchdog as active */239		if (!synced) {240			status &= ~SIOX_STATUS_WDG;241			status_clean &= ~SIOX_STATUS_WDG;242		}243 244		if (siox_device_wdg_error(sdevice, status_clean))245			connected = false;246 247		/* The watchdog state changed just now */248		if ((status_clean ^ prev_status_clean) & SIOX_STATUS_WDG) {249			sysfs_notify_dirent(sdevice->watchdog_kn);250 251			if (siox_device_wdg_error(sdevice, status_clean)) {252				struct kernfs_node *wd_errs =253					sdevice->watchdog_errors_kn;254 255				sdevice->watchdog_errors++;256				sysfs_notify_dirent(wd_errs);257			}258		}259 260		if (connected != sdevice->connected)261			sysfs_notify_dirent(sdevice->connected_kn);262 263		sdevice->status_read_clean = status_clean;264		sdevice->status_written_lastcycle = sdevice->status_written;265		sdevice->connected = connected;266 267		trace_siox_get_data(smaster, sdevice, devno, status_clean, i);268 269		/* only give data read to driver if the device is connected */270		if (sdriver && connected)271			sdriver->get_data(sdevice, &smaster->buf[i]);272 273		devno++;274		i += sdevice->outbytes;275	}276}277 278static int siox_poll_thread(void *data)279{280	struct siox_master *smaster = data;281	signed long timeout = 0;282 283	get_device(&smaster->dev);284 285	for (;;) {286		if (kthread_should_stop()) {287			put_device(&smaster->dev);288			return 0;289		}290 291		siox_master_lock(smaster);292 293		if (smaster->active) {294			unsigned long next_poll =295				smaster->last_poll + smaster->poll_interval;296			if (time_is_before_eq_jiffies(next_poll))297				siox_poll(smaster);298 299			timeout = smaster->poll_interval -300				(jiffies - smaster->last_poll);301		} else {302			timeout = MAX_SCHEDULE_TIMEOUT;303		}304 305		/*306		 * Set the task to idle while holding the lock. This makes sure307		 * that we don't sleep too long when the bus is reenabled before308		 * schedule_timeout is reached.309		 */310		if (timeout > 0)311			set_current_state(TASK_IDLE);312 313		siox_master_unlock(smaster);314 315		if (timeout > 0)316			schedule_timeout(timeout);317 318		/*319		 * I'm not clear if/why it is important to set the state to320		 * RUNNING again, but it fixes a "do not call blocking ops when321		 * !TASK_RUNNING;"-warning.322		 */323		set_current_state(TASK_RUNNING);324	}325}326 327static int __siox_start(struct siox_master *smaster)328{329	if (!(smaster->setbuf_len + smaster->getbuf_len))330		return -ENODEV;331 332	if (!smaster->buf)333		return -ENOMEM;334 335	if (smaster->active)336		return 0;337 338	smaster->active = 1;339	wake_up_process(smaster->poll_thread);340 341	return 1;342}343 344static int siox_start(struct siox_master *smaster)345{346	int ret;347 348	siox_master_lock(smaster);349	ret = __siox_start(smaster);350	siox_master_unlock(smaster);351 352	return ret;353}354 355static int __siox_stop(struct siox_master *smaster)356{357	if (smaster->active) {358		struct siox_device *sdevice;359 360		smaster->active = 0;361 362		list_for_each_entry(sdevice, &smaster->devices, node) {363			if (sdevice->connected)364				sysfs_notify_dirent(sdevice->connected_kn);365			sdevice->connected = false;366		}367 368		return 1;369	}370	return 0;371}372 373static int siox_stop(struct siox_master *smaster)374{375	int ret;376 377	siox_master_lock(smaster);378	ret = __siox_stop(smaster);379	siox_master_unlock(smaster);380 381	return ret;382}383 384static ssize_t type_show(struct device *dev,385			 struct device_attribute *attr, char *buf)386{387	struct siox_device *sdev = to_siox_device(dev);388 389	return sprintf(buf, "%s\n", sdev->type);390}391 392static DEVICE_ATTR_RO(type);393 394static ssize_t inbytes_show(struct device *dev,395			    struct device_attribute *attr, char *buf)396{397	struct siox_device *sdev = to_siox_device(dev);398 399	return sprintf(buf, "%zu\n", sdev->inbytes);400}401 402static DEVICE_ATTR_RO(inbytes);403 404static ssize_t outbytes_show(struct device *dev,405			     struct device_attribute *attr, char *buf)406{407	struct siox_device *sdev = to_siox_device(dev);408 409	return sprintf(buf, "%zu\n", sdev->outbytes);410}411 412static DEVICE_ATTR_RO(outbytes);413 414static ssize_t status_errors_show(struct device *dev,415				  struct device_attribute *attr, char *buf)416{417	struct siox_device *sdev = to_siox_device(dev);418	unsigned int status_errors;419 420	siox_master_lock(sdev->smaster);421 422	status_errors = sdev->status_errors;423 424	siox_master_unlock(sdev->smaster);425 426	return sprintf(buf, "%u\n", status_errors);427}428 429static DEVICE_ATTR_RO(status_errors);430 431static ssize_t connected_show(struct device *dev,432			      struct device_attribute *attr, char *buf)433{434	struct siox_device *sdev = to_siox_device(dev);435	bool connected;436 437	siox_master_lock(sdev->smaster);438 439	connected = sdev->connected;440 441	siox_master_unlock(sdev->smaster);442 443	return sprintf(buf, "%u\n", connected);444}445 446static DEVICE_ATTR_RO(connected);447 448static ssize_t watchdog_show(struct device *dev,449			     struct device_attribute *attr, char *buf)450{451	struct siox_device *sdev = to_siox_device(dev);452	u8 status;453 454	siox_master_lock(sdev->smaster);455 456	status = sdev->status_read_clean;457 458	siox_master_unlock(sdev->smaster);459 460	return sprintf(buf, "%d\n", status & SIOX_STATUS_WDG);461}462 463static DEVICE_ATTR_RO(watchdog);464 465static ssize_t watchdog_errors_show(struct device *dev,466				    struct device_attribute *attr, char *buf)467{468	struct siox_device *sdev = to_siox_device(dev);469	unsigned int watchdog_errors;470 471	siox_master_lock(sdev->smaster);472 473	watchdog_errors = sdev->watchdog_errors;474 475	siox_master_unlock(sdev->smaster);476 477	return sprintf(buf, "%u\n", watchdog_errors);478}479 480static DEVICE_ATTR_RO(watchdog_errors);481 482static struct attribute *siox_device_attrs[] = {483	&dev_attr_type.attr,484	&dev_attr_inbytes.attr,485	&dev_attr_outbytes.attr,486	&dev_attr_status_errors.attr,487	&dev_attr_connected.attr,488	&dev_attr_watchdog.attr,489	&dev_attr_watchdog_errors.attr,490	NULL491};492ATTRIBUTE_GROUPS(siox_device);493 494static void siox_device_release(struct device *dev)495{496	struct siox_device *sdevice = to_siox_device(dev);497 498	kfree(sdevice);499}500 501static const struct device_type siox_device_type = {502	.groups = siox_device_groups,503	.release = siox_device_release,504};505 506static int siox_match(struct device *dev, const struct device_driver *drv)507{508	if (dev->type != &siox_device_type)509		return 0;510 511	/* up to now there is only a single driver so keeping this simple */512	return 1;513}514 515static int siox_probe(struct device *dev)516{517	struct siox_driver *sdriver = to_siox_driver(dev->driver);518	struct siox_device *sdevice = to_siox_device(dev);519 520	return sdriver->probe(sdevice);521}522 523static void siox_remove(struct device *dev)524{525	struct siox_driver *sdriver =526		container_of(dev->driver, struct siox_driver, driver);527	struct siox_device *sdevice = to_siox_device(dev);528 529	if (sdriver->remove)530		sdriver->remove(sdevice);531}532 533static void siox_shutdown(struct device *dev)534{535	struct siox_device *sdevice = to_siox_device(dev);536	struct siox_driver *sdriver;537 538	if (!dev->driver)539		return;540 541	sdriver = container_of(dev->driver, struct siox_driver, driver);542	if (sdriver->shutdown)543		sdriver->shutdown(sdevice);544}545 546static const struct bus_type siox_bus_type = {547	.name = "siox",548	.match = siox_match,549	.probe = siox_probe,550	.remove = siox_remove,551	.shutdown = siox_shutdown,552};553 554static ssize_t active_show(struct device *dev,555			   struct device_attribute *attr, char *buf)556{557	struct siox_master *smaster = to_siox_master(dev);558 559	return sprintf(buf, "%d\n", smaster->active);560}561 562static ssize_t active_store(struct device *dev,563			    struct device_attribute *attr,564			    const char *buf, size_t count)565{566	struct siox_master *smaster = to_siox_master(dev);567	int ret;568	int active;569 570	ret = kstrtoint(buf, 0, &active);571	if (ret < 0)572		return ret;573 574	if (active)575		ret = siox_start(smaster);576	else577		ret = siox_stop(smaster);578 579	if (ret < 0)580		return ret;581 582	return count;583}584 585static DEVICE_ATTR_RW(active);586 587static struct siox_device *siox_device_add(struct siox_master *smaster,588					   const char *type, size_t inbytes,589					   size_t outbytes, u8 statustype);590 591static ssize_t device_add_store(struct device *dev,592				struct device_attribute *attr,593				const char *buf, size_t count)594{595	struct siox_master *smaster = to_siox_master(dev);596	int ret;597	char type[20] = "";598	size_t inbytes = 0, outbytes = 0;599	u8 statustype = 0;600 601	ret = sscanf(buf, "%19s %zu %zu %hhu", type, &inbytes,602		     &outbytes, &statustype);603	if (ret != 3 && ret != 4)604		return -EINVAL;605 606	if (strcmp(type, "siox-12x8") || inbytes != 2 || outbytes != 4)607		return -EINVAL;608 609	siox_device_add(smaster, "siox-12x8", inbytes, outbytes, statustype);610 611	return count;612}613 614static DEVICE_ATTR_WO(device_add);615 616static void siox_device_remove(struct siox_master *smaster);617 618static ssize_t device_remove_store(struct device *dev,619				   struct device_attribute *attr,620				   const char *buf, size_t count)621{622	struct siox_master *smaster = to_siox_master(dev);623 624	/* XXX? require to write <type> <inbytes> <outbytes> */625	siox_device_remove(smaster);626 627	return count;628}629 630static DEVICE_ATTR_WO(device_remove);631 632static ssize_t poll_interval_ns_show(struct device *dev,633				     struct device_attribute *attr, char *buf)634{635	struct siox_master *smaster = to_siox_master(dev);636 637	return sprintf(buf, "%lld\n", jiffies_to_nsecs(smaster->poll_interval));638}639 640static ssize_t poll_interval_ns_store(struct device *dev,641				      struct device_attribute *attr,642				      const char *buf, size_t count)643{644	struct siox_master *smaster = to_siox_master(dev);645	int ret;646	u64 val;647 648	ret = kstrtou64(buf, 0, &val);649	if (ret < 0)650		return ret;651 652	siox_master_lock(smaster);653 654	smaster->poll_interval = nsecs_to_jiffies(val);655 656	siox_master_unlock(smaster);657 658	return count;659}660 661static DEVICE_ATTR_RW(poll_interval_ns);662 663static struct attribute *siox_master_attrs[] = {664	&dev_attr_active.attr,665	&dev_attr_device_add.attr,666	&dev_attr_device_remove.attr,667	&dev_attr_poll_interval_ns.attr,668	NULL669};670ATTRIBUTE_GROUPS(siox_master);671 672static void siox_master_release(struct device *dev)673{674	struct siox_master *smaster = to_siox_master(dev);675 676	kfree(smaster);677}678 679static const struct device_type siox_master_type = {680	.groups = siox_master_groups,681	.release = siox_master_release,682};683 684struct siox_master *siox_master_alloc(struct device *dev,685				      size_t size)686{687	struct siox_master *smaster;688 689	if (!dev)690		return NULL;691 692	smaster = kzalloc(sizeof(*smaster) + size, GFP_KERNEL);693	if (!smaster)694		return NULL;695 696	device_initialize(&smaster->dev);697 698	smaster->busno = -1;699	smaster->dev.bus = &siox_bus_type;700	smaster->dev.type = &siox_master_type;701	smaster->dev.parent = dev;702	smaster->poll_interval = DIV_ROUND_UP(HZ, 40);703 704	dev_set_drvdata(&smaster->dev, &smaster[1]);705 706	return smaster;707}708EXPORT_SYMBOL_GPL(siox_master_alloc);709 710static void devm_siox_master_put(void *data)711{712	struct siox_master *smaster = data;713 714	siox_master_put(smaster);715}716 717struct siox_master *devm_siox_master_alloc(struct device *dev,718					   size_t size)719{720	struct siox_master *smaster;721	int ret;722 723	smaster = siox_master_alloc(dev, size);724	if (!smaster)725		return NULL;726 727	ret = devm_add_action_or_reset(dev, devm_siox_master_put, smaster);728	if (ret)729		return NULL;730 731	return smaster;732}733EXPORT_SYMBOL_GPL(devm_siox_master_alloc);734 735int siox_master_register(struct siox_master *smaster)736{737	int ret;738 739	if (!siox_is_registered)740		return -EPROBE_DEFER;741 742	if (!smaster->pushpull)743		return -EINVAL;744 745	get_device(&smaster->dev);746 747	dev_set_name(&smaster->dev, "siox-%d", smaster->busno);748 749	mutex_init(&smaster->lock);750	INIT_LIST_HEAD(&smaster->devices);751 752	smaster->last_poll = jiffies;753	smaster->poll_thread = kthread_run(siox_poll_thread, smaster,754					   "siox-%d", smaster->busno);755	if (IS_ERR(smaster->poll_thread)) {756		smaster->active = 0;757		return PTR_ERR(smaster->poll_thread);758	}759 760	ret = device_add(&smaster->dev);761	if (ret)762		kthread_stop(smaster->poll_thread);763 764	return ret;765}766EXPORT_SYMBOL_GPL(siox_master_register);767 768void siox_master_unregister(struct siox_master *smaster)769{770	/* remove device */771	device_del(&smaster->dev);772 773	siox_master_lock(smaster);774 775	__siox_stop(smaster);776 777	while (smaster->num_devices) {778		struct siox_device *sdevice;779 780		sdevice = container_of(smaster->devices.prev,781				       struct siox_device, node);782		list_del(&sdevice->node);783		smaster->num_devices--;784 785		siox_master_unlock(smaster);786 787		device_unregister(&sdevice->dev);788 789		siox_master_lock(smaster);790	}791 792	siox_master_unlock(smaster);793 794	put_device(&smaster->dev);795}796EXPORT_SYMBOL_GPL(siox_master_unregister);797 798static void devm_siox_master_unregister(void *data)799{800	struct siox_master *smaster = data;801 802	siox_master_unregister(smaster);803}804 805int devm_siox_master_register(struct device *dev, struct siox_master *smaster)806{807	int ret;808 809	ret = siox_master_register(smaster);810	if (ret)811		return ret;812 813	return devm_add_action_or_reset(dev, devm_siox_master_unregister, smaster);814}815EXPORT_SYMBOL_GPL(devm_siox_master_register);816 817static struct siox_device *siox_device_add(struct siox_master *smaster,818					   const char *type, size_t inbytes,819					   size_t outbytes, u8 statustype)820{821	struct siox_device *sdevice;822	int ret;823	size_t buf_len;824 825	sdevice = kzalloc(sizeof(*sdevice), GFP_KERNEL);826	if (!sdevice)827		return ERR_PTR(-ENOMEM);828 829	sdevice->type = type;830	sdevice->inbytes = inbytes;831	sdevice->outbytes = outbytes;832	sdevice->statustype = statustype;833 834	sdevice->smaster = smaster;835	sdevice->dev.parent = &smaster->dev;836	sdevice->dev.bus = &siox_bus_type;837	sdevice->dev.type = &siox_device_type;838 839	siox_master_lock(smaster);840 841	dev_set_name(&sdevice->dev, "siox-%d-%d",842		     smaster->busno, smaster->num_devices);843 844	buf_len = smaster->setbuf_len + inbytes +845		smaster->getbuf_len + outbytes;846	if (smaster->buf_len < buf_len) {847		u8 *buf = krealloc(smaster->buf, buf_len, GFP_KERNEL);848 849		if (!buf) {850			dev_err(&smaster->dev,851				"failed to realloc buffer to %zu\n", buf_len);852			ret = -ENOMEM;853			goto err_buf_alloc;854		}855 856		smaster->buf_len = buf_len;857		smaster->buf = buf;858	}859 860	ret = device_register(&sdevice->dev);861	if (ret) {862		dev_err(&smaster->dev, "failed to register device: %d\n", ret);863 864		goto err_device_register;865	}866 867	smaster->num_devices++;868	list_add_tail(&sdevice->node, &smaster->devices);869 870	smaster->setbuf_len += sdevice->inbytes;871	smaster->getbuf_len += sdevice->outbytes;872 873	sdevice->status_errors_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,874						     "status_errors");875	sdevice->watchdog_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,876						"watchdog");877	sdevice->watchdog_errors_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,878						       "watchdog_errors");879	sdevice->connected_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,880						 "connected");881 882	siox_master_unlock(smaster);883 884	return sdevice;885 886err_device_register:887	/* don't care to make the buffer smaller again */888	put_device(&sdevice->dev);889	sdevice = NULL;890 891err_buf_alloc:892	siox_master_unlock(smaster);893 894	kfree(sdevice);895 896	return ERR_PTR(ret);897}898 899static void siox_device_remove(struct siox_master *smaster)900{901	struct siox_device *sdevice;902 903	siox_master_lock(smaster);904 905	if (!smaster->num_devices) {906		siox_master_unlock(smaster);907		return;908	}909 910	sdevice = container_of(smaster->devices.prev, struct siox_device, node);911	list_del(&sdevice->node);912	smaster->num_devices--;913 914	smaster->setbuf_len -= sdevice->inbytes;915	smaster->getbuf_len -= sdevice->outbytes;916 917	if (!smaster->num_devices)918		__siox_stop(smaster);919 920	siox_master_unlock(smaster);921 922	/*923	 * This must be done without holding the master lock because we're924	 * called from device_remove_store which also holds a sysfs mutex.925	 * device_unregister tries to aquire the same lock.926	 */927	device_unregister(&sdevice->dev);928}929 930int __siox_driver_register(struct siox_driver *sdriver, struct module *owner)931{932	int ret;933 934	if (unlikely(!siox_is_registered))935		return -EPROBE_DEFER;936 937	if (!sdriver->probe ||938	    (!sdriver->set_data && !sdriver->get_data)) {939		pr_err("Driver %s doesn't provide needed callbacks\n",940		       sdriver->driver.name);941		return -EINVAL;942	}943 944	sdriver->driver.owner = owner;945	sdriver->driver.bus = &siox_bus_type;946 947	ret = driver_register(&sdriver->driver);948	if (ret)949		pr_err("Failed to register siox driver %s (%d)\n",950		       sdriver->driver.name, ret);951 952	return ret;953}954EXPORT_SYMBOL_GPL(__siox_driver_register);955 956static int __init siox_init(void)957{958	int ret;959 960	ret = bus_register(&siox_bus_type);961	if (ret) {962		pr_err("Registration of SIOX bus type failed: %d\n", ret);963		return ret;964	}965 966	siox_is_registered = true;967 968	return 0;969}970subsys_initcall(siox_init);971 972static void __exit siox_exit(void)973{974	bus_unregister(&siox_bus_type);975}976module_exit(siox_exit);977 978MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");979MODULE_DESCRIPTION("Eckelmann SIOX driver core");980MODULE_LICENSE("GPL v2");981