From: Jake Oshins <jakeo@microsoft.com>
To: rafael.j.wysocki@intel.com, gregkh@linuxfoundation.org,
kys@microsoft.com, linux-kernel@vger.kernel.org,
devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com,
vkuznets@redhat.com
Cc: Jake Oshins <jakeo@microsoft.com>
Subject: [PATCH 2/3] drivers:hv Convert VMBus and its descendants to PnP
Date: Tue, 17 Feb 2015 11:41:50 -0800 [thread overview]
Message-ID: <1424202111-14461-2-git-send-email-jakeo@microsoft.com> (raw)
In-Reply-To: <1424202111-14461-1-git-send-email-jakeo@microsoft.com>
This patch adds paravirtual "devices" discovered by hv_vmbus to the
pnp layer, and adds any memory-mapped I/O space claims expressed
by those paravirtual devices to the "options" for that device in pnp.
This allows the pnp layer to choose the memory-mapped I/O space that
those paravirtual devices use.
Signed-off-by: Jake Oshins <jakeo@microsoft.com>
---
drivers/hid/hid-hyperv.c | 6 +--
drivers/hv/channel_mgmt.c | 5 ++-
drivers/hv/hyperv_vmbus.h | 1 +
drivers/hv/vmbus_drv.c | 69 +++++++++++++++++++++++++++--------
drivers/input/serio/hyperv-keyboard.c | 24 ++++++------
drivers/net/hyperv/netvsc.c | 5 ++-
drivers/net/hyperv/netvsc_drv.c | 4 +-
drivers/net/hyperv/rndis_filter.c | 4 +-
drivers/scsi/storvsc_drv.c | 2 +-
drivers/video/fbdev/hyperv_fb.c | 2 +-
include/linux/hyperv.h | 15 ++++++--
11 files changed, 93 insertions(+), 44 deletions(-)
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 6039f07..0cf9105 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -309,7 +309,7 @@ static void mousevsc_on_receive(struct hv_device *device,
hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
input_dev->input_buf, len, 1);
- pm_wakeup_event(&input_dev->device->device, 0);
+ pm_wakeup_event(&input_dev->device->pnp_dev->dev, 0);
break;
default:
@@ -552,7 +552,7 @@ static int mousevsc_probe(struct hv_device *device,
goto probe_err2;
}
- device_init_wakeup(&device->device, true);
+ device_init_wakeup(&device->pnp_dev->dev, true);
input_dev->connected = true;
input_dev->init_complete = true;
@@ -576,7 +576,7 @@ static int mousevsc_remove(struct hv_device *dev)
{
struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
- device_init_wakeup(&dev->device, false);
+ device_init_wakeup(&dev->pnp_dev->dev, false);
vmbus_close(dev->channel);
hid_hw_stop(input_dev->hid_device);
hid_destroy_device(input_dev->hid_device);
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 3736f71..fcb1be8 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -218,8 +218,8 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
struct vmbus_channel_relid_released msg;
struct device *dev;
- if (channel->device_obj) {
- dev = get_device(&channel->device_obj->device);
+ if (channel->device_obj && channel->device_obj->pnp_dev) {
+ dev = get_device(&channel->device_obj->pnp_dev->dev);
if (dev) {
vmbus_device_unregister(channel->device_obj);
put_device(dev);
@@ -359,6 +359,7 @@ static void vmbus_process_offer(struct work_struct *work)
newchannel->device_obj = vmbus_device_create(
&newchannel->offermsg.offer.if_type,
&newchannel->offermsg.offer.if_instance,
+ newchannel->offermsg.offer.mmio_megabytes,
newchannel);
if (!newchannel->device_obj)
goto err_free_chan;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 44b1c94..73b9bc0 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -676,6 +676,7 @@ extern struct vmbus_connection vmbus_connection;
struct hv_device *vmbus_device_create(const uuid_le *type,
const uuid_le *instance,
+ u16 mmio_mb,
struct vmbus_channel *channel);
int vmbus_device_register(struct hv_device *child_device_obj);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index f518b8d7..5d85ef3 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -549,10 +549,13 @@ static void vmbus_device_release(struct device *device)
{
struct hv_device *hv_dev = device_to_hv_device(device);
- kfree(hv_dev);
+ if (hv_dev->pnp_dev)
+ free_pnp_descendant(hv_dev->pnp_dev);
+ kfree(hv_dev);
}
+
/* The one and only one */
static struct bus_type hv_bus = {
.name = "vmbus",
@@ -814,6 +817,7 @@ EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
*/
struct hv_device *vmbus_device_create(const uuid_le *type,
const uuid_le *instance,
+ u16 mmio_mb,
struct vmbus_channel *channel)
{
struct hv_device *child_device_obj;
@@ -825,6 +829,7 @@ struct hv_device *vmbus_device_create(const uuid_le *type,
}
child_device_obj->channel = channel;
+ child_device_obj->mmio_mb = mmio_mb;
memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
memcpy(&child_device_obj->dev_instance, instance,
sizeof(uuid_le));
@@ -839,27 +844,59 @@ struct hv_device *vmbus_device_create(const uuid_le *type,
int vmbus_device_register(struct hv_device *child_device_obj)
{
int ret = 0;
-
+ char device_id[40];
+ bool added = FALSE;
+ resource_size_t bytes = child_device_obj->mmio_mb * 0x100000;
static atomic_t device_num = ATOMIC_INIT(0);
- dev_set_name(&child_device_obj->device, "vmbus_0_%d",
+
+ sprintf(device_id, "{%pUl}", child_device_obj->dev_instance.b);
+ child_device_obj->pnp_dev = alloc_pnp_descendant(device_id);
+ if (!child_device_obj->pnp_dev)
+ return -ENOMEM;
+
+ dev_set_name(&child_device_obj->pnp_dev->dev, "vmbus_0_%d",
atomic_inc_return(&device_num));
- child_device_obj->device.bus = &hv_bus;
- child_device_obj->device.parent = &hv_acpi_dev->dev;
- child_device_obj->device.release = vmbus_device_release;
+ child_device_obj->pnp_dev->data = child_device_obj;
+ child_device_obj->pnp_dev->dev.bus = &hv_bus;
+ child_device_obj->pnp_dev->dev.parent = &hv_acpi_dev->dev;
+ child_device_obj->pnp_dev->dev.release = vmbus_device_release;
- /*
- * Register with the LDM. This will kick off the driver/device
- * binding...which will eventually call vmbus_match() and vmbus_probe()
- */
- ret = device_register(&child_device_obj->device);
+ if (bytes) {
+ /*
+ * Add a memory option that is aligned on the length. All VMBus
+ * channels can tolerate their memory regions going above
+ * the 32-bit line.
+ */
+ ret = pnp_descendant_memory_option(child_device_obj->pnp_dev,
+ (u64)0x100000000,
+ (u64)(-1),
+ bytes,
+ bytes,
+ IORESOURCE_MEM_WRITEABLE);
+ if (ret)
+ goto register_exit;
+ }
+ ret = pnp_add_descendant(child_device_obj->pnp_dev);
if (ret)
+ goto register_exit;
+
+ added = TRUE;
+
+ ret = pnp_activate_dev(child_device_obj->pnp_dev);
+
+register_exit:
+
+ if (ret) {
+ if (added)
+ pnp_remove_descendant(child_device_obj->pnp_dev);
+ free_pnp_descendant(child_device_obj->pnp_dev);
pr_err("Unable to register child device\n");
- else
+ } else
pr_debug("child device %s registered\n",
- dev_name(&child_device_obj->device));
+ dev_name(&child_device_obj->pnp_dev->dev));
return ret;
}
@@ -870,14 +907,16 @@ int vmbus_device_register(struct hv_device *child_device_obj)
*/
void vmbus_device_unregister(struct hv_device *device_obj)
{
+ pnp_disable_dev(device_obj->pnp_dev);
+
pr_debug("child device %s unregistered\n",
- dev_name(&device_obj->device));
+ dev_name(&device_obj->pnp_dev->dev));
/*
* Kick off the process of unregistering the device.
* This will call vmbus_remove() and eventually vmbus_device_release()
*/
- device_unregister(&device_obj->device);
+ pnp_remove_descendant(device_obj->pnp_dev);
}
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
index e74e5d6..0115e23 100644
--- a/drivers/input/serio/hyperv-keyboard.c
+++ b/drivers/input/serio/hyperv-keyboard.c
@@ -124,7 +124,7 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
* goes away).
*/
if (msg_length < sizeof(struct synth_kbd_protocol_response)) {
- dev_err(&hv_dev->device,
+ dev_err(&hv_dev->pnp_dev->dev,
"Illegal protocol response packet (len: %d)\n",
msg_length);
break;
@@ -143,7 +143,7 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
* goes away).
*/
if (msg_length < sizeof(struct synth_kbd_keystroke)) {
- dev_err(&hv_dev->device,
+ dev_err(&hv_dev->pnp_dev->dev,
"Illegal keyboard event packet (len: %d)\n",
msg_length);
break;
@@ -177,12 +177,12 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
* state because the Enter-UP can trigger a wakeup at once.
*/
if (!(info & IS_BREAK))
- pm_wakeup_event(&hv_dev->device, 0);
+ pm_wakeup_event(&hv_dev->pnp_dev->dev, 0);
break;
default:
- dev_err(&hv_dev->device,
+ dev_err(&hv_dev->pnp_dev->dev,
"unhandled message type %d\n", msg_type);
}
}
@@ -225,7 +225,7 @@ static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
* Drop the packet and hope
* the problem magically goes away.
*/
- dev_err(&hv_dev->device,
+ dev_err(&hv_dev->pnp_dev->dev,
"Illegal packet (type: %d, tid: %llx, size: %d)\n",
desc->type, req_id, msg_sz);
break;
@@ -236,7 +236,7 @@ static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
break;
default:
- dev_err(&hv_dev->device,
+ dev_err(&hv_dev->pnp_dev->dev,
"unhandled packet type %d, tid %llx len %d\n",
desc->type, req_id, bytes_recvd);
break;
@@ -309,7 +309,7 @@ static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev)
response = &kbd_dev->protocol_resp;
proto_status = __le32_to_cpu(response->proto_status);
if (!(proto_status & PROTOCOL_ACCEPTED)) {
- dev_err(&hv_dev->device,
+ dev_err(&hv_dev->pnp_dev->dev,
"synth_kbd protocol request failed (version %d)\n",
SYNTH_KBD_VERSION);
return -ENODEV;
@@ -360,12 +360,12 @@ static int hv_kbd_probe(struct hv_device *hv_dev,
init_completion(&kbd_dev->wait_event);
hv_set_drvdata(hv_dev, kbd_dev);
- hv_serio->dev.parent = &hv_dev->device;
+ hv_serio->dev.parent = &hv_dev->pnp_dev->dev;
hv_serio->id.type = SERIO_8042_XL;
hv_serio->port_data = kbd_dev;
- strlcpy(hv_serio->name, dev_name(&hv_dev->device),
+ strlcpy(hv_serio->name, dev_name(&hv_dev->pnp_dev->dev),
sizeof(hv_serio->name));
- strlcpy(hv_serio->phys, dev_name(&hv_dev->device),
+ strlcpy(hv_serio->phys, dev_name(&hv_dev->pnp_dev->dev),
sizeof(hv_serio->phys));
hv_serio->start = hv_kbd_start;
@@ -386,7 +386,7 @@ static int hv_kbd_probe(struct hv_device *hv_dev,
serio_register_port(kbd_dev->hv_serio);
- device_init_wakeup(&hv_dev->device, true);
+ device_init_wakeup(&hv_dev->pnp_dev->dev, true);
return 0;
@@ -402,7 +402,7 @@ static int hv_kbd_remove(struct hv_device *hv_dev)
{
struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
- device_init_wakeup(&hv_dev->device, false);
+ device_init_wakeup(&hv_dev->pnp_dev->dev, false);
serio_unregister_port(kbd_dev->hv_serio);
vmbus_close(hv_dev->channel);
kfree(kbd_dev);
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 208eb05..00ecfba 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -379,7 +379,8 @@ static int netvsc_init_buf(struct hv_device *device)
net_device->send_section_cnt =
net_device->send_buf_size/net_device->send_section_size;
- dev_info(&device->device, "Send section size: %d, Section count:%d\n",
+ dev_info(&device->pnp_dev->dev,
+ "Send section size: %d, Section count:%d\n",
net_device->send_section_size, net_device->send_section_cnt);
/* Setup state for managing the send buffer. */
@@ -557,7 +558,7 @@ int netvsc_device_remove(struct hv_device *device)
* At this point, no one should be accessing net_device
* except in here
*/
- dev_notice(&device->device, "net device safe to remove\n");
+ dev_notice(&device->pnp_dev->dev, "net device safe to remove\n");
/* Now, we can close the channel safely */
vmbus_close(device->channel);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 15d82ed..37f867b 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -853,7 +853,7 @@ static int netvsc_probe(struct hv_device *dev,
NETIF_F_IP_CSUM | NETIF_F_TSO;
net->ethtool_ops = ðtool_ops;
- SET_NETDEV_DEV(net, &dev->device);
+ SET_NETDEV_DEV(net, &dev->pnp_dev->dev);
/* Notify the netvsc driver of the new device */
device_info.ring_size = ring_size;
@@ -892,7 +892,7 @@ static int netvsc_remove(struct hv_device *dev)
net = net_device->ndev;
if (net == NULL) {
- dev_err(&dev->device, "No net device to remove\n");
+ dev_err(&dev->pnp_dev->dev, "No net device to remove\n");
return 0;
}
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 7816d98..ae9f626 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1079,7 +1079,7 @@ int rndis_filter_device_add(struct hv_device *dev,
device_info->link_state = rndis_device->link_state;
- dev_info(&dev->device, "Device MAC %pM link state %s\n",
+ dev_info(&dev->pnp_dev->dev, "Device MAC %pM link state %s\n",
rndis_device->hw_mac_adr,
device_info->link_state ? "down" : "up");
@@ -1103,7 +1103,7 @@ int rndis_filter_device_add(struct hv_device *dev,
NETVSC_PACKET_SIZE);
if (!net_device->sub_cb_buf) {
net_device->num_chn = 1;
- dev_info(&dev->device, "No memory for subchannels.\n");
+ dev_info(&dev->pnp_dev->dev, "No memory for subchannels.\n");
goto out;
}
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index efc6e44..1f15a26b 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1781,7 +1781,7 @@ static int storvsc_probe(struct hv_device *device,
host->max_cmd_len = STORVSC_MAX_CMD_LEN;
/* Register the HBA and start the scsi bus scan */
- ret = scsi_add_host(host, &device->device);
+ ret = scsi_add_host(host, &device->pnp_dev->dev);
if (ret != 0)
goto err_out2;
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index 4254336..69ea59b 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -772,7 +772,7 @@ static int hvfb_probe(struct hv_device *hdev,
struct hvfb_par *par;
int ret;
- info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
+ info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->pnp_dev->dev);
if (!info) {
pr_err("No memory for framebuffer info\n");
return -ENOMEM;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 5a2ba67..796cc32 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -35,6 +35,7 @@
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
+#include <linux/pnp.h>
#define MAX_PAGE_BUFFER_COUNT 32
@@ -928,7 +929,11 @@ struct hv_device {
/* the device instance id of this device */
uuid_le dev_instance;
- struct device device;
+ /* the amount of memory address space that should be
+ reserved for this channel, in megabytes */
+ u16 mmio_mb;
+
+ struct pnp_dev *pnp_dev;
struct vmbus_channel *channel;
};
@@ -936,7 +941,9 @@ struct hv_device {
static inline struct hv_device *device_to_hv_device(struct device *d)
{
- return container_of(d, struct hv_device, device);
+ struct pnp_dev *pnp_dev = container_of(d, struct pnp_dev, dev);
+
+ return (struct hv_device *)(pnp_dev->data);
}
static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
@@ -946,12 +953,12 @@ static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
static inline void hv_set_drvdata(struct hv_device *dev, void *data)
{
- dev_set_drvdata(&dev->device, data);
+ dev_set_drvdata(&dev->pnp_dev->dev, data);
}
static inline void *hv_get_drvdata(struct hv_device *dev)
{
- return dev_get_drvdata(&dev->device);
+ return dev_get_drvdata(&dev->pnp_dev->dev);
}
/* Vmbus interface */
--
1.9.1
next prev parent reply other threads:[~2015-02-17 18:27 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-17 19:41 [PATCH 1/3] drivers:pnp Add support for descendants claiming memory address space Jake Oshins
2015-02-17 19:41 ` Jake Oshins [this message]
2015-02-18 10:24 ` [PATCH 2/3] drivers:hv Convert VMBus and its descendants to PnP Dan Carpenter
2015-02-18 16:55 ` Jake Oshins
2015-02-17 19:41 ` [PATCH 3/3] drivers:hv Remove old MMIO management code Jake Oshins
2015-03-02 3:33 ` [PATCH 1/3] drivers:pnp Add support for descendants claiming memory address space Greg KH
2015-03-02 3:36 ` KY Srinivasan
2015-03-05 23:03 ` Rafael J. Wysocki
2015-03-05 23:03 ` Rafael J. Wysocki
2015-03-10 22:10 ` Jake Oshins
2015-03-10 22:10 ` Jake Oshins
2015-03-11 0:34 ` Rafael J. Wysocki
2015-03-19 19:21 ` Jake Oshins
2015-03-19 19:21 ` Jake Oshins
2015-03-19 19:21 ` Jake Oshins
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1424202111-14461-2-git-send-email-jakeo@microsoft.com \
--to=jakeo@microsoft.com \
--cc=apw@canonical.com \
--cc=devel@linuxdriverproject.org \
--cc=gregkh@linuxfoundation.org \
--cc=kys@microsoft.com \
--cc=linux-kernel@vger.kernel.org \
--cc=olaf@aepfle.de \
--cc=rafael.j.wysocki@intel.com \
--cc=vkuznets@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.