1*8465def4SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2*8465def4SGreg Kroah-Hartman /* 3*8465def4SGreg Kroah-Hartman * Greybus Module code 4*8465def4SGreg Kroah-Hartman * 5*8465def4SGreg Kroah-Hartman * Copyright 2016 Google Inc. 6*8465def4SGreg Kroah-Hartman * Copyright 2016 Linaro Ltd. 7*8465def4SGreg Kroah-Hartman */ 8*8465def4SGreg Kroah-Hartman 9*8465def4SGreg Kroah-Hartman #include <linux/greybus.h> 10*8465def4SGreg Kroah-Hartman #include "greybus_trace.h" 11*8465def4SGreg Kroah-Hartman 12*8465def4SGreg Kroah-Hartman static ssize_t eject_store(struct device *dev, 13*8465def4SGreg Kroah-Hartman struct device_attribute *attr, 14*8465def4SGreg Kroah-Hartman const char *buf, size_t len) 15*8465def4SGreg Kroah-Hartman { 16*8465def4SGreg Kroah-Hartman struct gb_module *module = to_gb_module(dev); 17*8465def4SGreg Kroah-Hartman struct gb_interface *intf; 18*8465def4SGreg Kroah-Hartman size_t i; 19*8465def4SGreg Kroah-Hartman long val; 20*8465def4SGreg Kroah-Hartman int ret; 21*8465def4SGreg Kroah-Hartman 22*8465def4SGreg Kroah-Hartman ret = kstrtol(buf, 0, &val); 23*8465def4SGreg Kroah-Hartman if (ret) 24*8465def4SGreg Kroah-Hartman return ret; 25*8465def4SGreg Kroah-Hartman 26*8465def4SGreg Kroah-Hartman if (!val) 27*8465def4SGreg Kroah-Hartman return len; 28*8465def4SGreg Kroah-Hartman 29*8465def4SGreg Kroah-Hartman for (i = 0; i < module->num_interfaces; ++i) { 30*8465def4SGreg Kroah-Hartman intf = module->interfaces[i]; 31*8465def4SGreg Kroah-Hartman 32*8465def4SGreg Kroah-Hartman mutex_lock(&intf->mutex); 33*8465def4SGreg Kroah-Hartman /* Set flag to prevent concurrent activation. */ 34*8465def4SGreg Kroah-Hartman intf->ejected = true; 35*8465def4SGreg Kroah-Hartman gb_interface_disable(intf); 36*8465def4SGreg Kroah-Hartman gb_interface_deactivate(intf); 37*8465def4SGreg Kroah-Hartman mutex_unlock(&intf->mutex); 38*8465def4SGreg Kroah-Hartman } 39*8465def4SGreg Kroah-Hartman 40*8465def4SGreg Kroah-Hartman /* Tell the SVC to eject the primary interface. */ 41*8465def4SGreg Kroah-Hartman ret = gb_svc_intf_eject(module->hd->svc, module->module_id); 42*8465def4SGreg Kroah-Hartman if (ret) 43*8465def4SGreg Kroah-Hartman return ret; 44*8465def4SGreg Kroah-Hartman 45*8465def4SGreg Kroah-Hartman return len; 46*8465def4SGreg Kroah-Hartman } 47*8465def4SGreg Kroah-Hartman static DEVICE_ATTR_WO(eject); 48*8465def4SGreg Kroah-Hartman 49*8465def4SGreg Kroah-Hartman static ssize_t module_id_show(struct device *dev, 50*8465def4SGreg Kroah-Hartman struct device_attribute *attr, char *buf) 51*8465def4SGreg Kroah-Hartman { 52*8465def4SGreg Kroah-Hartman struct gb_module *module = to_gb_module(dev); 53*8465def4SGreg Kroah-Hartman 54*8465def4SGreg Kroah-Hartman return sprintf(buf, "%u\n", module->module_id); 55*8465def4SGreg Kroah-Hartman } 56*8465def4SGreg Kroah-Hartman static DEVICE_ATTR_RO(module_id); 57*8465def4SGreg Kroah-Hartman 58*8465def4SGreg Kroah-Hartman static ssize_t num_interfaces_show(struct device *dev, 59*8465def4SGreg Kroah-Hartman struct device_attribute *attr, char *buf) 60*8465def4SGreg Kroah-Hartman { 61*8465def4SGreg Kroah-Hartman struct gb_module *module = to_gb_module(dev); 62*8465def4SGreg Kroah-Hartman 63*8465def4SGreg Kroah-Hartman return sprintf(buf, "%zu\n", module->num_interfaces); 64*8465def4SGreg Kroah-Hartman } 65*8465def4SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_interfaces); 66*8465def4SGreg Kroah-Hartman 67*8465def4SGreg Kroah-Hartman static struct attribute *module_attrs[] = { 68*8465def4SGreg Kroah-Hartman &dev_attr_eject.attr, 69*8465def4SGreg Kroah-Hartman &dev_attr_module_id.attr, 70*8465def4SGreg Kroah-Hartman &dev_attr_num_interfaces.attr, 71*8465def4SGreg Kroah-Hartman NULL, 72*8465def4SGreg Kroah-Hartman }; 73*8465def4SGreg Kroah-Hartman ATTRIBUTE_GROUPS(module); 74*8465def4SGreg Kroah-Hartman 75*8465def4SGreg Kroah-Hartman static void gb_module_release(struct device *dev) 76*8465def4SGreg Kroah-Hartman { 77*8465def4SGreg Kroah-Hartman struct gb_module *module = to_gb_module(dev); 78*8465def4SGreg Kroah-Hartman 79*8465def4SGreg Kroah-Hartman trace_gb_module_release(module); 80*8465def4SGreg Kroah-Hartman 81*8465def4SGreg Kroah-Hartman kfree(module); 82*8465def4SGreg Kroah-Hartman } 83*8465def4SGreg Kroah-Hartman 84*8465def4SGreg Kroah-Hartman struct device_type greybus_module_type = { 85*8465def4SGreg Kroah-Hartman .name = "greybus_module", 86*8465def4SGreg Kroah-Hartman .release = gb_module_release, 87*8465def4SGreg Kroah-Hartman }; 88*8465def4SGreg Kroah-Hartman 89*8465def4SGreg Kroah-Hartman struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, 90*8465def4SGreg Kroah-Hartman size_t num_interfaces) 91*8465def4SGreg Kroah-Hartman { 92*8465def4SGreg Kroah-Hartman struct gb_interface *intf; 93*8465def4SGreg Kroah-Hartman struct gb_module *module; 94*8465def4SGreg Kroah-Hartman int i; 95*8465def4SGreg Kroah-Hartman 96*8465def4SGreg Kroah-Hartman module = kzalloc(struct_size(module, interfaces, num_interfaces), 97*8465def4SGreg Kroah-Hartman GFP_KERNEL); 98*8465def4SGreg Kroah-Hartman if (!module) 99*8465def4SGreg Kroah-Hartman return NULL; 100*8465def4SGreg Kroah-Hartman 101*8465def4SGreg Kroah-Hartman module->hd = hd; 102*8465def4SGreg Kroah-Hartman module->module_id = module_id; 103*8465def4SGreg Kroah-Hartman module->num_interfaces = num_interfaces; 104*8465def4SGreg Kroah-Hartman 105*8465def4SGreg Kroah-Hartman module->dev.parent = &hd->dev; 106*8465def4SGreg Kroah-Hartman module->dev.bus = &greybus_bus_type; 107*8465def4SGreg Kroah-Hartman module->dev.type = &greybus_module_type; 108*8465def4SGreg Kroah-Hartman module->dev.groups = module_groups; 109*8465def4SGreg Kroah-Hartman module->dev.dma_mask = hd->dev.dma_mask; 110*8465def4SGreg Kroah-Hartman device_initialize(&module->dev); 111*8465def4SGreg Kroah-Hartman dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); 112*8465def4SGreg Kroah-Hartman 113*8465def4SGreg Kroah-Hartman trace_gb_module_create(module); 114*8465def4SGreg Kroah-Hartman 115*8465def4SGreg Kroah-Hartman for (i = 0; i < num_interfaces; ++i) { 116*8465def4SGreg Kroah-Hartman intf = gb_interface_create(module, module_id + i); 117*8465def4SGreg Kroah-Hartman if (!intf) { 118*8465def4SGreg Kroah-Hartman dev_err(&module->dev, "failed to create interface %u\n", 119*8465def4SGreg Kroah-Hartman module_id + i); 120*8465def4SGreg Kroah-Hartman goto err_put_interfaces; 121*8465def4SGreg Kroah-Hartman } 122*8465def4SGreg Kroah-Hartman module->interfaces[i] = intf; 123*8465def4SGreg Kroah-Hartman } 124*8465def4SGreg Kroah-Hartman 125*8465def4SGreg Kroah-Hartman return module; 126*8465def4SGreg Kroah-Hartman 127*8465def4SGreg Kroah-Hartman err_put_interfaces: 128*8465def4SGreg Kroah-Hartman for (--i; i >= 0; --i) 129*8465def4SGreg Kroah-Hartman gb_interface_put(module->interfaces[i]); 130*8465def4SGreg Kroah-Hartman 131*8465def4SGreg Kroah-Hartman put_device(&module->dev); 132*8465def4SGreg Kroah-Hartman 133*8465def4SGreg Kroah-Hartman return NULL; 134*8465def4SGreg Kroah-Hartman } 135*8465def4SGreg Kroah-Hartman 136*8465def4SGreg Kroah-Hartman /* 137*8465def4SGreg Kroah-Hartman * Register and enable an interface after first attempting to activate it. 138*8465def4SGreg Kroah-Hartman */ 139*8465def4SGreg Kroah-Hartman static void gb_module_register_interface(struct gb_interface *intf) 140*8465def4SGreg Kroah-Hartman { 141*8465def4SGreg Kroah-Hartman struct gb_module *module = intf->module; 142*8465def4SGreg Kroah-Hartman u8 intf_id = intf->interface_id; 143*8465def4SGreg Kroah-Hartman int ret; 144*8465def4SGreg Kroah-Hartman 145*8465def4SGreg Kroah-Hartman mutex_lock(&intf->mutex); 146*8465def4SGreg Kroah-Hartman 147*8465def4SGreg Kroah-Hartman ret = gb_interface_activate(intf); 148*8465def4SGreg Kroah-Hartman if (ret) { 149*8465def4SGreg Kroah-Hartman if (intf->type != GB_INTERFACE_TYPE_DUMMY) { 150*8465def4SGreg Kroah-Hartman dev_err(&module->dev, 151*8465def4SGreg Kroah-Hartman "failed to activate interface %u: %d\n", 152*8465def4SGreg Kroah-Hartman intf_id, ret); 153*8465def4SGreg Kroah-Hartman } 154*8465def4SGreg Kroah-Hartman 155*8465def4SGreg Kroah-Hartman gb_interface_add(intf); 156*8465def4SGreg Kroah-Hartman goto err_unlock; 157*8465def4SGreg Kroah-Hartman } 158*8465def4SGreg Kroah-Hartman 159*8465def4SGreg Kroah-Hartman ret = gb_interface_add(intf); 160*8465def4SGreg Kroah-Hartman if (ret) 161*8465def4SGreg Kroah-Hartman goto err_interface_deactivate; 162*8465def4SGreg Kroah-Hartman 163*8465def4SGreg Kroah-Hartman ret = gb_interface_enable(intf); 164*8465def4SGreg Kroah-Hartman if (ret) { 165*8465def4SGreg Kroah-Hartman dev_err(&module->dev, "failed to enable interface %u: %d\n", 166*8465def4SGreg Kroah-Hartman intf_id, ret); 167*8465def4SGreg Kroah-Hartman goto err_interface_deactivate; 168*8465def4SGreg Kroah-Hartman } 169*8465def4SGreg Kroah-Hartman 170*8465def4SGreg Kroah-Hartman mutex_unlock(&intf->mutex); 171*8465def4SGreg Kroah-Hartman 172*8465def4SGreg Kroah-Hartman return; 173*8465def4SGreg Kroah-Hartman 174*8465def4SGreg Kroah-Hartman err_interface_deactivate: 175*8465def4SGreg Kroah-Hartman gb_interface_deactivate(intf); 176*8465def4SGreg Kroah-Hartman err_unlock: 177*8465def4SGreg Kroah-Hartman mutex_unlock(&intf->mutex); 178*8465def4SGreg Kroah-Hartman } 179*8465def4SGreg Kroah-Hartman 180*8465def4SGreg Kroah-Hartman static void gb_module_deregister_interface(struct gb_interface *intf) 181*8465def4SGreg Kroah-Hartman { 182*8465def4SGreg Kroah-Hartman /* Mark as disconnected to prevent I/O during disable. */ 183*8465def4SGreg Kroah-Hartman if (intf->module->disconnected) 184*8465def4SGreg Kroah-Hartman intf->disconnected = true; 185*8465def4SGreg Kroah-Hartman 186*8465def4SGreg Kroah-Hartman mutex_lock(&intf->mutex); 187*8465def4SGreg Kroah-Hartman intf->removed = true; 188*8465def4SGreg Kroah-Hartman gb_interface_disable(intf); 189*8465def4SGreg Kroah-Hartman gb_interface_deactivate(intf); 190*8465def4SGreg Kroah-Hartman mutex_unlock(&intf->mutex); 191*8465def4SGreg Kroah-Hartman 192*8465def4SGreg Kroah-Hartman gb_interface_del(intf); 193*8465def4SGreg Kroah-Hartman } 194*8465def4SGreg Kroah-Hartman 195*8465def4SGreg Kroah-Hartman /* Register a module and its interfaces. */ 196*8465def4SGreg Kroah-Hartman int gb_module_add(struct gb_module *module) 197*8465def4SGreg Kroah-Hartman { 198*8465def4SGreg Kroah-Hartman size_t i; 199*8465def4SGreg Kroah-Hartman int ret; 200*8465def4SGreg Kroah-Hartman 201*8465def4SGreg Kroah-Hartman ret = device_add(&module->dev); 202*8465def4SGreg Kroah-Hartman if (ret) { 203*8465def4SGreg Kroah-Hartman dev_err(&module->dev, "failed to register module: %d\n", ret); 204*8465def4SGreg Kroah-Hartman return ret; 205*8465def4SGreg Kroah-Hartman } 206*8465def4SGreg Kroah-Hartman 207*8465def4SGreg Kroah-Hartman trace_gb_module_add(module); 208*8465def4SGreg Kroah-Hartman 209*8465def4SGreg Kroah-Hartman for (i = 0; i < module->num_interfaces; ++i) 210*8465def4SGreg Kroah-Hartman gb_module_register_interface(module->interfaces[i]); 211*8465def4SGreg Kroah-Hartman 212*8465def4SGreg Kroah-Hartman return 0; 213*8465def4SGreg Kroah-Hartman } 214*8465def4SGreg Kroah-Hartman 215*8465def4SGreg Kroah-Hartman /* Deregister a module and its interfaces. */ 216*8465def4SGreg Kroah-Hartman void gb_module_del(struct gb_module *module) 217*8465def4SGreg Kroah-Hartman { 218*8465def4SGreg Kroah-Hartman size_t i; 219*8465def4SGreg Kroah-Hartman 220*8465def4SGreg Kroah-Hartman for (i = 0; i < module->num_interfaces; ++i) 221*8465def4SGreg Kroah-Hartman gb_module_deregister_interface(module->interfaces[i]); 222*8465def4SGreg Kroah-Hartman 223*8465def4SGreg Kroah-Hartman trace_gb_module_del(module); 224*8465def4SGreg Kroah-Hartman 225*8465def4SGreg Kroah-Hartman device_del(&module->dev); 226*8465def4SGreg Kroah-Hartman } 227*8465def4SGreg Kroah-Hartman 228*8465def4SGreg Kroah-Hartman void gb_module_put(struct gb_module *module) 229*8465def4SGreg Kroah-Hartman { 230*8465def4SGreg Kroah-Hartman size_t i; 231*8465def4SGreg Kroah-Hartman 232*8465def4SGreg Kroah-Hartman for (i = 0; i < module->num_interfaces; ++i) 233*8465def4SGreg Kroah-Hartman gb_interface_put(module->interfaces[i]); 234*8465def4SGreg Kroah-Hartman 235*8465def4SGreg Kroah-Hartman put_device(&module->dev); 236*8465def4SGreg Kroah-Hartman } 237