/* * vmbus_remove - Remove a vmbus device */ static int vmbus_remove(struct device *child_device) { struct hv_driver *drv; struct hv_device *dev = device_to_hv_device(child_device); u32 relid = dev->channel->offermsg.child_relid; if (child_device->driver) { drv = drv_to_hv_drv(child_device->driver); if (drv->remove) drv->remove(dev); else { hv_process_channel_removal(dev->channel, relid); pr_err("remove not set for driver %s\n", dev_name(child_device)); } } else { /* * We don't have a driver for this device; deal with the * rescind message by removing the channel. */ hv_process_channel_removal(dev->channel, relid); } return 0; }
/* * vmbus_device_release - Final callback release of the vmbus child device */ static void vmbus_device_release(struct device *device) { struct hv_device *hv_dev = device_to_hv_device(device); kfree(hv_dev); }
static ssize_t device_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); return sprintf(buf, "0x%x\n", hv_dev->device_id); }
static ssize_t monitor_id_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); if (!hv_dev->channel) return -ENODEV; return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid); }
static ssize_t modalias_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); char alias_name[VMBUS_ALIAS_LEN + 1]; print_alias_name(hv_dev, alias_name); return sprintf(buf, "vmbus:%s\n", alias_name); }
static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); if (!hv_dev->channel) return -ENODEV; return sprintf(buf, "%d\n", hv_dev->channel->state); }
/* * vmbus_uevent - add uevent for our device * * This routine is invoked when a device is added or removed on the vmbus to * generate a uevent to udev in the userspace. The udev will then look at its * rule and the uevent generated here to load the appropriate driver * * The alias string will be of the form vmbus:guid where guid is the string * representation of the device guid (each byte of the guid will be * represented with two hex characters. */ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) { struct hv_device *dev = device_to_hv_device(device); int ret; char alias_name[VMBUS_ALIAS_LEN + 1]; print_alias_name(dev, alias_name); ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name); return ret; }
static ssize_t device_id_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); if (!hv_dev->channel) return -ENODEV; return sprintf(buf, "{%pUl}\n", hv_dev->channel->offermsg.offer.if_instance.b); }
/* * vmbus_match - Attempt to match the specified device to the specified driver */ static int vmbus_match(struct device *device, struct device_driver *driver) { struct hv_driver *drv = drv_to_hv_drv(driver); struct hv_device *hv_dev = device_to_hv_device(device); if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b)) return 1; return 0; }
static ssize_t in_write_index_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info inbound; if (!hv_dev->channel) return -ENODEV; hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); return sprintf(buf, "%d\n", inbound.current_write_index); }
static ssize_t out_intr_mask_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; if (!hv_dev->channel) return -ENODEV; hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); return sprintf(buf, "%d\n", outbound.current_interrupt_mask); }
static ssize_t client_monitor_conn_id_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); if (!hv_dev->channel) return -ENODEV; return sprintf(buf, "%d\n", channel_conn_id(hv_dev->channel, vmbus_connection.monitor_pages[1])); }
static ssize_t out_write_bytes_avail_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_ring_buffer_debug_info outbound; if (!hv_dev->channel) return -ENODEV; hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); return sprintf(buf, "%d\n", outbound.bytes_avail_towrite); }
static ssize_t server_monitor_latency_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); if (!hv_dev->channel) return -ENODEV; return sprintf(buf, "%d\n", channel_latency(hv_dev->channel, vmbus_connection.monitor_pages[0])); }
/* * vmbus_remove - Remove a vmbus device */ static int vmbus_remove(struct device *child_device) { struct hv_driver *drv = drv_to_hv_drv(child_device->driver); struct hv_device *dev = device_to_hv_device(child_device); if (drv->remove) drv->remove(dev); else pr_err("remove not set for driver %s\n", dev_name(child_device)); return 0; }
/* * vmbus_shutdown - Shutdown a vmbus device */ static void vmbus_shutdown(struct device *child_device) { struct hv_driver *drv; struct hv_device *dev = device_to_hv_device(child_device); /* The device may not be attached yet */ if (!child_device->driver) return; drv = drv_to_hv_drv(child_device->driver); if (drv->shutdown) drv->shutdown(dev); return; }
int vmbus_uevent(struct device *device, char **envp, int num_envp, char *buffer, int buffer_size) { struct hv_device *dev = device_to_hv_device(device); int i = 0; int len = 0; int ret; char alias_name[VMBUS_ALIAS_LEN + 1]; print_alias_name(dev, alias_name); ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, "MODALIAS=vmbus:%s", alias_name); if (ret) return ret; envp[i] = NULL; return 0; }
/* Send updated screen area (dirty rectangle) location to host */ static int synthvid_update(struct fb_info *info) { struct hv_device *hdev = device_to_hv_device(info->device); struct synthvid_msg msg; memset(&msg, 0, sizeof(struct synthvid_msg)); msg.vid_hdr.type = SYNTHVID_DIRT; msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + sizeof(struct synthvid_dirt); msg.dirt.video_output = 0; msg.dirt.dirt_count = 1; msg.dirt.rect[0].x1 = 0; msg.dirt.rect[0].y1 = 0; msg.dirt.rect[0].x2 = info->var.xres; msg.dirt.rect[0].y2 = info->var.yres; synthvid_send(hdev, &msg); return 0; }
/* * vmbus_probe - Add the new vmbus's child device */ static int vmbus_probe(struct device *child_device) { int ret = 0; struct hv_driver *drv = drv_to_hv_drv(child_device->driver); struct hv_device *dev = device_to_hv_device(child_device); const struct hv_vmbus_device_id *dev_id; dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b); if (drv->probe) { ret = drv->probe(dev, dev_id); if (ret != 0) pr_err("probe failed for device %s (%d)\n", dev_name(child_device), ret); } else { pr_err("probe not set for driver %s\n", dev_name(child_device)); ret = -ENODEV; } return ret; }
/* * vmbus_show_device_attr - Show the device attribute in sysfs. * * This is invoked when user does a * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>" */ static ssize_t vmbus_show_device_attr(struct device *dev, struct device_attribute *dev_attr, char *buf) { struct hv_device *hv_dev = device_to_hv_device(dev); struct hv_device_info *device_info; char alias_name[VMBUS_ALIAS_LEN + 1]; int ret = 0; device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL); if (!device_info) return ret; get_channel_info(hv_dev, device_info); if (!strcmp(dev_attr->attr.name, "class_id")) { ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b); } else if (!strcmp(dev_attr->attr.name, "device_id")) { ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b); } else if (!strcmp(dev_attr->attr.name, "modalias")) { print_alias_name(hv_dev, alias_name); ret = sprintf(buf, "vmbus:%s\n", alias_name); } else if (!strcmp(dev_attr->attr.name, "state")) { ret = sprintf(buf, "%d\n", device_info->chn_state); } else if (!strcmp(dev_attr->attr.name, "id")) { ret = sprintf(buf, "%d\n", device_info->chn_id); } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { ret = sprintf(buf, "%d\n", device_info->outbound.read_idx); } else if (!strcmp(dev_attr->attr.name, "out_write_index")) { ret = sprintf(buf, "%d\n", device_info->outbound.write_idx); } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->outbound.bytes_avail_toread); } else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->outbound.bytes_avail_towrite); } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) { ret = sprintf(buf, "%d\n", device_info->inbound.int_mask); } else if (!strcmp(dev_attr->attr.name, "in_read_index")) { ret = sprintf(buf, "%d\n", device_info->inbound.read_idx); } else if (!strcmp(dev_attr->attr.name, "in_write_index")) { ret = sprintf(buf, "%d\n", device_info->inbound.write_idx); } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_toread); } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { ret = sprintf(buf, "%d\n", device_info->inbound.bytes_avail_towrite); } else if (!strcmp(dev_attr->attr.name, "monitor_id")) { ret = sprintf(buf, "%d\n", device_info->monitor_id); } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { ret = sprintf(buf, "%d\n", device_info->server_monitor_conn_id); } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) { ret = sprintf(buf, "%d\n", device_info->client_monitor_pending); } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { ret = sprintf(buf, "%d\n", device_info->client_monitor_latency); } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { ret = sprintf(buf, "%d\n", device_info->client_monitor_conn_id); } kfree(device_info); return ret; }
static int hvfb_set_par(struct fb_info *info) { struct hv_device *hdev = device_to_hv_device(info->device); return synthvid_send_situ(hdev); }