virtualization.lists.linux-foundation.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
@ 2012-07-03  5:41 Cong Meng
  2012-07-03 11:50 ` Paolo Bonzini
  2012-07-04  6:10 ` Zhi Yong Wu
  0 siblings, 2 replies; 5+ messages in thread
From: Cong Meng @ 2012-07-03  5:41 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: stefanha, linux-scsi, senwang, zwanp, linuxram, linux-kernel,
	virtualization, Cong Meng

This patch implements the hotplug support for virtio-scsi.
When there is a device attached/detached, the virtio-scsi driver will be
signaled via event virtual queue and it will add/remove the scsi device 
in question automatically.

v2: handle no_event event

Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>
---
 drivers/scsi/virtio_scsi.c  |  113 ++++++++++++++++++++++++++++++++++++++++++-
 include/linux/virtio_scsi.h |    9 ++++
 2 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 9fc5e67..e44b2d6 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -25,6 +25,7 @@
 #include <scsi/scsi_cmnd.h>
 
 #define VIRTIO_SCSI_MEMPOOL_SZ 64
+#define VIRTIO_SCSI_EVENT_LEN 8
 
 /* Command queue element */
 struct virtio_scsi_cmd {
@@ -43,6 +44,12 @@ struct virtio_scsi_cmd {
 	} resp;
 } ____cacheline_aligned_in_smp;
 
+struct virtio_scsi_event_node {
+	struct virtio_scsi *vscsi;
+	struct virtio_scsi_event event;
+	struct work_struct work;
+};
+
 struct virtio_scsi_vq {
 	/* Protects vq */
 	spinlock_t vq_lock;
@@ -67,6 +74,9 @@ struct virtio_scsi {
 	struct virtio_scsi_vq event_vq;
 	struct virtio_scsi_vq req_vq;
 
+	/* Get some buffers reday for event vq */
+	struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
+
 	struct virtio_scsi_target_state *tgt[];
 };
 
@@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
 	spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags);
 };
 
+static int virtscsi_kick_event(struct virtio_scsi *vscsi,
+			       struct virtio_scsi_event_node *event_node)
+{
+	int ret;
+	struct scatterlist sg;
+	unsigned long flags;
+
+	sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
+
+	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
+
+	ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC);
+	if (ret >= 0)
+		virtqueue_kick(vscsi->event_vq.vq);
+
+	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
+
+	return ret;
+}
+
+static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
+{
+	int i;
+
+	for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) {
+		vscsi->event_list[i].vscsi = vscsi;
+		virtscsi_kick_event(vscsi, &vscsi->event_list[i]);
+	}
+
+	return 0;
+}
+
+static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
+                                            struct virtio_scsi_event *event)
+{
+	struct scsi_device *sdev;
+	struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
+	unsigned int target = event->lun[1];
+	unsigned int lun = (event->lun[2] << 8) | event->lun[3];
+
+	switch (event->reason) {
+	case VIRTIO_SCSI_EVT_RESET_RESCAN:
+		scsi_add_device(shost, 0, target, lun);
+		break;
+	case VIRTIO_SCSI_EVT_RESET_REMOVED:
+		sdev = scsi_device_lookup(shost, 0, target, lun);
+		if (sdev) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		} else {
+			pr_err("SCSI device %d 0 %d %d not found\n",
+				shost->host_no, target, lun);
+		}
+		break;
+	default:
+		pr_info("Unsupport virtio scsi event reason %x\n", event->reason);
+	}
+}
+
+static void virtscsi_handle_event(struct work_struct *work)
+{
+	struct virtio_scsi_event_node *event_node =
+		container_of(work, struct virtio_scsi_event_node, work);
+	struct virtio_scsi *vscsi = event_node->vscsi;
+	struct virtio_scsi_event *event = &event_node->event;
+
+	if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) {
+		event->event &= (~VIRTIO_SCSI_T_EVENTS_MISSED);
+		/* FIXME: handle event missed here */
+	}
+
+	switch (event->event) {
+	case VIRTIO_SCSI_T_NO_EVENT:
+		break;
+	case VIRTIO_SCSI_T_TRANSPORT_RESET:
+		virtscsi_handle_transport_reset(vscsi, event);
+		break;
+	default:
+		pr_err("Unsupport virtio scsi event %x\n", event->event);
+	}
+	virtscsi_kick_event(vscsi, event_node);
+}
+
+static void virtscsi_complete_event(void *buf)
+{
+	struct virtio_scsi_event_node *event_node = buf;
+
+	INIT_WORK(&event_node->work, virtscsi_handle_event);
+	schedule_work(&event_node->work);
+}
+
 static void virtscsi_event_done(struct virtqueue *vq)
 {
 	struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
@@ -209,7 +310,7 @@ static void virtscsi_event_done(struct virtqueue *vq)
 	unsigned long flags;
 
 	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
-	virtscsi_vq_done(vq, virtscsi_complete_free);
+	virtscsi_vq_done(vq, virtscsi_complete_event);
 	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
 };
 
@@ -510,6 +611,10 @@ static int virtscsi_init(struct virtio_device *vdev,
 	virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE);
 	virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE);
 
+	if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
+		virtscsi_kick_event_all(vscsi);
+	}
+
 	/* We need to know how many segments before we allocate.  */
 	sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
 
@@ -608,7 +713,13 @@ static struct virtio_device_id id_table[] = {
 	{ 0 },
 };
 
+static unsigned int features[] = {
+	VIRTIO_SCSI_F_HOTPLUG
+};
+
 static struct virtio_driver virtio_scsi_driver = {
+	.feature_table = features,
+	.feature_table_size = ARRAY_SIZE(features),
 	.driver.name = KBUILD_MODNAME,
 	.driver.owner = THIS_MODULE,
 	.id_table = id_table,
diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
index 8ddeafd..dc8d305 100644
--- a/include/linux/virtio_scsi.h
+++ b/include/linux/virtio_scsi.h
@@ -69,6 +69,10 @@ struct virtio_scsi_config {
 	u32 max_lun;
 } __packed;
 
+/* Feature Bits */
+#define VIRTIO_SCSI_F_INOUT                    0
+#define VIRTIO_SCSI_F_HOTPLUG                  1
+
 /* Response codes */
 #define VIRTIO_SCSI_S_OK                       0
 #define VIRTIO_SCSI_S_OVERRUN                  1
@@ -105,6 +109,11 @@ struct virtio_scsi_config {
 #define VIRTIO_SCSI_T_TRANSPORT_RESET          1
 #define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
 
+/* Reasons of transport reset event */
+#define VIRTIO_SCSI_EVT_RESET_HARD             0
+#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
+#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
+
 #define VIRTIO_SCSI_S_SIMPLE                   0
 #define VIRTIO_SCSI_S_ORDERED                  1
 #define VIRTIO_SCSI_S_HEAD                     2
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
  2012-07-03  5:41 [PATCH v2] virtio-scsi: hotplug support for virtio-scsi Cong Meng
@ 2012-07-03 11:50 ` Paolo Bonzini
  2012-07-04  8:11   ` mc
       [not found]   ` <20120704041124.Horde.MN5WeZir309P8-qsGUCj3vA@imap.linux.ibm.com>
  2012-07-04  6:10 ` Zhi Yong Wu
  1 sibling, 2 replies; 5+ messages in thread
From: Paolo Bonzini @ 2012-07-03 11:50 UTC (permalink / raw)
  To: Cong Meng
  Cc: stefanha, linux-scsi, senwang, zwanp, linuxram, linux-kernel,
	virtualization

Il 03/07/2012 07:41, Cong Meng ha scritto:
> This patch implements the hotplug support for virtio-scsi.
> When there is a device attached/detached, the virtio-scsi driver will be
> signaled via event virtual queue and it will add/remove the scsi device 
> in question automatically.
> 
> v2: handle no_event event
> 
> Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
> Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>

The SoB lines are swapped.  Otherwise looks good.  Since you have to
respin, please add dropped event support too, it shouldn't be hard.

Paolo

> ---
>  drivers/scsi/virtio_scsi.c  |  113 ++++++++++++++++++++++++++++++++++++++++++-
>  include/linux/virtio_scsi.h |    9 ++++
>  2 files changed, 121 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
> index 9fc5e67..e44b2d6 100644
> --- a/drivers/scsi/virtio_scsi.c
> +++ b/drivers/scsi/virtio_scsi.c
> @@ -25,6 +25,7 @@
>  #include <scsi/scsi_cmnd.h>
>  
>  #define VIRTIO_SCSI_MEMPOOL_SZ 64
> +#define VIRTIO_SCSI_EVENT_LEN 8
>  
>  /* Command queue element */
>  struct virtio_scsi_cmd {
> @@ -43,6 +44,12 @@ struct virtio_scsi_cmd {
>  	} resp;
>  } ____cacheline_aligned_in_smp;
>  
> +struct virtio_scsi_event_node {
> +	struct virtio_scsi *vscsi;
> +	struct virtio_scsi_event event;
> +	struct work_struct work;
> +};
> +
>  struct virtio_scsi_vq {
>  	/* Protects vq */
>  	spinlock_t vq_lock;
> @@ -67,6 +74,9 @@ struct virtio_scsi {
>  	struct virtio_scsi_vq event_vq;
>  	struct virtio_scsi_vq req_vq;
>  
> +	/* Get some buffers reday for event vq */
> +	struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
> +
>  	struct virtio_scsi_target_state *tgt[];
>  };
>  
> @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
>  	spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags);
>  };
>  
> +static int virtscsi_kick_event(struct virtio_scsi *vscsi,
> +			       struct virtio_scsi_event_node *event_node)
> +{
> +	int ret;
> +	struct scatterlist sg;
> +	unsigned long flags;
> +
> +	sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
> +
> +	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
> +
> +	ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC);
> +	if (ret >= 0)
> +		virtqueue_kick(vscsi->event_vq.vq);
> +
> +	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
> +
> +	return ret;
> +}
> +
> +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
> +{
> +	int i;
> +
> +	for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) {
> +		vscsi->event_list[i].vscsi = vscsi;
> +		virtscsi_kick_event(vscsi, &vscsi->event_list[i]);
> +	}
> +
> +	return 0;
> +}
> +
> +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
> +                                            struct virtio_scsi_event *event)
> +{
> +	struct scsi_device *sdev;
> +	struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
> +	unsigned int target = event->lun[1];
> +	unsigned int lun = (event->lun[2] << 8) | event->lun[3];
> +
> +	switch (event->reason) {
> +	case VIRTIO_SCSI_EVT_RESET_RESCAN:
> +		scsi_add_device(shost, 0, target, lun);
> +		break;
> +	case VIRTIO_SCSI_EVT_RESET_REMOVED:
> +		sdev = scsi_device_lookup(shost, 0, target, lun);
> +		if (sdev) {
> +			scsi_remove_device(sdev);
> +			scsi_device_put(sdev);
> +		} else {
> +			pr_err("SCSI device %d 0 %d %d not found\n",
> +				shost->host_no, target, lun);
> +		}
> +		break;
> +	default:
> +		pr_info("Unsupport virtio scsi event reason %x\n", event->reason);
> +	}
> +}
> +
> +static void virtscsi_handle_event(struct work_struct *work)
> +{
> +	struct virtio_scsi_event_node *event_node =
> +		container_of(work, struct virtio_scsi_event_node, work);
> +	struct virtio_scsi *vscsi = event_node->vscsi;
> +	struct virtio_scsi_event *event = &event_node->event;
> +
> +	if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) {
> +		event->event &= (~VIRTIO_SCSI_T_EVENTS_MISSED);
> +		/* FIXME: handle event missed here */
> +	}
> +
> +	switch (event->event) {
> +	case VIRTIO_SCSI_T_NO_EVENT:
> +		break;
> +	case VIRTIO_SCSI_T_TRANSPORT_RESET:
> +		virtscsi_handle_transport_reset(vscsi, event);
> +		break;
> +	default:
> +		pr_err("Unsupport virtio scsi event %x\n", event->event);
> +	}
> +	virtscsi_kick_event(vscsi, event_node);
> +}
> +
> +static void virtscsi_complete_event(void *buf)
> +{
> +	struct virtio_scsi_event_node *event_node = buf;
> +
> +	INIT_WORK(&event_node->work, virtscsi_handle_event);
> +	schedule_work(&event_node->work);
> +}
> +
>  static void virtscsi_event_done(struct virtqueue *vq)
>  {
>  	struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
> @@ -209,7 +310,7 @@ static void virtscsi_event_done(struct virtqueue *vq)
>  	unsigned long flags;
>  
>  	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
> -	virtscsi_vq_done(vq, virtscsi_complete_free);
> +	virtscsi_vq_done(vq, virtscsi_complete_event);
>  	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
>  };
>  
> @@ -510,6 +611,10 @@ static int virtscsi_init(struct virtio_device *vdev,
>  	virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE);
>  	virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE);
>  
> +	if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
> +		virtscsi_kick_event_all(vscsi);
> +	}
> +
>  	/* We need to know how many segments before we allocate.  */
>  	sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
>  
> @@ -608,7 +713,13 @@ static struct virtio_device_id id_table[] = {
>  	{ 0 },
>  };
>  
> +static unsigned int features[] = {
> +	VIRTIO_SCSI_F_HOTPLUG
> +};
> +
>  static struct virtio_driver virtio_scsi_driver = {
> +	.feature_table = features,
> +	.feature_table_size = ARRAY_SIZE(features),
>  	.driver.name = KBUILD_MODNAME,
>  	.driver.owner = THIS_MODULE,
>  	.id_table = id_table,
> diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
> index 8ddeafd..dc8d305 100644
> --- a/include/linux/virtio_scsi.h
> +++ b/include/linux/virtio_scsi.h
> @@ -69,6 +69,10 @@ struct virtio_scsi_config {
>  	u32 max_lun;
>  } __packed;
>  
> +/* Feature Bits */
> +#define VIRTIO_SCSI_F_INOUT                    0
> +#define VIRTIO_SCSI_F_HOTPLUG                  1
> +
>  /* Response codes */
>  #define VIRTIO_SCSI_S_OK                       0
>  #define VIRTIO_SCSI_S_OVERRUN                  1
> @@ -105,6 +109,11 @@ struct virtio_scsi_config {
>  #define VIRTIO_SCSI_T_TRANSPORT_RESET          1
>  #define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
>  
> +/* Reasons of transport reset event */
> +#define VIRTIO_SCSI_EVT_RESET_HARD             0
> +#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
> +#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
> +
>  #define VIRTIO_SCSI_S_SIMPLE                   0
>  #define VIRTIO_SCSI_S_ORDERED                  1
>  #define VIRTIO_SCSI_S_HEAD                     2
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
  2012-07-03  5:41 [PATCH v2] virtio-scsi: hotplug support for virtio-scsi Cong Meng
  2012-07-03 11:50 ` Paolo Bonzini
@ 2012-07-04  6:10 ` Zhi Yong Wu
  1 sibling, 0 replies; 5+ messages in thread
From: Zhi Yong Wu @ 2012-07-04  6:10 UTC (permalink / raw)
  To: Cong Meng
  Cc: stefanha, linux-scsi, zwanp, linuxram, senwang, linux-kernel,
	Paolo Bonzini, virtualization

On Tue, Jul 3, 2012 at 1:41 PM, Cong Meng <mc@linux.vnet.ibm.com> wrote:
> This patch implements the hotplug support for virtio-scsi.
> When there is a device attached/detached, the virtio-scsi driver will be
> signaled via event virtual queue and it will add/remove the scsi device
> in question automatically.
>
> v2: handle no_event event
>
> Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
> Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>
> ---
>  drivers/scsi/virtio_scsi.c  |  113 ++++++++++++++++++++++++++++++++++++++++++-
>  include/linux/virtio_scsi.h |    9 ++++
>  2 files changed, 121 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
> index 9fc5e67..e44b2d6 100644
> --- a/drivers/scsi/virtio_scsi.c
> +++ b/drivers/scsi/virtio_scsi.c
> @@ -25,6 +25,7 @@
>  #include <scsi/scsi_cmnd.h>
>
>  #define VIRTIO_SCSI_MEMPOOL_SZ 64
> +#define VIRTIO_SCSI_EVENT_LEN 8
>
>  /* Command queue element */
>  struct virtio_scsi_cmd {
> @@ -43,6 +44,12 @@ struct virtio_scsi_cmd {
>         } resp;
>  } ____cacheline_aligned_in_smp;
>
> +struct virtio_scsi_event_node {
> +       struct virtio_scsi *vscsi;
> +       struct virtio_scsi_event event;
> +       struct work_struct work;
> +};
> +
>  struct virtio_scsi_vq {
>         /* Protects vq */
>         spinlock_t vq_lock;
> @@ -67,6 +74,9 @@ struct virtio_scsi {
>         struct virtio_scsi_vq event_vq;
>         struct virtio_scsi_vq req_vq;
>
> +       /* Get some buffers reday for event vq */
s/reday/ready/   ^^^^
> +       struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
> +
>         struct virtio_scsi_target_state *tgt[];
>  };
>
> @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
>         spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags);
>  };
>
> +static int virtscsi_kick_event(struct virtio_scsi *vscsi,
> +                              struct virtio_scsi_event_node *event_node)
> +{
> +       int ret;
> +       struct scatterlist sg;
> +       unsigned long flags;
> +
> +       sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
> +
> +       spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
> +
> +       ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC);
> +       if (ret >= 0)
> +               virtqueue_kick(vscsi->event_vq.vq);
> +
> +       spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
> +
> +       return ret;
> +}
> +
> +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
> +{
> +       int i;
> +
> +       for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) {
> +               vscsi->event_list[i].vscsi = vscsi;
> +               virtscsi_kick_event(vscsi, &vscsi->event_list[i]);
> +       }
> +
> +       return 0;
> +}
> +
> +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
> +                                            struct virtio_scsi_event *event)
> +{
> +       struct scsi_device *sdev;
> +       struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
> +       unsigned int target = event->lun[1];
> +       unsigned int lun = (event->lun[2] << 8) | event->lun[3];
> +
> +       switch (event->reason) {
> +       case VIRTIO_SCSI_EVT_RESET_RESCAN:
> +               scsi_add_device(shost, 0, target, lun);
> +               break;
> +       case VIRTIO_SCSI_EVT_RESET_REMOVED:
> +               sdev = scsi_device_lookup(shost, 0, target, lun);
> +               if (sdev) {
> +                       scsi_remove_device(sdev);
> +                       scsi_device_put(sdev);
> +               } else {
> +                       pr_err("SCSI device %d 0 %d %d not found\n",
> +                               shost->host_no, target, lun);
> +               }
> +               break;
> +       default:
> +               pr_info("Unsupport virtio scsi event reason %x\n", event->reason);
> +       }
> +}
> +
> +static void virtscsi_handle_event(struct work_struct *work)
> +{
> +       struct virtio_scsi_event_node *event_node =
> +               container_of(work, struct virtio_scsi_event_node, work);
> +       struct virtio_scsi *vscsi = event_node->vscsi;
> +       struct virtio_scsi_event *event = &event_node->event;
> +
> +       if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) {
> +               event->event &= (~VIRTIO_SCSI_T_EVENTS_MISSED);
> +               /* FIXME: handle event missed here */
> +       }
> +
> +       switch (event->event) {
> +       case VIRTIO_SCSI_T_NO_EVENT:
> +               break;
> +       case VIRTIO_SCSI_T_TRANSPORT_RESET:
> +               virtscsi_handle_transport_reset(vscsi, event);
> +               break;
> +       default:
> +               pr_err("Unsupport virtio scsi event %x\n", event->event);
> +       }
> +       virtscsi_kick_event(vscsi, event_node);
> +}
> +
> +static void virtscsi_complete_event(void *buf)
> +{
> +       struct virtio_scsi_event_node *event_node = buf;
> +
> +       INIT_WORK(&event_node->work, virtscsi_handle_event);
> +       schedule_work(&event_node->work);
> +}
> +
>  static void virtscsi_event_done(struct virtqueue *vq)
>  {
>         struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
> @@ -209,7 +310,7 @@ static void virtscsi_event_done(struct virtqueue *vq)
>         unsigned long flags;
>
>         spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
> -       virtscsi_vq_done(vq, virtscsi_complete_free);
> +       virtscsi_vq_done(vq, virtscsi_complete_event);
>         spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
>  };
>
> @@ -510,6 +611,10 @@ static int virtscsi_init(struct virtio_device *vdev,
>         virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE);
>         virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE);
>
> +       if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
> +               virtscsi_kick_event_all(vscsi);
> +       }
> +
>         /* We need to know how many segments before we allocate.  */
>         sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
>
> @@ -608,7 +713,13 @@ static struct virtio_device_id id_table[] = {
>         { 0 },
>  };
>
> +static unsigned int features[] = {
> +       VIRTIO_SCSI_F_HOTPLUG
> +};
> +
>  static struct virtio_driver virtio_scsi_driver = {
> +       .feature_table = features,
> +       .feature_table_size = ARRAY_SIZE(features),
>         .driver.name = KBUILD_MODNAME,
>         .driver.owner = THIS_MODULE,
>         .id_table = id_table,
> diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
> index 8ddeafd..dc8d305 100644
> --- a/include/linux/virtio_scsi.h
> +++ b/include/linux/virtio_scsi.h
> @@ -69,6 +69,10 @@ struct virtio_scsi_config {
>         u32 max_lun;
>  } __packed;
>
> +/* Feature Bits */
> +#define VIRTIO_SCSI_F_INOUT                    0
> +#define VIRTIO_SCSI_F_HOTPLUG                  1
> +
>  /* Response codes */
>  #define VIRTIO_SCSI_S_OK                       0
>  #define VIRTIO_SCSI_S_OVERRUN                  1
> @@ -105,6 +109,11 @@ struct virtio_scsi_config {
>  #define VIRTIO_SCSI_T_TRANSPORT_RESET          1
>  #define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
>
> +/* Reasons of transport reset event */
> +#define VIRTIO_SCSI_EVT_RESET_HARD             0
> +#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
> +#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
> +
>  #define VIRTIO_SCSI_S_SIMPLE                   0
>  #define VIRTIO_SCSI_S_ORDERED                  1
>  #define VIRTIO_SCSI_S_HEAD                     2
> --
> 1.7.7.6
>
> _______________________________________________
> Virtualization mailing list
> Virtualization@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/virtualization



-- 
Regards,

Zhi Yong Wu

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
  2012-07-03 11:50 ` Paolo Bonzini
@ 2012-07-04  8:11   ` mc
       [not found]   ` <20120704041124.Horde.MN5WeZir309P8-qsGUCj3vA@imap.linux.ibm.com>
  1 sibling, 0 replies; 5+ messages in thread
From: mc @ 2012-07-04  8:11 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: stefanha, linux-scsi, senwang, zwanp, linuxram, linux-kernel,
	virtualization


Quoting Paolo Bonzini <pbonzini@redhat.com>:

> Il 03/07/2012 07:41, Cong Meng ha scritto:
>> This patch implements the hotplug support for virtio-scsi.
>> When there is a device attached/detached, the virtio-scsi driver will be
>> signaled via event virtual queue and it will add/remove the scsi device
>> in question automatically.
>>
>> v2: handle no_event event
>>
>> Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
>> Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>
>
> The SoB lines are swapped.  Otherwise looks good.  Since you have to
> respin, please add dropped event support too, it shouldn't be hard.

What does "The SoB lines are swapped" mean? should the changelog be  
placed after SoB lines?

>
> Paolo
>
>> ---
>>  drivers/scsi/virtio_scsi.c  |  113  
>> ++++++++++++++++++++++++++++++++++++++++++-
>>  include/linux/virtio_scsi.h |    9 ++++
>>  2 files changed, 121 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
>> index 9fc5e67..e44b2d6 100644
>> --- a/drivers/scsi/virtio_scsi.c
>> +++ b/drivers/scsi/virtio_scsi.c
>> @@ -25,6 +25,7 @@
>>  #include <scsi/scsi_cmnd.h>
>>
>>  #define VIRTIO_SCSI_MEMPOOL_SZ 64
>> +#define VIRTIO_SCSI_EVENT_LEN 8
>>
>>  /* Command queue element */
>>  struct virtio_scsi_cmd {
>> @@ -43,6 +44,12 @@ struct virtio_scsi_cmd {
>>  	} resp;
>>  } ____cacheline_aligned_in_smp;
>>
>> +struct virtio_scsi_event_node {
>> +	struct virtio_scsi *vscsi;
>> +	struct virtio_scsi_event event;
>> +	struct work_struct work;
>> +};
>> +
>>  struct virtio_scsi_vq {
>>  	/* Protects vq */
>>  	spinlock_t vq_lock;
>> @@ -67,6 +74,9 @@ struct virtio_scsi {
>>  	struct virtio_scsi_vq event_vq;
>>  	struct virtio_scsi_vq req_vq;
>>
>> +	/* Get some buffers reday for event vq */
>> +	struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
>> +
>>  	struct virtio_scsi_target_state *tgt[];
>>  };
>>
>> @@ -202,6 +212,97 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
>>  	spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags);
>>  };
>>
>> +static int virtscsi_kick_event(struct virtio_scsi *vscsi,
>> +			       struct virtio_scsi_event_node *event_node)
>> +{
>> +	int ret;
>> +	struct scatterlist sg;
>> +	unsigned long flags;
>> +
>> +	sg_set_buf(&sg, &event_node->event, sizeof(struct virtio_scsi_event));
>> +
>> +	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
>> +
>> +	ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1,  
>> event_node, GFP_ATOMIC);
>> +	if (ret >= 0)
>> +		virtqueue_kick(vscsi->event_vq.vq);
>> +
>> +	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
>> +
>> +	return ret;
>> +}
>> +
>> +static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) {
>> +		vscsi->event_list[i].vscsi = vscsi;
>> +		virtscsi_kick_event(vscsi, &vscsi->event_list[i]);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
>> +                                            struct  
>> virtio_scsi_event *event)
>> +{
>> +	struct scsi_device *sdev;
>> +	struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
>> +	unsigned int target = event->lun[1];
>> +	unsigned int lun = (event->lun[2] << 8) | event->lun[3];
>> +
>> +	switch (event->reason) {
>> +	case VIRTIO_SCSI_EVT_RESET_RESCAN:
>> +		scsi_add_device(shost, 0, target, lun);
>> +		break;
>> +	case VIRTIO_SCSI_EVT_RESET_REMOVED:
>> +		sdev = scsi_device_lookup(shost, 0, target, lun);
>> +		if (sdev) {
>> +			scsi_remove_device(sdev);
>> +			scsi_device_put(sdev);
>> +		} else {
>> +			pr_err("SCSI device %d 0 %d %d not found\n",
>> +				shost->host_no, target, lun);
>> +		}
>> +		break;
>> +	default:
>> +		pr_info("Unsupport virtio scsi event reason %x\n", event->reason);
>> +	}
>> +}
>> +
>> +static void virtscsi_handle_event(struct work_struct *work)
>> +{
>> +	struct virtio_scsi_event_node *event_node =
>> +		container_of(work, struct virtio_scsi_event_node, work);
>> +	struct virtio_scsi *vscsi = event_node->vscsi;
>> +	struct virtio_scsi_event *event = &event_node->event;
>> +
>> +	if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) {
>> +		event->event &= (~VIRTIO_SCSI_T_EVENTS_MISSED);
>> +		/* FIXME: handle event missed here */
>> +	}
>> +
>> +	switch (event->event) {
>> +	case VIRTIO_SCSI_T_NO_EVENT:
>> +		break;
>> +	case VIRTIO_SCSI_T_TRANSPORT_RESET:
>> +		virtscsi_handle_transport_reset(vscsi, event);
>> +		break;
>> +	default:
>> +		pr_err("Unsupport virtio scsi event %x\n", event->event);
>> +	}
>> +	virtscsi_kick_event(vscsi, event_node);
>> +}
>> +
>> +static void virtscsi_complete_event(void *buf)
>> +{
>> +	struct virtio_scsi_event_node *event_node = buf;
>> +
>> +	INIT_WORK(&event_node->work, virtscsi_handle_event);
>> +	schedule_work(&event_node->work);
>> +}
>> +
>>  static void virtscsi_event_done(struct virtqueue *vq)
>>  {
>>  	struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
>> @@ -209,7 +310,7 @@ static void virtscsi_event_done(struct virtqueue *vq)
>>  	unsigned long flags;
>>
>>  	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
>> -	virtscsi_vq_done(vq, virtscsi_complete_free);
>> +	virtscsi_vq_done(vq, virtscsi_complete_event);
>>  	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
>>  };
>>
>> @@ -510,6 +611,10 @@ static int virtscsi_init(struct virtio_device *vdev,
>>  	virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE);
>>  	virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE);
>>
>> +	if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
>> +		virtscsi_kick_event_all(vscsi);
>> +	}
>> +
>>  	/* We need to know how many segments before we allocate.  */
>>  	sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1;
>>
>> @@ -608,7 +713,13 @@ static struct virtio_device_id id_table[] = {
>>  	{ 0 },
>>  };
>>
>> +static unsigned int features[] = {
>> +	VIRTIO_SCSI_F_HOTPLUG
>> +};
>> +
>>  static struct virtio_driver virtio_scsi_driver = {
>> +	.feature_table = features,
>> +	.feature_table_size = ARRAY_SIZE(features),
>>  	.driver.name = KBUILD_MODNAME,
>>  	.driver.owner = THIS_MODULE,
>>  	.id_table = id_table,
>> diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
>> index 8ddeafd..dc8d305 100644
>> --- a/include/linux/virtio_scsi.h
>> +++ b/include/linux/virtio_scsi.h
>> @@ -69,6 +69,10 @@ struct virtio_scsi_config {
>>  	u32 max_lun;
>>  } __packed;
>>
>> +/* Feature Bits */
>> +#define VIRTIO_SCSI_F_INOUT                    0
>> +#define VIRTIO_SCSI_F_HOTPLUG                  1
>> +
>>  /* Response codes */
>>  #define VIRTIO_SCSI_S_OK                       0
>>  #define VIRTIO_SCSI_S_OVERRUN                  1
>> @@ -105,6 +109,11 @@ struct virtio_scsi_config {
>>  #define VIRTIO_SCSI_T_TRANSPORT_RESET          1
>>  #define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
>>
>> +/* Reasons of transport reset event */
>> +#define VIRTIO_SCSI_EVT_RESET_HARD             0
>> +#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
>> +#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
>> +
>>  #define VIRTIO_SCSI_S_SIMPLE                   0
>>  #define VIRTIO_SCSI_S_ORDERED                  1
>>  #define VIRTIO_SCSI_S_HEAD                     2
>>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] virtio-scsi: hotplug support for virtio-scsi
       [not found]   ` <20120704041124.Horde.MN5WeZir309P8-qsGUCj3vA@imap.linux.ibm.com>
@ 2012-07-04 12:35     ` Paolo Bonzini
  0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2012-07-04 12:35 UTC (permalink / raw)
  To: mc
  Cc: stefanha, linux-scsi, senwang, zwanp, linuxram, linux-kernel,
	virtualization

Il 04/07/2012 10:11, mc@linux.vnet.ibm.com ha scritto:
>>>
>>>
>>> Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
>>> Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>
>>
>> The SoB lines are swapped.  Otherwise looks good.  Since you have to
>> respin, please add dropped event support too, it shouldn't be hard.
> 
> What does "The SoB lines are swapped" mean? should the changelog be
> placed after SoB lines?

No, the patch sender should be the last SoB line.  Sen Wang should hence
come before you, not after.

Paolo

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-07-04 12:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-03  5:41 [PATCH v2] virtio-scsi: hotplug support for virtio-scsi Cong Meng
2012-07-03 11:50 ` Paolo Bonzini
2012-07-04  8:11   ` mc
     [not found]   ` <20120704041124.Horde.MN5WeZir309P8-qsGUCj3vA@imap.linux.ibm.com>
2012-07-04 12:35     ` Paolo Bonzini
2012-07-04  6:10 ` Zhi Yong Wu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).