1 /* 2 * Copyright (c) 2017 Red Hat, Inc 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 as published by 6 * the Free Software Foundation. 7 */ 8 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/libps2.h> 14 #include <linux/i2c.h> 15 #include <linux/serio.h> 16 #include <linux/slab.h> 17 #include <linux/workqueue.h> 18 #include "psmouse.h" 19 20 struct psmouse_smbus_dev { 21 struct i2c_board_info board; 22 struct psmouse *psmouse; 23 struct i2c_client *client; 24 struct list_head node; 25 bool dead; 26 bool need_deactivate; 27 }; 28 29 static LIST_HEAD(psmouse_smbus_list); 30 static DEFINE_MUTEX(psmouse_smbus_mutex); 31 32 static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter) 33 { 34 struct psmouse_smbus_dev *smbdev; 35 36 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) 37 return; 38 39 mutex_lock(&psmouse_smbus_mutex); 40 41 list_for_each_entry(smbdev, &psmouse_smbus_list, node) { 42 if (smbdev->dead) 43 continue; 44 45 if (smbdev->client) 46 continue; 47 48 /* 49 * Here would be a good place to check if device is actually 50 * present, but it seems that SMBus will not respond unless we 51 * fully reset PS/2 connection. So cross our fingers, and try 52 * to switch over, hopefully our system will not have too many 53 * "host notify" I2C adapters. 54 */ 55 psmouse_dbg(smbdev->psmouse, 56 "SMBus candidate adapter appeared, triggering rescan\n"); 57 serio_rescan(smbdev->psmouse->ps2dev.serio); 58 } 59 60 mutex_unlock(&psmouse_smbus_mutex); 61 } 62 63 static void psmouse_smbus_detach_i2c_client(struct i2c_client *client) 64 { 65 struct psmouse_smbus_dev *smbdev, *tmp; 66 67 mutex_lock(&psmouse_smbus_mutex); 68 69 list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) { 70 if (smbdev->client != client) 71 continue; 72 73 kfree(client->dev.platform_data); 74 client->dev.platform_data = NULL; 75 76 if (!smbdev->dead) { 77 psmouse_dbg(smbdev->psmouse, 78 "Marking SMBus companion %s as gone\n", 79 dev_name(&smbdev->client->dev)); 80 smbdev->dead = true; 81 serio_rescan(smbdev->psmouse->ps2dev.serio); 82 } else { 83 list_del(&smbdev->node); 84 kfree(smbdev); 85 } 86 } 87 88 mutex_unlock(&psmouse_smbus_mutex); 89 } 90 91 static int psmouse_smbus_notifier_call(struct notifier_block *nb, 92 unsigned long action, void *data) 93 { 94 struct device *dev = data; 95 96 switch (action) { 97 case BUS_NOTIFY_ADD_DEVICE: 98 if (dev->type == &i2c_adapter_type) 99 psmouse_smbus_check_adapter(to_i2c_adapter(dev)); 100 break; 101 102 case BUS_NOTIFY_REMOVED_DEVICE: 103 if (dev->type == &i2c_client_type) 104 psmouse_smbus_detach_i2c_client(to_i2c_client(dev)); 105 break; 106 } 107 108 return 0; 109 } 110 111 static struct notifier_block psmouse_smbus_notifier = { 112 .notifier_call = psmouse_smbus_notifier_call, 113 }; 114 115 static psmouse_ret_t psmouse_smbus_process_byte(struct psmouse *psmouse) 116 { 117 return PSMOUSE_FULL_PACKET; 118 } 119 120 static int psmouse_smbus_reconnect(struct psmouse *psmouse) 121 { 122 struct psmouse_smbus_dev *smbdev = psmouse->private; 123 124 if (smbdev->need_deactivate) 125 psmouse_deactivate(psmouse); 126 127 return 0; 128 } 129 130 struct psmouse_smbus_removal_work { 131 struct work_struct work; 132 struct i2c_client *client; 133 }; 134 135 static void psmouse_smbus_remove_i2c_device(struct work_struct *work) 136 { 137 struct psmouse_smbus_removal_work *rwork = 138 container_of(work, struct psmouse_smbus_removal_work, work); 139 140 dev_dbg(&rwork->client->dev, "destroying SMBus companion device\n"); 141 i2c_unregister_device(rwork->client); 142 143 kfree(rwork); 144 } 145 146 /* 147 * This schedules removal of SMBus companion device. We have to do 148 * it in a separate tread to avoid deadlocking on psmouse_mutex in 149 * case the device has a trackstick (which is also driven by psmouse). 150 * 151 * Note that this may be racing with i2c adapter removal, but we 152 * can't do anything about that: i2c automatically destroys clients 153 * attached to an adapter that is being removed. This has to be 154 * fixed in i2c core. 155 */ 156 static void psmouse_smbus_schedule_remove(struct i2c_client *client) 157 { 158 struct psmouse_smbus_removal_work *rwork; 159 160 rwork = kzalloc(sizeof(*rwork), GFP_KERNEL); 161 if (rwork) { 162 INIT_WORK(&rwork->work, psmouse_smbus_remove_i2c_device); 163 rwork->client = client; 164 165 schedule_work(&rwork->work); 166 } 167 } 168 169 static void psmouse_smbus_disconnect(struct psmouse *psmouse) 170 { 171 struct psmouse_smbus_dev *smbdev = psmouse->private; 172 173 mutex_lock(&psmouse_smbus_mutex); 174 175 if (smbdev->dead) { 176 list_del(&smbdev->node); 177 kfree(smbdev); 178 } else { 179 smbdev->dead = true; 180 psmouse_dbg(smbdev->psmouse, 181 "posting removal request for SMBus companion %s\n", 182 dev_name(&smbdev->client->dev)); 183 psmouse_smbus_schedule_remove(smbdev->client); 184 } 185 186 mutex_unlock(&psmouse_smbus_mutex); 187 188 psmouse->private = NULL; 189 } 190 191 static int psmouse_smbus_create_companion(struct device *dev, void *data) 192 { 193 struct psmouse_smbus_dev *smbdev = data; 194 unsigned short addr_list[] = { smbdev->board.addr, I2C_CLIENT_END }; 195 struct i2c_adapter *adapter; 196 197 adapter = i2c_verify_adapter(dev); 198 if (!adapter) 199 return 0; 200 201 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) 202 return 0; 203 204 smbdev->client = i2c_new_probed_device(adapter, &smbdev->board, 205 addr_list, NULL); 206 if (!smbdev->client) 207 return 0; 208 209 /* We have our(?) device, stop iterating i2c bus. */ 210 return 1; 211 } 212 213 void psmouse_smbus_cleanup(struct psmouse *psmouse) 214 { 215 struct psmouse_smbus_dev *smbdev, *tmp; 216 217 mutex_lock(&psmouse_smbus_mutex); 218 219 list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) { 220 if (psmouse == smbdev->psmouse) { 221 list_del(&smbdev->node); 222 kfree(smbdev); 223 } 224 } 225 226 mutex_unlock(&psmouse_smbus_mutex); 227 } 228 229 int psmouse_smbus_init(struct psmouse *psmouse, 230 const struct i2c_board_info *board, 231 const void *pdata, size_t pdata_size, 232 bool need_deactivate, 233 bool leave_breadcrumbs) 234 { 235 struct psmouse_smbus_dev *smbdev; 236 int error; 237 238 smbdev = kzalloc(sizeof(*smbdev), GFP_KERNEL); 239 if (!smbdev) 240 return -ENOMEM; 241 242 smbdev->psmouse = psmouse; 243 smbdev->board = *board; 244 smbdev->need_deactivate = need_deactivate; 245 246 if (pdata) { 247 smbdev->board.platform_data = kmemdup(pdata, pdata_size, 248 GFP_KERNEL); 249 if (!smbdev->board.platform_data) { 250 kfree(smbdev); 251 return -ENOMEM; 252 } 253 } 254 255 if (need_deactivate) 256 psmouse_deactivate(psmouse); 257 258 psmouse->private = smbdev; 259 psmouse->protocol_handler = psmouse_smbus_process_byte; 260 psmouse->reconnect = psmouse_smbus_reconnect; 261 psmouse->fast_reconnect = psmouse_smbus_reconnect; 262 psmouse->disconnect = psmouse_smbus_disconnect; 263 psmouse->resync_time = 0; 264 265 mutex_lock(&psmouse_smbus_mutex); 266 list_add_tail(&smbdev->node, &psmouse_smbus_list); 267 mutex_unlock(&psmouse_smbus_mutex); 268 269 /* Bind to already existing adapters right away */ 270 error = i2c_for_each_dev(smbdev, psmouse_smbus_create_companion); 271 272 if (smbdev->client) { 273 /* We have our companion device */ 274 return 0; 275 } 276 277 /* 278 * If we did not create i2c device we will not need platform 279 * data even if we are leaving breadcrumbs. 280 */ 281 kfree(smbdev->board.platform_data); 282 smbdev->board.platform_data = NULL; 283 284 if (error < 0 || !leave_breadcrumbs) { 285 mutex_lock(&psmouse_smbus_mutex); 286 list_del(&smbdev->node); 287 mutex_unlock(&psmouse_smbus_mutex); 288 289 kfree(smbdev); 290 } 291 292 return error < 0 ? error : -EAGAIN; 293 } 294 295 int __init psmouse_smbus_module_init(void) 296 { 297 int error; 298 299 error = bus_register_notifier(&i2c_bus_type, &psmouse_smbus_notifier); 300 if (error) { 301 pr_err("failed to register i2c bus notifier: %d\n", error); 302 return error; 303 } 304 305 return 0; 306 } 307 308 void psmouse_smbus_module_exit(void) 309 { 310 bus_unregister_notifier(&i2c_bus_type, &psmouse_smbus_notifier); 311 flush_scheduled_work(); 312 } 313