0001
0002
0003
0004
0005 #include <linux/kernel.h>
0006 #include <linux/device.h>
0007 #include <linux/module.h>
0008 #include <linux/slab.h>
0009 #include <linux/sysfs.h>
0010
0011 #include "siox.h"
0012
0013
0014
0015
0016
0017
0018
0019 #define SIOX_STATUS_WDG 0x01
0020
0021
0022
0023
0024
0025
0026 #define SIOX_STATUS_COUNTER 0x0e
0027
0028
0029
0030
0031
0032
0033
0034 #define SIOX_STATUS_TYPE 0xf0
0035
0036 #define CREATE_TRACE_POINTS
0037 #include <trace/events/siox.h>
0038
0039 static bool siox_is_registered;
0040
0041 static void siox_master_lock(struct siox_master *smaster)
0042 {
0043 mutex_lock(&smaster->lock);
0044 }
0045
0046 static void siox_master_unlock(struct siox_master *smaster)
0047 {
0048 mutex_unlock(&smaster->lock);
0049 }
0050
0051 static inline u8 siox_status_clean(u8 status_read, u8 status_written)
0052 {
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 return status_read ^ (~status_written & 0xe);
0066 }
0067
0068 static bool siox_device_counter_error(struct siox_device *sdevice,
0069 u8 status_clean)
0070 {
0071 return (status_clean & SIOX_STATUS_COUNTER) != 0;
0072 }
0073
0074 static bool siox_device_type_error(struct siox_device *sdevice, u8 status_clean)
0075 {
0076 u8 statustype = (status_clean & SIOX_STATUS_TYPE) >> 4;
0077
0078
0079
0080
0081
0082
0083 if (sdevice->statustype) {
0084 if (statustype != sdevice->statustype)
0085 return true;
0086 } else {
0087 switch (statustype) {
0088 case 0:
0089 case 0xf:
0090 return true;
0091 }
0092 }
0093
0094 return false;
0095 }
0096
0097 static bool siox_device_wdg_error(struct siox_device *sdevice, u8 status_clean)
0098 {
0099 return (status_clean & SIOX_STATUS_WDG) == 0;
0100 }
0101
0102
0103
0104
0105 bool siox_device_synced(struct siox_device *sdevice)
0106 {
0107 if (siox_device_type_error(sdevice, sdevice->status_read_clean))
0108 return false;
0109
0110 return !siox_device_counter_error(sdevice, sdevice->status_read_clean);
0111
0112 }
0113 EXPORT_SYMBOL_GPL(siox_device_synced);
0114
0115
0116
0117
0118
0119 bool siox_device_connected(struct siox_device *sdevice)
0120 {
0121 if (!siox_device_synced(sdevice))
0122 return false;
0123
0124 return !siox_device_wdg_error(sdevice, sdevice->status_read_clean);
0125 }
0126 EXPORT_SYMBOL_GPL(siox_device_connected);
0127
0128 static void siox_poll(struct siox_master *smaster)
0129 {
0130 struct siox_device *sdevice;
0131 size_t i = smaster->setbuf_len;
0132 unsigned int devno = 0;
0133 int unsync_error = 0;
0134
0135 smaster->last_poll = jiffies;
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 if (++smaster->status > 0x0d)
0148 smaster->status = 0;
0149
0150 memset(smaster->buf, 0, smaster->setbuf_len);
0151
0152
0153 list_for_each_entry(sdevice, &smaster->devices, node) {
0154 struct siox_driver *sdriver =
0155 to_siox_driver(sdevice->dev.driver);
0156 sdevice->status_written = smaster->status;
0157
0158 i -= sdevice->inbytes;
0159
0160
0161
0162
0163
0164
0165 if (!siox_device_synced(sdevice))
0166 unsync_error = 1;
0167
0168 if (sdriver && !unsync_error)
0169 sdriver->set_data(sdevice, sdevice->status_written,
0170 &smaster->buf[i + 1]);
0171 else
0172
0173
0174
0175
0176 sdevice->status_written &= ~SIOX_STATUS_WDG;
0177
0178 smaster->buf[i] = sdevice->status_written;
0179
0180 trace_siox_set_data(smaster, sdevice, devno, i);
0181
0182 devno++;
0183 }
0184
0185 smaster->pushpull(smaster, smaster->setbuf_len, smaster->buf,
0186 smaster->getbuf_len,
0187 smaster->buf + smaster->setbuf_len);
0188
0189 unsync_error = 0;
0190
0191
0192 devno = 0;
0193 i = smaster->setbuf_len;
0194 list_for_each_entry(sdevice, &smaster->devices, node) {
0195 struct siox_driver *sdriver =
0196 to_siox_driver(sdevice->dev.driver);
0197 u8 status = smaster->buf[i + sdevice->outbytes - 1];
0198 u8 status_clean;
0199 u8 prev_status_clean = sdevice->status_read_clean;
0200 bool synced = true;
0201 bool connected = true;
0202
0203 if (!siox_device_synced(sdevice))
0204 unsync_error = 1;
0205
0206
0207
0208
0209
0210
0211 if (!sdriver || unsync_error)
0212 status &= ~SIOX_STATUS_WDG;
0213
0214 status_clean =
0215 siox_status_clean(status,
0216 sdevice->status_written_lastcycle);
0217
0218
0219 if (siox_device_counter_error(sdevice, status_clean) ||
0220 siox_device_type_error(sdevice, status_clean)) {
0221 bool prev_error;
0222
0223 synced = false;
0224
0225
0226 prev_error =
0227 siox_device_counter_error(sdevice,
0228 prev_status_clean) ||
0229 siox_device_type_error(sdevice,
0230 prev_status_clean);
0231
0232 if (!prev_error) {
0233 sdevice->status_errors++;
0234 sysfs_notify_dirent(sdevice->status_errors_kn);
0235 }
0236 }
0237
0238
0239 if (!synced) {
0240 status &= ~SIOX_STATUS_WDG;
0241 status_clean &= ~SIOX_STATUS_WDG;
0242 }
0243
0244 if (siox_device_wdg_error(sdevice, status_clean))
0245 connected = false;
0246
0247
0248 if ((status_clean ^ prev_status_clean) & SIOX_STATUS_WDG) {
0249 sysfs_notify_dirent(sdevice->watchdog_kn);
0250
0251 if (siox_device_wdg_error(sdevice, status_clean)) {
0252 struct kernfs_node *wd_errs =
0253 sdevice->watchdog_errors_kn;
0254
0255 sdevice->watchdog_errors++;
0256 sysfs_notify_dirent(wd_errs);
0257 }
0258 }
0259
0260 if (connected != sdevice->connected)
0261 sysfs_notify_dirent(sdevice->connected_kn);
0262
0263 sdevice->status_read_clean = status_clean;
0264 sdevice->status_written_lastcycle = sdevice->status_written;
0265 sdevice->connected = connected;
0266
0267 trace_siox_get_data(smaster, sdevice, devno, status_clean, i);
0268
0269
0270 if (sdriver && connected)
0271 sdriver->get_data(sdevice, &smaster->buf[i]);
0272
0273 devno++;
0274 i += sdevice->outbytes;
0275 }
0276 }
0277
0278 static int siox_poll_thread(void *data)
0279 {
0280 struct siox_master *smaster = data;
0281 signed long timeout = 0;
0282
0283 get_device(&smaster->dev);
0284
0285 for (;;) {
0286 if (kthread_should_stop()) {
0287 put_device(&smaster->dev);
0288 return 0;
0289 }
0290
0291 siox_master_lock(smaster);
0292
0293 if (smaster->active) {
0294 unsigned long next_poll =
0295 smaster->last_poll + smaster->poll_interval;
0296 if (time_is_before_eq_jiffies(next_poll))
0297 siox_poll(smaster);
0298
0299 timeout = smaster->poll_interval -
0300 (jiffies - smaster->last_poll);
0301 } else {
0302 timeout = MAX_SCHEDULE_TIMEOUT;
0303 }
0304
0305
0306
0307
0308
0309
0310 if (timeout > 0)
0311 set_current_state(TASK_IDLE);
0312
0313 siox_master_unlock(smaster);
0314
0315 if (timeout > 0)
0316 schedule_timeout(timeout);
0317
0318
0319
0320
0321
0322
0323 set_current_state(TASK_RUNNING);
0324 }
0325 }
0326
0327 static int __siox_start(struct siox_master *smaster)
0328 {
0329 if (!(smaster->setbuf_len + smaster->getbuf_len))
0330 return -ENODEV;
0331
0332 if (!smaster->buf)
0333 return -ENOMEM;
0334
0335 if (smaster->active)
0336 return 0;
0337
0338 smaster->active = 1;
0339 wake_up_process(smaster->poll_thread);
0340
0341 return 1;
0342 }
0343
0344 static int siox_start(struct siox_master *smaster)
0345 {
0346 int ret;
0347
0348 siox_master_lock(smaster);
0349 ret = __siox_start(smaster);
0350 siox_master_unlock(smaster);
0351
0352 return ret;
0353 }
0354
0355 static int __siox_stop(struct siox_master *smaster)
0356 {
0357 if (smaster->active) {
0358 struct siox_device *sdevice;
0359
0360 smaster->active = 0;
0361
0362 list_for_each_entry(sdevice, &smaster->devices, node) {
0363 if (sdevice->connected)
0364 sysfs_notify_dirent(sdevice->connected_kn);
0365 sdevice->connected = false;
0366 }
0367
0368 return 1;
0369 }
0370 return 0;
0371 }
0372
0373 static int siox_stop(struct siox_master *smaster)
0374 {
0375 int ret;
0376
0377 siox_master_lock(smaster);
0378 ret = __siox_stop(smaster);
0379 siox_master_unlock(smaster);
0380
0381 return ret;
0382 }
0383
0384 static ssize_t type_show(struct device *dev,
0385 struct device_attribute *attr, char *buf)
0386 {
0387 struct siox_device *sdev = to_siox_device(dev);
0388
0389 return sprintf(buf, "%s\n", sdev->type);
0390 }
0391
0392 static DEVICE_ATTR_RO(type);
0393
0394 static ssize_t inbytes_show(struct device *dev,
0395 struct device_attribute *attr, char *buf)
0396 {
0397 struct siox_device *sdev = to_siox_device(dev);
0398
0399 return sprintf(buf, "%zu\n", sdev->inbytes);
0400 }
0401
0402 static DEVICE_ATTR_RO(inbytes);
0403
0404 static ssize_t outbytes_show(struct device *dev,
0405 struct device_attribute *attr, char *buf)
0406 {
0407 struct siox_device *sdev = to_siox_device(dev);
0408
0409 return sprintf(buf, "%zu\n", sdev->outbytes);
0410 }
0411
0412 static DEVICE_ATTR_RO(outbytes);
0413
0414 static ssize_t status_errors_show(struct device *dev,
0415 struct device_attribute *attr, char *buf)
0416 {
0417 struct siox_device *sdev = to_siox_device(dev);
0418 unsigned int status_errors;
0419
0420 siox_master_lock(sdev->smaster);
0421
0422 status_errors = sdev->status_errors;
0423
0424 siox_master_unlock(sdev->smaster);
0425
0426 return sprintf(buf, "%u\n", status_errors);
0427 }
0428
0429 static DEVICE_ATTR_RO(status_errors);
0430
0431 static ssize_t connected_show(struct device *dev,
0432 struct device_attribute *attr, char *buf)
0433 {
0434 struct siox_device *sdev = to_siox_device(dev);
0435 bool connected;
0436
0437 siox_master_lock(sdev->smaster);
0438
0439 connected = sdev->connected;
0440
0441 siox_master_unlock(sdev->smaster);
0442
0443 return sprintf(buf, "%u\n", connected);
0444 }
0445
0446 static DEVICE_ATTR_RO(connected);
0447
0448 static ssize_t watchdog_show(struct device *dev,
0449 struct device_attribute *attr, char *buf)
0450 {
0451 struct siox_device *sdev = to_siox_device(dev);
0452 u8 status;
0453
0454 siox_master_lock(sdev->smaster);
0455
0456 status = sdev->status_read_clean;
0457
0458 siox_master_unlock(sdev->smaster);
0459
0460 return sprintf(buf, "%d\n", status & SIOX_STATUS_WDG);
0461 }
0462
0463 static DEVICE_ATTR_RO(watchdog);
0464
0465 static ssize_t watchdog_errors_show(struct device *dev,
0466 struct device_attribute *attr, char *buf)
0467 {
0468 struct siox_device *sdev = to_siox_device(dev);
0469 unsigned int watchdog_errors;
0470
0471 siox_master_lock(sdev->smaster);
0472
0473 watchdog_errors = sdev->watchdog_errors;
0474
0475 siox_master_unlock(sdev->smaster);
0476
0477 return sprintf(buf, "%u\n", watchdog_errors);
0478 }
0479
0480 static DEVICE_ATTR_RO(watchdog_errors);
0481
0482 static struct attribute *siox_device_attrs[] = {
0483 &dev_attr_type.attr,
0484 &dev_attr_inbytes.attr,
0485 &dev_attr_outbytes.attr,
0486 &dev_attr_status_errors.attr,
0487 &dev_attr_connected.attr,
0488 &dev_attr_watchdog.attr,
0489 &dev_attr_watchdog_errors.attr,
0490 NULL
0491 };
0492 ATTRIBUTE_GROUPS(siox_device);
0493
0494 static void siox_device_release(struct device *dev)
0495 {
0496 struct siox_device *sdevice = to_siox_device(dev);
0497
0498 kfree(sdevice);
0499 }
0500
0501 static struct device_type siox_device_type = {
0502 .groups = siox_device_groups,
0503 .release = siox_device_release,
0504 };
0505
0506 static int siox_match(struct device *dev, struct device_driver *drv)
0507 {
0508 if (dev->type != &siox_device_type)
0509 return 0;
0510
0511
0512 return 1;
0513 }
0514
0515 static int siox_probe(struct device *dev)
0516 {
0517 struct siox_driver *sdriver = to_siox_driver(dev->driver);
0518 struct siox_device *sdevice = to_siox_device(dev);
0519
0520 return sdriver->probe(sdevice);
0521 }
0522
0523 static void siox_remove(struct device *dev)
0524 {
0525 struct siox_driver *sdriver =
0526 container_of(dev->driver, struct siox_driver, driver);
0527 struct siox_device *sdevice = to_siox_device(dev);
0528
0529 if (sdriver->remove)
0530 sdriver->remove(sdevice);
0531 }
0532
0533 static void siox_shutdown(struct device *dev)
0534 {
0535 struct siox_device *sdevice = to_siox_device(dev);
0536 struct siox_driver *sdriver;
0537
0538 if (!dev->driver)
0539 return;
0540
0541 sdriver = container_of(dev->driver, struct siox_driver, driver);
0542 if (sdriver->shutdown)
0543 sdriver->shutdown(sdevice);
0544 }
0545
0546 static struct bus_type siox_bus_type = {
0547 .name = "siox",
0548 .match = siox_match,
0549 .probe = siox_probe,
0550 .remove = siox_remove,
0551 .shutdown = siox_shutdown,
0552 };
0553
0554 static ssize_t active_show(struct device *dev,
0555 struct device_attribute *attr, char *buf)
0556 {
0557 struct siox_master *smaster = to_siox_master(dev);
0558
0559 return sprintf(buf, "%d\n", smaster->active);
0560 }
0561
0562 static ssize_t active_store(struct device *dev,
0563 struct device_attribute *attr,
0564 const char *buf, size_t count)
0565 {
0566 struct siox_master *smaster = to_siox_master(dev);
0567 int ret;
0568 int active;
0569
0570 ret = kstrtoint(buf, 0, &active);
0571 if (ret < 0)
0572 return ret;
0573
0574 if (active)
0575 ret = siox_start(smaster);
0576 else
0577 ret = siox_stop(smaster);
0578
0579 if (ret < 0)
0580 return ret;
0581
0582 return count;
0583 }
0584
0585 static DEVICE_ATTR_RW(active);
0586
0587 static struct siox_device *siox_device_add(struct siox_master *smaster,
0588 const char *type, size_t inbytes,
0589 size_t outbytes, u8 statustype);
0590
0591 static ssize_t device_add_store(struct device *dev,
0592 struct device_attribute *attr,
0593 const char *buf, size_t count)
0594 {
0595 struct siox_master *smaster = to_siox_master(dev);
0596 int ret;
0597 char type[20] = "";
0598 size_t inbytes = 0, outbytes = 0;
0599 u8 statustype = 0;
0600
0601 ret = sscanf(buf, "%19s %zu %zu %hhu", type, &inbytes,
0602 &outbytes, &statustype);
0603 if (ret != 3 && ret != 4)
0604 return -EINVAL;
0605
0606 if (strcmp(type, "siox-12x8") || inbytes != 2 || outbytes != 4)
0607 return -EINVAL;
0608
0609 siox_device_add(smaster, "siox-12x8", inbytes, outbytes, statustype);
0610
0611 return count;
0612 }
0613
0614 static DEVICE_ATTR_WO(device_add);
0615
0616 static void siox_device_remove(struct siox_master *smaster);
0617
0618 static ssize_t device_remove_store(struct device *dev,
0619 struct device_attribute *attr,
0620 const char *buf, size_t count)
0621 {
0622 struct siox_master *smaster = to_siox_master(dev);
0623
0624
0625 siox_device_remove(smaster);
0626
0627 return count;
0628 }
0629
0630 static DEVICE_ATTR_WO(device_remove);
0631
0632 static ssize_t poll_interval_ns_show(struct device *dev,
0633 struct device_attribute *attr, char *buf)
0634 {
0635 struct siox_master *smaster = to_siox_master(dev);
0636
0637 return sprintf(buf, "%lld\n", jiffies_to_nsecs(smaster->poll_interval));
0638 }
0639
0640 static ssize_t poll_interval_ns_store(struct device *dev,
0641 struct device_attribute *attr,
0642 const char *buf, size_t count)
0643 {
0644 struct siox_master *smaster = to_siox_master(dev);
0645 int ret;
0646 u64 val;
0647
0648 ret = kstrtou64(buf, 0, &val);
0649 if (ret < 0)
0650 return ret;
0651
0652 siox_master_lock(smaster);
0653
0654 smaster->poll_interval = nsecs_to_jiffies(val);
0655
0656 siox_master_unlock(smaster);
0657
0658 return count;
0659 }
0660
0661 static DEVICE_ATTR_RW(poll_interval_ns);
0662
0663 static struct attribute *siox_master_attrs[] = {
0664 &dev_attr_active.attr,
0665 &dev_attr_device_add.attr,
0666 &dev_attr_device_remove.attr,
0667 &dev_attr_poll_interval_ns.attr,
0668 NULL
0669 };
0670 ATTRIBUTE_GROUPS(siox_master);
0671
0672 static void siox_master_release(struct device *dev)
0673 {
0674 struct siox_master *smaster = to_siox_master(dev);
0675
0676 kfree(smaster);
0677 }
0678
0679 static struct device_type siox_master_type = {
0680 .groups = siox_master_groups,
0681 .release = siox_master_release,
0682 };
0683
0684 struct siox_master *siox_master_alloc(struct device *dev,
0685 size_t size)
0686 {
0687 struct siox_master *smaster;
0688
0689 if (!dev)
0690 return NULL;
0691
0692 smaster = kzalloc(sizeof(*smaster) + size, GFP_KERNEL);
0693 if (!smaster)
0694 return NULL;
0695
0696 device_initialize(&smaster->dev);
0697
0698 smaster->busno = -1;
0699 smaster->dev.bus = &siox_bus_type;
0700 smaster->dev.type = &siox_master_type;
0701 smaster->dev.parent = dev;
0702 smaster->poll_interval = DIV_ROUND_UP(HZ, 40);
0703
0704 dev_set_drvdata(&smaster->dev, &smaster[1]);
0705
0706 return smaster;
0707 }
0708 EXPORT_SYMBOL_GPL(siox_master_alloc);
0709
0710 int siox_master_register(struct siox_master *smaster)
0711 {
0712 int ret;
0713
0714 if (!siox_is_registered)
0715 return -EPROBE_DEFER;
0716
0717 if (!smaster->pushpull)
0718 return -EINVAL;
0719
0720 dev_set_name(&smaster->dev, "siox-%d", smaster->busno);
0721
0722 mutex_init(&smaster->lock);
0723 INIT_LIST_HEAD(&smaster->devices);
0724
0725 smaster->last_poll = jiffies;
0726 smaster->poll_thread = kthread_run(siox_poll_thread, smaster,
0727 "siox-%d", smaster->busno);
0728 if (IS_ERR(smaster->poll_thread)) {
0729 smaster->active = 0;
0730 return PTR_ERR(smaster->poll_thread);
0731 }
0732
0733 ret = device_add(&smaster->dev);
0734 if (ret)
0735 kthread_stop(smaster->poll_thread);
0736
0737 return ret;
0738 }
0739 EXPORT_SYMBOL_GPL(siox_master_register);
0740
0741 void siox_master_unregister(struct siox_master *smaster)
0742 {
0743
0744 device_del(&smaster->dev);
0745
0746 siox_master_lock(smaster);
0747
0748 __siox_stop(smaster);
0749
0750 while (smaster->num_devices) {
0751 struct siox_device *sdevice;
0752
0753 sdevice = container_of(smaster->devices.prev,
0754 struct siox_device, node);
0755 list_del(&sdevice->node);
0756 smaster->num_devices--;
0757
0758 siox_master_unlock(smaster);
0759
0760 device_unregister(&sdevice->dev);
0761
0762 siox_master_lock(smaster);
0763 }
0764
0765 siox_master_unlock(smaster);
0766
0767 put_device(&smaster->dev);
0768 }
0769 EXPORT_SYMBOL_GPL(siox_master_unregister);
0770
0771 static struct siox_device *siox_device_add(struct siox_master *smaster,
0772 const char *type, size_t inbytes,
0773 size_t outbytes, u8 statustype)
0774 {
0775 struct siox_device *sdevice;
0776 int ret;
0777 size_t buf_len;
0778
0779 sdevice = kzalloc(sizeof(*sdevice), GFP_KERNEL);
0780 if (!sdevice)
0781 return ERR_PTR(-ENOMEM);
0782
0783 sdevice->type = type;
0784 sdevice->inbytes = inbytes;
0785 sdevice->outbytes = outbytes;
0786 sdevice->statustype = statustype;
0787
0788 sdevice->smaster = smaster;
0789 sdevice->dev.parent = &smaster->dev;
0790 sdevice->dev.bus = &siox_bus_type;
0791 sdevice->dev.type = &siox_device_type;
0792
0793 siox_master_lock(smaster);
0794
0795 dev_set_name(&sdevice->dev, "siox-%d-%d",
0796 smaster->busno, smaster->num_devices);
0797
0798 buf_len = smaster->setbuf_len + inbytes +
0799 smaster->getbuf_len + outbytes;
0800 if (smaster->buf_len < buf_len) {
0801 u8 *buf = krealloc(smaster->buf, buf_len, GFP_KERNEL);
0802
0803 if (!buf) {
0804 dev_err(&smaster->dev,
0805 "failed to realloc buffer to %zu\n", buf_len);
0806 ret = -ENOMEM;
0807 goto err_buf_alloc;
0808 }
0809
0810 smaster->buf_len = buf_len;
0811 smaster->buf = buf;
0812 }
0813
0814 ret = device_register(&sdevice->dev);
0815 if (ret) {
0816 dev_err(&smaster->dev, "failed to register device: %d\n", ret);
0817
0818 goto err_device_register;
0819 }
0820
0821 smaster->num_devices++;
0822 list_add_tail(&sdevice->node, &smaster->devices);
0823
0824 smaster->setbuf_len += sdevice->inbytes;
0825 smaster->getbuf_len += sdevice->outbytes;
0826
0827 sdevice->status_errors_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,
0828 "status_errors");
0829 sdevice->watchdog_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,
0830 "watchdog");
0831 sdevice->watchdog_errors_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,
0832 "watchdog_errors");
0833 sdevice->connected_kn = sysfs_get_dirent(sdevice->dev.kobj.sd,
0834 "connected");
0835
0836 siox_master_unlock(smaster);
0837
0838 return sdevice;
0839
0840 err_device_register:
0841
0842
0843 err_buf_alloc:
0844 siox_master_unlock(smaster);
0845
0846 kfree(sdevice);
0847
0848 return ERR_PTR(ret);
0849 }
0850
0851 static void siox_device_remove(struct siox_master *smaster)
0852 {
0853 struct siox_device *sdevice;
0854
0855 siox_master_lock(smaster);
0856
0857 if (!smaster->num_devices) {
0858 siox_master_unlock(smaster);
0859 return;
0860 }
0861
0862 sdevice = container_of(smaster->devices.prev, struct siox_device, node);
0863 list_del(&sdevice->node);
0864 smaster->num_devices--;
0865
0866 smaster->setbuf_len -= sdevice->inbytes;
0867 smaster->getbuf_len -= sdevice->outbytes;
0868
0869 if (!smaster->num_devices)
0870 __siox_stop(smaster);
0871
0872 siox_master_unlock(smaster);
0873
0874
0875
0876
0877
0878
0879 device_unregister(&sdevice->dev);
0880 }
0881
0882 int __siox_driver_register(struct siox_driver *sdriver, struct module *owner)
0883 {
0884 int ret;
0885
0886 if (unlikely(!siox_is_registered))
0887 return -EPROBE_DEFER;
0888
0889 if (!sdriver->probe ||
0890 (!sdriver->set_data && !sdriver->get_data)) {
0891 pr_err("Driver %s doesn't provide needed callbacks\n",
0892 sdriver->driver.name);
0893 return -EINVAL;
0894 }
0895
0896 sdriver->driver.owner = owner;
0897 sdriver->driver.bus = &siox_bus_type;
0898
0899 ret = driver_register(&sdriver->driver);
0900 if (ret)
0901 pr_err("Failed to register siox driver %s (%d)\n",
0902 sdriver->driver.name, ret);
0903
0904 return ret;
0905 }
0906 EXPORT_SYMBOL_GPL(__siox_driver_register);
0907
0908 static int __init siox_init(void)
0909 {
0910 int ret;
0911
0912 ret = bus_register(&siox_bus_type);
0913 if (ret) {
0914 pr_err("Registration of SIOX bus type failed: %d\n", ret);
0915 return ret;
0916 }
0917
0918 siox_is_registered = true;
0919
0920 return 0;
0921 }
0922 subsys_initcall(siox_init);
0923
0924 static void __exit siox_exit(void)
0925 {
0926 bus_unregister(&siox_bus_type);
0927 }
0928 module_exit(siox_exit);
0929
0930 MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
0931 MODULE_DESCRIPTION("Eckelmann SIOX driver core");
0932 MODULE_LICENSE("GPL v2");