Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Surface Book (gen. 2 and later) detachment system (DTX) driver.
0004  *
0005  * Provides a user-space interface to properly handle clipboard/tablet
0006  * (containing screen and processor) detachment from the base of the device
0007  * (containing the keyboard and optionally a discrete GPU). Allows to
0008  * acknowledge (to speed things up), abort (e.g. in case the dGPU is still in
0009  * use), or request detachment via user-space.
0010  *
0011  * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
0012  */
0013 
0014 #include <linux/fs.h>
0015 #include <linux/input.h>
0016 #include <linux/ioctl.h>
0017 #include <linux/kernel.h>
0018 #include <linux/kfifo.h>
0019 #include <linux/kref.h>
0020 #include <linux/miscdevice.h>
0021 #include <linux/module.h>
0022 #include <linux/mutex.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/poll.h>
0025 #include <linux/rwsem.h>
0026 #include <linux/slab.h>
0027 #include <linux/workqueue.h>
0028 
0029 #include <linux/surface_aggregator/controller.h>
0030 #include <linux/surface_aggregator/device.h>
0031 #include <linux/surface_aggregator/dtx.h>
0032 
0033 
0034 /* -- SSAM interface. ------------------------------------------------------- */
0035 
0036 enum sam_event_cid_bas {
0037     SAM_EVENT_CID_DTX_CONNECTION            = 0x0c,
0038     SAM_EVENT_CID_DTX_REQUEST           = 0x0e,
0039     SAM_EVENT_CID_DTX_CANCEL            = 0x0f,
0040     SAM_EVENT_CID_DTX_LATCH_STATUS          = 0x11,
0041 };
0042 
0043 enum ssam_bas_base_state {
0044     SSAM_BAS_BASE_STATE_DETACH_SUCCESS      = 0x00,
0045     SSAM_BAS_BASE_STATE_ATTACHED            = 0x01,
0046     SSAM_BAS_BASE_STATE_NOT_FEASIBLE        = 0x02,
0047 };
0048 
0049 enum ssam_bas_latch_status {
0050     SSAM_BAS_LATCH_STATUS_CLOSED            = 0x00,
0051     SSAM_BAS_LATCH_STATUS_OPENED            = 0x01,
0052     SSAM_BAS_LATCH_STATUS_FAILED_TO_OPEN        = 0x02,
0053     SSAM_BAS_LATCH_STATUS_FAILED_TO_REMAIN_OPEN = 0x03,
0054     SSAM_BAS_LATCH_STATUS_FAILED_TO_CLOSE       = 0x04,
0055 };
0056 
0057 enum ssam_bas_cancel_reason {
0058     SSAM_BAS_CANCEL_REASON_NOT_FEASIBLE     = 0x00,  /* Low battery. */
0059     SSAM_BAS_CANCEL_REASON_TIMEOUT          = 0x02,
0060     SSAM_BAS_CANCEL_REASON_FAILED_TO_OPEN       = 0x03,
0061     SSAM_BAS_CANCEL_REASON_FAILED_TO_REMAIN_OPEN    = 0x04,
0062     SSAM_BAS_CANCEL_REASON_FAILED_TO_CLOSE      = 0x05,
0063 };
0064 
0065 struct ssam_bas_base_info {
0066     u8 state;
0067     u8 base_id;
0068 } __packed;
0069 
0070 static_assert(sizeof(struct ssam_bas_base_info) == 2);
0071 
0072 SSAM_DEFINE_SYNC_REQUEST_N(ssam_bas_latch_lock, {
0073     .target_category = SSAM_SSH_TC_BAS,
0074     .target_id       = 0x01,
0075     .command_id      = 0x06,
0076     .instance_id     = 0x00,
0077 });
0078 
0079 SSAM_DEFINE_SYNC_REQUEST_N(ssam_bas_latch_unlock, {
0080     .target_category = SSAM_SSH_TC_BAS,
0081     .target_id       = 0x01,
0082     .command_id      = 0x07,
0083     .instance_id     = 0x00,
0084 });
0085 
0086 SSAM_DEFINE_SYNC_REQUEST_N(ssam_bas_latch_request, {
0087     .target_category = SSAM_SSH_TC_BAS,
0088     .target_id       = 0x01,
0089     .command_id      = 0x08,
0090     .instance_id     = 0x00,
0091 });
0092 
0093 SSAM_DEFINE_SYNC_REQUEST_N(ssam_bas_latch_confirm, {
0094     .target_category = SSAM_SSH_TC_BAS,
0095     .target_id       = 0x01,
0096     .command_id      = 0x09,
0097     .instance_id     = 0x00,
0098 });
0099 
0100 SSAM_DEFINE_SYNC_REQUEST_N(ssam_bas_latch_heartbeat, {
0101     .target_category = SSAM_SSH_TC_BAS,
0102     .target_id       = 0x01,
0103     .command_id      = 0x0a,
0104     .instance_id     = 0x00,
0105 });
0106 
0107 SSAM_DEFINE_SYNC_REQUEST_N(ssam_bas_latch_cancel, {
0108     .target_category = SSAM_SSH_TC_BAS,
0109     .target_id       = 0x01,
0110     .command_id      = 0x0b,
0111     .instance_id     = 0x00,
0112 });
0113 
0114 SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_get_base, struct ssam_bas_base_info, {
0115     .target_category = SSAM_SSH_TC_BAS,
0116     .target_id       = 0x01,
0117     .command_id      = 0x0c,
0118     .instance_id     = 0x00,
0119 });
0120 
0121 SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_get_device_mode, u8, {
0122     .target_category = SSAM_SSH_TC_BAS,
0123     .target_id       = 0x01,
0124     .command_id      = 0x0d,
0125     .instance_id     = 0x00,
0126 });
0127 
0128 SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_get_latch_status, u8, {
0129     .target_category = SSAM_SSH_TC_BAS,
0130     .target_id       = 0x01,
0131     .command_id      = 0x11,
0132     .instance_id     = 0x00,
0133 });
0134 
0135 
0136 /* -- Main structures. ------------------------------------------------------ */
0137 
0138 enum sdtx_device_state {
0139     SDTX_DEVICE_SHUTDOWN_BIT    = BIT(0),
0140     SDTX_DEVICE_DIRTY_BASE_BIT  = BIT(1),
0141     SDTX_DEVICE_DIRTY_MODE_BIT  = BIT(2),
0142     SDTX_DEVICE_DIRTY_LATCH_BIT = BIT(3),
0143 };
0144 
0145 struct sdtx_device {
0146     struct kref kref;
0147     struct rw_semaphore lock;         /* Guards device and controller reference. */
0148 
0149     struct device *dev;
0150     struct ssam_controller *ctrl;
0151     unsigned long flags;
0152 
0153     struct miscdevice mdev;
0154     wait_queue_head_t waitq;
0155     struct mutex write_lock;          /* Guards order of events/notifications. */
0156     struct rw_semaphore client_lock;  /* Guards client list.                   */
0157     struct list_head client_list;
0158 
0159     struct delayed_work state_work;
0160     struct {
0161         struct ssam_bas_base_info base;
0162         u8 device_mode;
0163         u8 latch_status;
0164     } state;
0165 
0166     struct delayed_work mode_work;
0167     struct input_dev *mode_switch;
0168 
0169     struct ssam_event_notifier notif;
0170 };
0171 
0172 enum sdtx_client_state {
0173     SDTX_CLIENT_EVENTS_ENABLED_BIT = BIT(0),
0174 };
0175 
0176 struct sdtx_client {
0177     struct sdtx_device *ddev;
0178     struct list_head node;
0179     unsigned long flags;
0180 
0181     struct fasync_struct *fasync;
0182 
0183     struct mutex read_lock;           /* Guards FIFO buffer read access. */
0184     DECLARE_KFIFO(buffer, u8, 512);
0185 };
0186 
0187 static void __sdtx_device_release(struct kref *kref)
0188 {
0189     struct sdtx_device *ddev = container_of(kref, struct sdtx_device, kref);
0190 
0191     mutex_destroy(&ddev->write_lock);
0192     kfree(ddev);
0193 }
0194 
0195 static struct sdtx_device *sdtx_device_get(struct sdtx_device *ddev)
0196 {
0197     if (ddev)
0198         kref_get(&ddev->kref);
0199 
0200     return ddev;
0201 }
0202 
0203 static void sdtx_device_put(struct sdtx_device *ddev)
0204 {
0205     if (ddev)
0206         kref_put(&ddev->kref, __sdtx_device_release);
0207 }
0208 
0209 
0210 /* -- Firmware value translations. ------------------------------------------ */
0211 
0212 static u16 sdtx_translate_base_state(struct sdtx_device *ddev, u8 state)
0213 {
0214     switch (state) {
0215     case SSAM_BAS_BASE_STATE_ATTACHED:
0216         return SDTX_BASE_ATTACHED;
0217 
0218     case SSAM_BAS_BASE_STATE_DETACH_SUCCESS:
0219         return SDTX_BASE_DETACHED;
0220 
0221     case SSAM_BAS_BASE_STATE_NOT_FEASIBLE:
0222         return SDTX_DETACH_NOT_FEASIBLE;
0223 
0224     default:
0225         dev_err(ddev->dev, "unknown base state: %#04x\n", state);
0226         return SDTX_UNKNOWN(state);
0227     }
0228 }
0229 
0230 static u16 sdtx_translate_latch_status(struct sdtx_device *ddev, u8 status)
0231 {
0232     switch (status) {
0233     case SSAM_BAS_LATCH_STATUS_CLOSED:
0234         return SDTX_LATCH_CLOSED;
0235 
0236     case SSAM_BAS_LATCH_STATUS_OPENED:
0237         return SDTX_LATCH_OPENED;
0238 
0239     case SSAM_BAS_LATCH_STATUS_FAILED_TO_OPEN:
0240         return SDTX_ERR_FAILED_TO_OPEN;
0241 
0242     case SSAM_BAS_LATCH_STATUS_FAILED_TO_REMAIN_OPEN:
0243         return SDTX_ERR_FAILED_TO_REMAIN_OPEN;
0244 
0245     case SSAM_BAS_LATCH_STATUS_FAILED_TO_CLOSE:
0246         return SDTX_ERR_FAILED_TO_CLOSE;
0247 
0248     default:
0249         dev_err(ddev->dev, "unknown latch status: %#04x\n", status);
0250         return SDTX_UNKNOWN(status);
0251     }
0252 }
0253 
0254 static u16 sdtx_translate_cancel_reason(struct sdtx_device *ddev, u8 reason)
0255 {
0256     switch (reason) {
0257     case SSAM_BAS_CANCEL_REASON_NOT_FEASIBLE:
0258         return SDTX_DETACH_NOT_FEASIBLE;
0259 
0260     case SSAM_BAS_CANCEL_REASON_TIMEOUT:
0261         return SDTX_DETACH_TIMEDOUT;
0262 
0263     case SSAM_BAS_CANCEL_REASON_FAILED_TO_OPEN:
0264         return SDTX_ERR_FAILED_TO_OPEN;
0265 
0266     case SSAM_BAS_CANCEL_REASON_FAILED_TO_REMAIN_OPEN:
0267         return SDTX_ERR_FAILED_TO_REMAIN_OPEN;
0268 
0269     case SSAM_BAS_CANCEL_REASON_FAILED_TO_CLOSE:
0270         return SDTX_ERR_FAILED_TO_CLOSE;
0271 
0272     default:
0273         dev_err(ddev->dev, "unknown cancel reason: %#04x\n", reason);
0274         return SDTX_UNKNOWN(reason);
0275     }
0276 }
0277 
0278 
0279 /* -- IOCTLs. --------------------------------------------------------------- */
0280 
0281 static int sdtx_ioctl_get_base_info(struct sdtx_device *ddev,
0282                     struct sdtx_base_info __user *buf)
0283 {
0284     struct ssam_bas_base_info raw;
0285     struct sdtx_base_info info;
0286     int status;
0287 
0288     lockdep_assert_held_read(&ddev->lock);
0289 
0290     status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &raw);
0291     if (status < 0)
0292         return status;
0293 
0294     info.state = sdtx_translate_base_state(ddev, raw.state);
0295     info.base_id = SDTX_BASE_TYPE_SSH(raw.base_id);
0296 
0297     if (copy_to_user(buf, &info, sizeof(info)))
0298         return -EFAULT;
0299 
0300     return 0;
0301 }
0302 
0303 static int sdtx_ioctl_get_device_mode(struct sdtx_device *ddev, u16 __user *buf)
0304 {
0305     u8 mode;
0306     int status;
0307 
0308     lockdep_assert_held_read(&ddev->lock);
0309 
0310     status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &mode);
0311     if (status < 0)
0312         return status;
0313 
0314     return put_user(mode, buf);
0315 }
0316 
0317 static int sdtx_ioctl_get_latch_status(struct sdtx_device *ddev, u16 __user *buf)
0318 {
0319     u8 latch;
0320     int status;
0321 
0322     lockdep_assert_held_read(&ddev->lock);
0323 
0324     status = ssam_retry(ssam_bas_get_latch_status, ddev->ctrl, &latch);
0325     if (status < 0)
0326         return status;
0327 
0328     return put_user(sdtx_translate_latch_status(ddev, latch), buf);
0329 }
0330 
0331 static long __surface_dtx_ioctl(struct sdtx_client *client, unsigned int cmd, unsigned long arg)
0332 {
0333     struct sdtx_device *ddev = client->ddev;
0334 
0335     lockdep_assert_held_read(&ddev->lock);
0336 
0337     switch (cmd) {
0338     case SDTX_IOCTL_EVENTS_ENABLE:
0339         set_bit(SDTX_CLIENT_EVENTS_ENABLED_BIT, &client->flags);
0340         return 0;
0341 
0342     case SDTX_IOCTL_EVENTS_DISABLE:
0343         clear_bit(SDTX_CLIENT_EVENTS_ENABLED_BIT, &client->flags);
0344         return 0;
0345 
0346     case SDTX_IOCTL_LATCH_LOCK:
0347         return ssam_retry(ssam_bas_latch_lock, ddev->ctrl);
0348 
0349     case SDTX_IOCTL_LATCH_UNLOCK:
0350         return ssam_retry(ssam_bas_latch_unlock, ddev->ctrl);
0351 
0352     case SDTX_IOCTL_LATCH_REQUEST:
0353         return ssam_retry(ssam_bas_latch_request, ddev->ctrl);
0354 
0355     case SDTX_IOCTL_LATCH_CONFIRM:
0356         return ssam_retry(ssam_bas_latch_confirm, ddev->ctrl);
0357 
0358     case SDTX_IOCTL_LATCH_HEARTBEAT:
0359         return ssam_retry(ssam_bas_latch_heartbeat, ddev->ctrl);
0360 
0361     case SDTX_IOCTL_LATCH_CANCEL:
0362         return ssam_retry(ssam_bas_latch_cancel, ddev->ctrl);
0363 
0364     case SDTX_IOCTL_GET_BASE_INFO:
0365         return sdtx_ioctl_get_base_info(ddev, (struct sdtx_base_info __user *)arg);
0366 
0367     case SDTX_IOCTL_GET_DEVICE_MODE:
0368         return sdtx_ioctl_get_device_mode(ddev, (u16 __user *)arg);
0369 
0370     case SDTX_IOCTL_GET_LATCH_STATUS:
0371         return sdtx_ioctl_get_latch_status(ddev, (u16 __user *)arg);
0372 
0373     default:
0374         return -EINVAL;
0375     }
0376 }
0377 
0378 static long surface_dtx_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0379 {
0380     struct sdtx_client *client = file->private_data;
0381     long status;
0382 
0383     if (down_read_killable(&client->ddev->lock))
0384         return -ERESTARTSYS;
0385 
0386     if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &client->ddev->flags)) {
0387         up_read(&client->ddev->lock);
0388         return -ENODEV;
0389     }
0390 
0391     status = __surface_dtx_ioctl(client, cmd, arg);
0392 
0393     up_read(&client->ddev->lock);
0394     return status;
0395 }
0396 
0397 
0398 /* -- File operations. ------------------------------------------------------ */
0399 
0400 static int surface_dtx_open(struct inode *inode, struct file *file)
0401 {
0402     struct sdtx_device *ddev = container_of(file->private_data, struct sdtx_device, mdev);
0403     struct sdtx_client *client;
0404 
0405     /* Initialize client. */
0406     client = kzalloc(sizeof(*client), GFP_KERNEL);
0407     if (!client)
0408         return -ENOMEM;
0409 
0410     client->ddev = sdtx_device_get(ddev);
0411 
0412     INIT_LIST_HEAD(&client->node);
0413 
0414     mutex_init(&client->read_lock);
0415     INIT_KFIFO(client->buffer);
0416 
0417     file->private_data = client;
0418 
0419     /* Attach client. */
0420     down_write(&ddev->client_lock);
0421 
0422     /*
0423      * Do not add a new client if the device has been shut down. Note that
0424      * it's enough to hold the client_lock here as, during shutdown, we
0425      * only acquire that lock and remove clients after marking the device
0426      * as shut down.
0427      */
0428     if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &ddev->flags)) {
0429         up_write(&ddev->client_lock);
0430         mutex_destroy(&client->read_lock);
0431         sdtx_device_put(client->ddev);
0432         kfree(client);
0433         return -ENODEV;
0434     }
0435 
0436     list_add_tail(&client->node, &ddev->client_list);
0437     up_write(&ddev->client_lock);
0438 
0439     stream_open(inode, file);
0440     return 0;
0441 }
0442 
0443 static int surface_dtx_release(struct inode *inode, struct file *file)
0444 {
0445     struct sdtx_client *client = file->private_data;
0446 
0447     /* Detach client. */
0448     down_write(&client->ddev->client_lock);
0449     list_del(&client->node);
0450     up_write(&client->ddev->client_lock);
0451 
0452     /* Free client. */
0453     sdtx_device_put(client->ddev);
0454     mutex_destroy(&client->read_lock);
0455     kfree(client);
0456 
0457     return 0;
0458 }
0459 
0460 static ssize_t surface_dtx_read(struct file *file, char __user *buf, size_t count, loff_t *offs)
0461 {
0462     struct sdtx_client *client = file->private_data;
0463     struct sdtx_device *ddev = client->ddev;
0464     unsigned int copied;
0465     int status = 0;
0466 
0467     if (down_read_killable(&ddev->lock))
0468         return -ERESTARTSYS;
0469 
0470     /* Make sure we're not shut down. */
0471     if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &ddev->flags)) {
0472         up_read(&ddev->lock);
0473         return -ENODEV;
0474     }
0475 
0476     do {
0477         /* Check availability, wait if necessary. */
0478         if (kfifo_is_empty(&client->buffer)) {
0479             up_read(&ddev->lock);
0480 
0481             if (file->f_flags & O_NONBLOCK)
0482                 return -EAGAIN;
0483 
0484             status = wait_event_interruptible(ddev->waitq,
0485                               !kfifo_is_empty(&client->buffer) ||
0486                               test_bit(SDTX_DEVICE_SHUTDOWN_BIT,
0487                                    &ddev->flags));
0488             if (status < 0)
0489                 return status;
0490 
0491             if (down_read_killable(&ddev->lock))
0492                 return -ERESTARTSYS;
0493 
0494             /* Need to check that we're not shut down again. */
0495             if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &ddev->flags)) {
0496                 up_read(&ddev->lock);
0497                 return -ENODEV;
0498             }
0499         }
0500 
0501         /* Try to read from FIFO. */
0502         if (mutex_lock_interruptible(&client->read_lock)) {
0503             up_read(&ddev->lock);
0504             return -ERESTARTSYS;
0505         }
0506 
0507         status = kfifo_to_user(&client->buffer, buf, count, &copied);
0508         mutex_unlock(&client->read_lock);
0509 
0510         if (status < 0) {
0511             up_read(&ddev->lock);
0512             return status;
0513         }
0514 
0515         /* We might not have gotten anything, check this here. */
0516         if (copied == 0 && (file->f_flags & O_NONBLOCK)) {
0517             up_read(&ddev->lock);
0518             return -EAGAIN;
0519         }
0520     } while (copied == 0);
0521 
0522     up_read(&ddev->lock);
0523     return copied;
0524 }
0525 
0526 static __poll_t surface_dtx_poll(struct file *file, struct poll_table_struct *pt)
0527 {
0528     struct sdtx_client *client = file->private_data;
0529     __poll_t events = 0;
0530 
0531     if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &client->ddev->flags))
0532         return EPOLLHUP | EPOLLERR;
0533 
0534     poll_wait(file, &client->ddev->waitq, pt);
0535 
0536     if (!kfifo_is_empty(&client->buffer))
0537         events |= EPOLLIN | EPOLLRDNORM;
0538 
0539     return events;
0540 }
0541 
0542 static int surface_dtx_fasync(int fd, struct file *file, int on)
0543 {
0544     struct sdtx_client *client = file->private_data;
0545 
0546     return fasync_helper(fd, file, on, &client->fasync);
0547 }
0548 
0549 static const struct file_operations surface_dtx_fops = {
0550     .owner          = THIS_MODULE,
0551     .open           = surface_dtx_open,
0552     .release        = surface_dtx_release,
0553     .read           = surface_dtx_read,
0554     .poll           = surface_dtx_poll,
0555     .fasync         = surface_dtx_fasync,
0556     .unlocked_ioctl = surface_dtx_ioctl,
0557     .compat_ioctl   = surface_dtx_ioctl,
0558     .llseek         = no_llseek,
0559 };
0560 
0561 
0562 /* -- Event handling/forwarding. -------------------------------------------- */
0563 
0564 /*
0565  * The device operation mode is not immediately updated on the EC when the
0566  * base has been connected, i.e. querying the device mode inside the
0567  * connection event callback yields an outdated value. Thus, we can only
0568  * determine the new tablet-mode switch and device mode values after some
0569  * time.
0570  *
0571  * These delays have been chosen by experimenting. We first delay on connect
0572  * events, then check and validate the device mode against the base state and
0573  * if invalid delay again by the "recheck" delay.
0574  */
0575 #define SDTX_DEVICE_MODE_DELAY_CONNECT  msecs_to_jiffies(100)
0576 #define SDTX_DEVICE_MODE_DELAY_RECHECK  msecs_to_jiffies(100)
0577 
0578 struct sdtx_status_event {
0579     struct sdtx_event e;
0580     __u16 v;
0581 } __packed;
0582 
0583 struct sdtx_base_info_event {
0584     struct sdtx_event e;
0585     struct sdtx_base_info v;
0586 } __packed;
0587 
0588 union sdtx_generic_event {
0589     struct sdtx_event common;
0590     struct sdtx_status_event status;
0591     struct sdtx_base_info_event base;
0592 };
0593 
0594 static void sdtx_update_device_mode(struct sdtx_device *ddev, unsigned long delay);
0595 
0596 /* Must be executed with ddev->write_lock held. */
0597 static void sdtx_push_event(struct sdtx_device *ddev, struct sdtx_event *evt)
0598 {
0599     const size_t len = sizeof(struct sdtx_event) + evt->length;
0600     struct sdtx_client *client;
0601 
0602     lockdep_assert_held(&ddev->write_lock);
0603 
0604     down_read(&ddev->client_lock);
0605     list_for_each_entry(client, &ddev->client_list, node) {
0606         if (!test_bit(SDTX_CLIENT_EVENTS_ENABLED_BIT, &client->flags))
0607             continue;
0608 
0609         if (likely(kfifo_avail(&client->buffer) >= len))
0610             kfifo_in(&client->buffer, (const u8 *)evt, len);
0611         else
0612             dev_warn(ddev->dev, "event buffer overrun\n");
0613 
0614         kill_fasync(&client->fasync, SIGIO, POLL_IN);
0615     }
0616     up_read(&ddev->client_lock);
0617 
0618     wake_up_interruptible(&ddev->waitq);
0619 }
0620 
0621 static u32 sdtx_notifier(struct ssam_event_notifier *nf, const struct ssam_event *in)
0622 {
0623     struct sdtx_device *ddev = container_of(nf, struct sdtx_device, notif);
0624     union sdtx_generic_event event;
0625     size_t len;
0626 
0627     /* Validate event payload length. */
0628     switch (in->command_id) {
0629     case SAM_EVENT_CID_DTX_CONNECTION:
0630         len = 2 * sizeof(u8);
0631         break;
0632 
0633     case SAM_EVENT_CID_DTX_REQUEST:
0634         len = 0;
0635         break;
0636 
0637     case SAM_EVENT_CID_DTX_CANCEL:
0638         len = sizeof(u8);
0639         break;
0640 
0641     case SAM_EVENT_CID_DTX_LATCH_STATUS:
0642         len = sizeof(u8);
0643         break;
0644 
0645     default:
0646         return 0;
0647     }
0648 
0649     if (in->length != len) {
0650         dev_err(ddev->dev,
0651             "unexpected payload size for event %#04x: got %u, expected %zu\n",
0652             in->command_id, in->length, len);
0653         return 0;
0654     }
0655 
0656     mutex_lock(&ddev->write_lock);
0657 
0658     /* Translate event. */
0659     switch (in->command_id) {
0660     case SAM_EVENT_CID_DTX_CONNECTION:
0661         clear_bit(SDTX_DEVICE_DIRTY_BASE_BIT, &ddev->flags);
0662 
0663         /* If state has not changed: do not send new event. */
0664         if (ddev->state.base.state == in->data[0] &&
0665             ddev->state.base.base_id == in->data[1])
0666             goto out;
0667 
0668         ddev->state.base.state = in->data[0];
0669         ddev->state.base.base_id = in->data[1];
0670 
0671         event.base.e.length = sizeof(struct sdtx_base_info);
0672         event.base.e.code = SDTX_EVENT_BASE_CONNECTION;
0673         event.base.v.state = sdtx_translate_base_state(ddev, in->data[0]);
0674         event.base.v.base_id = SDTX_BASE_TYPE_SSH(in->data[1]);
0675         break;
0676 
0677     case SAM_EVENT_CID_DTX_REQUEST:
0678         event.common.code = SDTX_EVENT_REQUEST;
0679         event.common.length = 0;
0680         break;
0681 
0682     case SAM_EVENT_CID_DTX_CANCEL:
0683         event.status.e.length = sizeof(u16);
0684         event.status.e.code = SDTX_EVENT_CANCEL;
0685         event.status.v = sdtx_translate_cancel_reason(ddev, in->data[0]);
0686         break;
0687 
0688     case SAM_EVENT_CID_DTX_LATCH_STATUS:
0689         clear_bit(SDTX_DEVICE_DIRTY_LATCH_BIT, &ddev->flags);
0690 
0691         /* If state has not changed: do not send new event. */
0692         if (ddev->state.latch_status == in->data[0])
0693             goto out;
0694 
0695         ddev->state.latch_status = in->data[0];
0696 
0697         event.status.e.length = sizeof(u16);
0698         event.status.e.code = SDTX_EVENT_LATCH_STATUS;
0699         event.status.v = sdtx_translate_latch_status(ddev, in->data[0]);
0700         break;
0701     }
0702 
0703     sdtx_push_event(ddev, &event.common);
0704 
0705     /* Update device mode on base connection change. */
0706     if (in->command_id == SAM_EVENT_CID_DTX_CONNECTION) {
0707         unsigned long delay;
0708 
0709         delay = in->data[0] ? SDTX_DEVICE_MODE_DELAY_CONNECT : 0;
0710         sdtx_update_device_mode(ddev, delay);
0711     }
0712 
0713 out:
0714     mutex_unlock(&ddev->write_lock);
0715     return SSAM_NOTIF_HANDLED;
0716 }
0717 
0718 
0719 /* -- State update functions. ----------------------------------------------- */
0720 
0721 static bool sdtx_device_mode_invalid(u8 mode, u8 base_state)
0722 {
0723     return ((base_state == SSAM_BAS_BASE_STATE_ATTACHED) &&
0724         (mode == SDTX_DEVICE_MODE_TABLET)) ||
0725            ((base_state == SSAM_BAS_BASE_STATE_DETACH_SUCCESS) &&
0726         (mode != SDTX_DEVICE_MODE_TABLET));
0727 }
0728 
0729 static void sdtx_device_mode_workfn(struct work_struct *work)
0730 {
0731     struct sdtx_device *ddev = container_of(work, struct sdtx_device, mode_work.work);
0732     struct sdtx_status_event event;
0733     struct ssam_bas_base_info base;
0734     int status, tablet;
0735     u8 mode;
0736 
0737     /* Get operation mode. */
0738     status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &mode);
0739     if (status) {
0740         dev_err(ddev->dev, "failed to get device mode: %d\n", status);
0741         return;
0742     }
0743 
0744     /* Get base info. */
0745     status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &base);
0746     if (status) {
0747         dev_err(ddev->dev, "failed to get base info: %d\n", status);
0748         return;
0749     }
0750 
0751     /*
0752      * In some cases (specifically when attaching the base), the device
0753      * mode isn't updated right away. Thus we check if the device mode
0754      * makes sense for the given base state and try again later if it
0755      * doesn't.
0756      */
0757     if (sdtx_device_mode_invalid(mode, base.state)) {
0758         dev_dbg(ddev->dev, "device mode is invalid, trying again\n");
0759         sdtx_update_device_mode(ddev, SDTX_DEVICE_MODE_DELAY_RECHECK);
0760         return;
0761     }
0762 
0763     mutex_lock(&ddev->write_lock);
0764     clear_bit(SDTX_DEVICE_DIRTY_MODE_BIT, &ddev->flags);
0765 
0766     /* Avoid sending duplicate device-mode events. */
0767     if (ddev->state.device_mode == mode) {
0768         mutex_unlock(&ddev->write_lock);
0769         return;
0770     }
0771 
0772     ddev->state.device_mode = mode;
0773 
0774     event.e.length = sizeof(u16);
0775     event.e.code = SDTX_EVENT_DEVICE_MODE;
0776     event.v = mode;
0777 
0778     sdtx_push_event(ddev, &event.e);
0779 
0780     /* Send SW_TABLET_MODE event. */
0781     tablet = mode != SDTX_DEVICE_MODE_LAPTOP;
0782     input_report_switch(ddev->mode_switch, SW_TABLET_MODE, tablet);
0783     input_sync(ddev->mode_switch);
0784 
0785     mutex_unlock(&ddev->write_lock);
0786 }
0787 
0788 static void sdtx_update_device_mode(struct sdtx_device *ddev, unsigned long delay)
0789 {
0790     schedule_delayed_work(&ddev->mode_work, delay);
0791 }
0792 
0793 /* Must be executed with ddev->write_lock held. */
0794 static void __sdtx_device_state_update_base(struct sdtx_device *ddev,
0795                         struct ssam_bas_base_info info)
0796 {
0797     struct sdtx_base_info_event event;
0798 
0799     lockdep_assert_held(&ddev->write_lock);
0800 
0801     /* Prevent duplicate events. */
0802     if (ddev->state.base.state == info.state &&
0803         ddev->state.base.base_id == info.base_id)
0804         return;
0805 
0806     ddev->state.base = info;
0807 
0808     event.e.length = sizeof(struct sdtx_base_info);
0809     event.e.code = SDTX_EVENT_BASE_CONNECTION;
0810     event.v.state = sdtx_translate_base_state(ddev, info.state);
0811     event.v.base_id = SDTX_BASE_TYPE_SSH(info.base_id);
0812 
0813     sdtx_push_event(ddev, &event.e);
0814 }
0815 
0816 /* Must be executed with ddev->write_lock held. */
0817 static void __sdtx_device_state_update_mode(struct sdtx_device *ddev, u8 mode)
0818 {
0819     struct sdtx_status_event event;
0820     int tablet;
0821 
0822     /*
0823      * Note: This function must be called after updating the base state
0824      * via __sdtx_device_state_update_base(), as we rely on the updated
0825      * base state value in the validity check below.
0826      */
0827 
0828     lockdep_assert_held(&ddev->write_lock);
0829 
0830     if (sdtx_device_mode_invalid(mode, ddev->state.base.state)) {
0831         dev_dbg(ddev->dev, "device mode is invalid, trying again\n");
0832         sdtx_update_device_mode(ddev, SDTX_DEVICE_MODE_DELAY_RECHECK);
0833         return;
0834     }
0835 
0836     /* Prevent duplicate events. */
0837     if (ddev->state.device_mode == mode)
0838         return;
0839 
0840     ddev->state.device_mode = mode;
0841 
0842     /* Send event. */
0843     event.e.length = sizeof(u16);
0844     event.e.code = SDTX_EVENT_DEVICE_MODE;
0845     event.v = mode;
0846 
0847     sdtx_push_event(ddev, &event.e);
0848 
0849     /* Send SW_TABLET_MODE event. */
0850     tablet = mode != SDTX_DEVICE_MODE_LAPTOP;
0851     input_report_switch(ddev->mode_switch, SW_TABLET_MODE, tablet);
0852     input_sync(ddev->mode_switch);
0853 }
0854 
0855 /* Must be executed with ddev->write_lock held. */
0856 static void __sdtx_device_state_update_latch(struct sdtx_device *ddev, u8 status)
0857 {
0858     struct sdtx_status_event event;
0859 
0860     lockdep_assert_held(&ddev->write_lock);
0861 
0862     /* Prevent duplicate events. */
0863     if (ddev->state.latch_status == status)
0864         return;
0865 
0866     ddev->state.latch_status = status;
0867 
0868     event.e.length = sizeof(struct sdtx_base_info);
0869     event.e.code = SDTX_EVENT_BASE_CONNECTION;
0870     event.v = sdtx_translate_latch_status(ddev, status);
0871 
0872     sdtx_push_event(ddev, &event.e);
0873 }
0874 
0875 static void sdtx_device_state_workfn(struct work_struct *work)
0876 {
0877     struct sdtx_device *ddev = container_of(work, struct sdtx_device, state_work.work);
0878     struct ssam_bas_base_info base;
0879     u8 mode, latch;
0880     int status;
0881 
0882     /* Mark everything as dirty. */
0883     set_bit(SDTX_DEVICE_DIRTY_BASE_BIT, &ddev->flags);
0884     set_bit(SDTX_DEVICE_DIRTY_MODE_BIT, &ddev->flags);
0885     set_bit(SDTX_DEVICE_DIRTY_LATCH_BIT, &ddev->flags);
0886 
0887     /*
0888      * Ensure that the state gets marked as dirty before continuing to
0889      * query it. Necessary to ensure that clear_bit() calls in
0890      * sdtx_notifier() and sdtx_device_mode_workfn() actually clear these
0891      * bits if an event is received while updating the state here.
0892      */
0893     smp_mb__after_atomic();
0894 
0895     status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &base);
0896     if (status) {
0897         dev_err(ddev->dev, "failed to get base state: %d\n", status);
0898         return;
0899     }
0900 
0901     status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &mode);
0902     if (status) {
0903         dev_err(ddev->dev, "failed to get device mode: %d\n", status);
0904         return;
0905     }
0906 
0907     status = ssam_retry(ssam_bas_get_latch_status, ddev->ctrl, &latch);
0908     if (status) {
0909         dev_err(ddev->dev, "failed to get latch status: %d\n", status);
0910         return;
0911     }
0912 
0913     mutex_lock(&ddev->write_lock);
0914 
0915     /*
0916      * If the respective dirty-bit has been cleared, an event has been
0917      * received, updating this state. The queried state may thus be out of
0918      * date. At this point, we can safely assume that the state provided
0919      * by the event is either up to date, or we're about to receive
0920      * another event updating it.
0921      */
0922 
0923     if (test_and_clear_bit(SDTX_DEVICE_DIRTY_BASE_BIT, &ddev->flags))
0924         __sdtx_device_state_update_base(ddev, base);
0925 
0926     if (test_and_clear_bit(SDTX_DEVICE_DIRTY_MODE_BIT, &ddev->flags))
0927         __sdtx_device_state_update_mode(ddev, mode);
0928 
0929     if (test_and_clear_bit(SDTX_DEVICE_DIRTY_LATCH_BIT, &ddev->flags))
0930         __sdtx_device_state_update_latch(ddev, latch);
0931 
0932     mutex_unlock(&ddev->write_lock);
0933 }
0934 
0935 static void sdtx_update_device_state(struct sdtx_device *ddev, unsigned long delay)
0936 {
0937     schedule_delayed_work(&ddev->state_work, delay);
0938 }
0939 
0940 
0941 /* -- Common device initialization. ----------------------------------------- */
0942 
0943 static int sdtx_device_init(struct sdtx_device *ddev, struct device *dev,
0944                 struct ssam_controller *ctrl)
0945 {
0946     int status, tablet_mode;
0947 
0948     /* Basic initialization. */
0949     kref_init(&ddev->kref);
0950     init_rwsem(&ddev->lock);
0951     ddev->dev = dev;
0952     ddev->ctrl = ctrl;
0953 
0954     ddev->mdev.minor = MISC_DYNAMIC_MINOR;
0955     ddev->mdev.name = "surface_dtx";
0956     ddev->mdev.nodename = "surface/dtx";
0957     ddev->mdev.fops = &surface_dtx_fops;
0958 
0959     ddev->notif.base.priority = 1;
0960     ddev->notif.base.fn = sdtx_notifier;
0961     ddev->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
0962     ddev->notif.event.id.target_category = SSAM_SSH_TC_BAS;
0963     ddev->notif.event.id.instance = 0;
0964     ddev->notif.event.mask = SSAM_EVENT_MASK_NONE;
0965     ddev->notif.event.flags = SSAM_EVENT_SEQUENCED;
0966 
0967     init_waitqueue_head(&ddev->waitq);
0968     mutex_init(&ddev->write_lock);
0969     init_rwsem(&ddev->client_lock);
0970     INIT_LIST_HEAD(&ddev->client_list);
0971 
0972     INIT_DELAYED_WORK(&ddev->mode_work, sdtx_device_mode_workfn);
0973     INIT_DELAYED_WORK(&ddev->state_work, sdtx_device_state_workfn);
0974 
0975     /*
0976      * Get current device state. We want to guarantee that events are only
0977      * sent when state actually changes. Thus we cannot use special
0978      * "uninitialized" values, as that would cause problems when manually
0979      * querying the state in surface_dtx_pm_complete(). I.e. we would not
0980      * be able to detect state changes there if no change event has been
0981      * received between driver initialization and first device suspension.
0982      *
0983      * Note that we also need to do this before registering the event
0984      * notifier, as that may access the state values.
0985      */
0986     status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &ddev->state.base);
0987     if (status)
0988         return status;
0989 
0990     status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &ddev->state.device_mode);
0991     if (status)
0992         return status;
0993 
0994     status = ssam_retry(ssam_bas_get_latch_status, ddev->ctrl, &ddev->state.latch_status);
0995     if (status)
0996         return status;
0997 
0998     /* Set up tablet mode switch. */
0999     ddev->mode_switch = input_allocate_device();
1000     if (!ddev->mode_switch)
1001         return -ENOMEM;
1002 
1003     ddev->mode_switch->name = "Microsoft Surface DTX Device Mode Switch";
1004     ddev->mode_switch->phys = "ssam/01:11:01:00:00/input0";
1005     ddev->mode_switch->id.bustype = BUS_HOST;
1006     ddev->mode_switch->dev.parent = ddev->dev;
1007 
1008     tablet_mode = (ddev->state.device_mode != SDTX_DEVICE_MODE_LAPTOP);
1009     input_set_capability(ddev->mode_switch, EV_SW, SW_TABLET_MODE);
1010     input_report_switch(ddev->mode_switch, SW_TABLET_MODE, tablet_mode);
1011 
1012     status = input_register_device(ddev->mode_switch);
1013     if (status) {
1014         input_free_device(ddev->mode_switch);
1015         return status;
1016     }
1017 
1018     /* Set up event notifier. */
1019     status = ssam_notifier_register(ddev->ctrl, &ddev->notif);
1020     if (status)
1021         goto err_notif;
1022 
1023     /* Register miscdevice. */
1024     status = misc_register(&ddev->mdev);
1025     if (status)
1026         goto err_mdev;
1027 
1028     /*
1029      * Update device state in case it has changed between getting the
1030      * initial mode and registering the event notifier.
1031      */
1032     sdtx_update_device_state(ddev, 0);
1033     return 0;
1034 
1035 err_notif:
1036     ssam_notifier_unregister(ddev->ctrl, &ddev->notif);
1037     cancel_delayed_work_sync(&ddev->mode_work);
1038 err_mdev:
1039     input_unregister_device(ddev->mode_switch);
1040     return status;
1041 }
1042 
1043 static struct sdtx_device *sdtx_device_create(struct device *dev, struct ssam_controller *ctrl)
1044 {
1045     struct sdtx_device *ddev;
1046     int status;
1047 
1048     ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
1049     if (!ddev)
1050         return ERR_PTR(-ENOMEM);
1051 
1052     status = sdtx_device_init(ddev, dev, ctrl);
1053     if (status) {
1054         sdtx_device_put(ddev);
1055         return ERR_PTR(status);
1056     }
1057 
1058     return ddev;
1059 }
1060 
1061 static void sdtx_device_destroy(struct sdtx_device *ddev)
1062 {
1063     struct sdtx_client *client;
1064 
1065     /*
1066      * Mark device as shut-down. Prevent new clients from being added and
1067      * new operations from being executed.
1068      */
1069     set_bit(SDTX_DEVICE_SHUTDOWN_BIT, &ddev->flags);
1070 
1071     /* Disable notifiers, prevent new events from arriving. */
1072     ssam_notifier_unregister(ddev->ctrl, &ddev->notif);
1073 
1074     /* Stop mode_work, prevent access to mode_switch. */
1075     cancel_delayed_work_sync(&ddev->mode_work);
1076 
1077     /* Stop state_work. */
1078     cancel_delayed_work_sync(&ddev->state_work);
1079 
1080     /* With mode_work canceled, we can unregister the mode_switch. */
1081     input_unregister_device(ddev->mode_switch);
1082 
1083     /* Wake up async clients. */
1084     down_write(&ddev->client_lock);
1085     list_for_each_entry(client, &ddev->client_list, node) {
1086         kill_fasync(&client->fasync, SIGIO, POLL_HUP);
1087     }
1088     up_write(&ddev->client_lock);
1089 
1090     /* Wake up blocking clients. */
1091     wake_up_interruptible(&ddev->waitq);
1092 
1093     /*
1094      * Wait for clients to finish their current operation. After this, the
1095      * controller and device references are guaranteed to be no longer in
1096      * use.
1097      */
1098     down_write(&ddev->lock);
1099     ddev->dev = NULL;
1100     ddev->ctrl = NULL;
1101     up_write(&ddev->lock);
1102 
1103     /* Finally remove the misc-device. */
1104     misc_deregister(&ddev->mdev);
1105 
1106     /*
1107      * We're now guaranteed that sdtx_device_open() won't be called any
1108      * more, so we can now drop out reference.
1109      */
1110     sdtx_device_put(ddev);
1111 }
1112 
1113 
1114 /* -- PM ops. --------------------------------------------------------------- */
1115 
1116 #ifdef CONFIG_PM_SLEEP
1117 
1118 static void surface_dtx_pm_complete(struct device *dev)
1119 {
1120     struct sdtx_device *ddev = dev_get_drvdata(dev);
1121 
1122     /*
1123      * Normally, the EC will store events while suspended (i.e. in
1124      * display-off state) and release them when resumed (i.e. transitioned
1125      * to display-on state). During hibernation, however, the EC will be
1126      * shut down and does not store events. Furthermore, events might be
1127      * dropped during prolonged suspension (it is currently unknown how
1128      * big this event buffer is and how it behaves on overruns).
1129      *
1130      * To prevent any problems, we update the device state here. We do
1131      * this delayed to ensure that any events sent by the EC directly
1132      * after resuming will be handled first. The delay below has been
1133      * chosen (experimentally), so that there should be ample time for
1134      * these events to be handled, before we check and, if necessary,
1135      * update the state.
1136      */
1137     sdtx_update_device_state(ddev, msecs_to_jiffies(1000));
1138 }
1139 
1140 static const struct dev_pm_ops surface_dtx_pm_ops = {
1141     .complete = surface_dtx_pm_complete,
1142 };
1143 
1144 #else /* CONFIG_PM_SLEEP */
1145 
1146 static const struct dev_pm_ops surface_dtx_pm_ops = {};
1147 
1148 #endif /* CONFIG_PM_SLEEP */
1149 
1150 
1151 /* -- Platform driver. ------------------------------------------------------ */
1152 
1153 static int surface_dtx_platform_probe(struct platform_device *pdev)
1154 {
1155     struct ssam_controller *ctrl;
1156     struct sdtx_device *ddev;
1157 
1158     /* Link to EC. */
1159     ctrl = ssam_client_bind(&pdev->dev);
1160     if (IS_ERR(ctrl))
1161         return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl);
1162 
1163     ddev = sdtx_device_create(&pdev->dev, ctrl);
1164     if (IS_ERR(ddev))
1165         return PTR_ERR(ddev);
1166 
1167     platform_set_drvdata(pdev, ddev);
1168     return 0;
1169 }
1170 
1171 static int surface_dtx_platform_remove(struct platform_device *pdev)
1172 {
1173     sdtx_device_destroy(platform_get_drvdata(pdev));
1174     return 0;
1175 }
1176 
1177 static const struct acpi_device_id surface_dtx_acpi_match[] = {
1178     { "MSHW0133", 0 },
1179     { },
1180 };
1181 MODULE_DEVICE_TABLE(acpi, surface_dtx_acpi_match);
1182 
1183 static struct platform_driver surface_dtx_platform_driver = {
1184     .probe = surface_dtx_platform_probe,
1185     .remove = surface_dtx_platform_remove,
1186     .driver = {
1187         .name = "surface_dtx_pltf",
1188         .acpi_match_table = surface_dtx_acpi_match,
1189         .pm = &surface_dtx_pm_ops,
1190         .probe_type = PROBE_PREFER_ASYNCHRONOUS,
1191     },
1192 };
1193 
1194 
1195 /* -- SSAM device driver. --------------------------------------------------- */
1196 
1197 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
1198 
1199 static int surface_dtx_ssam_probe(struct ssam_device *sdev)
1200 {
1201     struct sdtx_device *ddev;
1202 
1203     ddev = sdtx_device_create(&sdev->dev, sdev->ctrl);
1204     if (IS_ERR(ddev))
1205         return PTR_ERR(ddev);
1206 
1207     ssam_device_set_drvdata(sdev, ddev);
1208     return 0;
1209 }
1210 
1211 static void surface_dtx_ssam_remove(struct ssam_device *sdev)
1212 {
1213     sdtx_device_destroy(ssam_device_get_drvdata(sdev));
1214 }
1215 
1216 static const struct ssam_device_id surface_dtx_ssam_match[] = {
1217     { SSAM_SDEV(BAS, 0x01, 0x00, 0x00) },
1218     { },
1219 };
1220 MODULE_DEVICE_TABLE(ssam, surface_dtx_ssam_match);
1221 
1222 static struct ssam_device_driver surface_dtx_ssam_driver = {
1223     .probe = surface_dtx_ssam_probe,
1224     .remove = surface_dtx_ssam_remove,
1225     .match_table = surface_dtx_ssam_match,
1226     .driver = {
1227         .name = "surface_dtx",
1228         .pm = &surface_dtx_pm_ops,
1229         .probe_type = PROBE_PREFER_ASYNCHRONOUS,
1230     },
1231 };
1232 
1233 static int ssam_dtx_driver_register(void)
1234 {
1235     return ssam_device_driver_register(&surface_dtx_ssam_driver);
1236 }
1237 
1238 static void ssam_dtx_driver_unregister(void)
1239 {
1240     ssam_device_driver_unregister(&surface_dtx_ssam_driver);
1241 }
1242 
1243 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
1244 
1245 static int ssam_dtx_driver_register(void)
1246 {
1247     return 0;
1248 }
1249 
1250 static void ssam_dtx_driver_unregister(void)
1251 {
1252 }
1253 
1254 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
1255 
1256 
1257 /* -- Module setup. --------------------------------------------------------- */
1258 
1259 static int __init surface_dtx_init(void)
1260 {
1261     int status;
1262 
1263     status = ssam_dtx_driver_register();
1264     if (status)
1265         return status;
1266 
1267     status = platform_driver_register(&surface_dtx_platform_driver);
1268     if (status)
1269         ssam_dtx_driver_unregister();
1270 
1271     return status;
1272 }
1273 module_init(surface_dtx_init);
1274 
1275 static void __exit surface_dtx_exit(void)
1276 {
1277     platform_driver_unregister(&surface_dtx_platform_driver);
1278     ssam_dtx_driver_unregister();
1279 }
1280 module_exit(surface_dtx_exit);
1281 
1282 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
1283 MODULE_DESCRIPTION("Detachment-system driver for Surface System Aggregator Module");
1284 MODULE_LICENSE("GPL");