linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] virtio-scsi: hotplug suppot for virtio-scsi
@ 2012-06-20  6:55 Cong Meng
  2012-07-01 13:24 ` Paolo Bonzini
  0 siblings, 1 reply; 4+ messages in thread
From: Cong Meng @ 2012-06-20  6:55 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Rusty Russell, Nicholas A. Bellinger, stefanha, linuxram,
	Anthony Liguori, senwang, zwanp, James E.J. Bottomley,
	virtualization, linux-kernel, linux-scsi, 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.

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  |  109 ++++++++++++++++++++++++++++++++++++++++++-
 include/linux/virtio_scsi.h |    9 ++++
 2 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 1b38431..6dad625 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,9 +44,15 @@ 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;
+};
+
 /* Driver instance state */
 struct virtio_scsi {
-	/* Protects ctrl_vq, req_vq and sg[] */
+	/* Protects ctrl_vq, event_vq, req_vq and sg[] */
 	spinlock_t vq_lock;
 
 	struct virtio_device *vdev;
@@ -53,6 +60,9 @@ struct virtio_scsi {
 	struct virtqueue *event_vq;
 	struct virtqueue *req_vq;
 
+	/* Get some buffers reday for event vq */
+	struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
+
 	/* For sglist construction when adding commands to the virtqueue.  */
 	struct scatterlist sg[];
 };
@@ -184,9 +194,93 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
 	virtscsi_vq_done(vq, virtscsi_complete_free);
 };
 
+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->vq_lock, flags);
+
+	ret = virtqueue_add_buf(vscsi->event_vq, &sg, 0, 1, event_node, GFP_ATOMIC);
+	if (ret >= 0)
+		virtqueue_kick(vscsi->event_vq);
+
+	spin_unlock_irqrestore(&vscsi->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;
+
+	switch (event->event) {
+	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)
 {
-	virtscsi_vq_done(vq, virtscsi_complete_free);
+	virtscsi_vq_done(vq, virtscsi_complete_event);
 };
 
 static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
@@ -435,6 +529,11 @@ 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);
+	}
+
 	return 0;
 }
 
@@ -532,7 +631,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] 4+ messages in thread

* Re: [PATCH] virtio-scsi: hotplug suppot for virtio-scsi
  2012-06-20  6:55 [PATCH] virtio-scsi: hotplug suppot for virtio-scsi Cong Meng
@ 2012-07-01 13:24 ` Paolo Bonzini
  2012-07-02  7:20   ` mc
  0 siblings, 1 reply; 4+ messages in thread
From: Paolo Bonzini @ 2012-07-01 13:24 UTC (permalink / raw)
  To: Cong Meng
  Cc: Rusty Russell, Nicholas A. Bellinger, stefanha, linuxram,
	Anthony Liguori, senwang, zwanp, James E.J. Bottomley,
	virtualization, linux-kernel, linux-scsi

Il 20/06/2012 08:55, 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.
> 
> Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
> Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>

Looks good (with one nit below), but please rebase over the four patches
at http://permalink.gmane.org/gmane.linux.kernel/1312496

> ---
>  drivers/scsi/virtio_scsi.c  |  109 ++++++++++++++++++++++++++++++++++++++++++-
>  include/linux/virtio_scsi.h |    9 ++++
>  2 files changed, 116 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
> index 1b38431..6dad625 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,9 +44,15 @@ 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;
> +};
> +
>  /* Driver instance state */
>  struct virtio_scsi {
> -	/* Protects ctrl_vq, req_vq and sg[] */
> +	/* Protects ctrl_vq, event_vq, req_vq and sg[] */
>  	spinlock_t vq_lock;
>  
>  	struct virtio_device *vdev;
> @@ -53,6 +60,9 @@ struct virtio_scsi {
>  	struct virtqueue *event_vq;
>  	struct virtqueue *req_vq;
>  
> +	/* Get some buffers reday for event vq */
> +	struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
> +
>  	/* For sglist construction when adding commands to the virtqueue.  */
>  	struct scatterlist sg[];
>  };
> @@ -184,9 +194,93 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
>  	virtscsi_vq_done(vq, virtscsi_complete_free);
>  };
>  
> +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->vq_lock, flags);
> +
> +	ret = virtqueue_add_buf(vscsi->event_vq, &sg, 0, 1, event_node, GFP_ATOMIC);
> +	if (ret >= 0)
> +		virtqueue_kick(vscsi->event_vq);
> +
> +	spin_unlock_irqrestore(&vscsi->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;
> +
> +	switch (event->event) {
> +	case VIRTIO_SCSI_T_TRANSPORT_RESET:
> +		virtscsi_handle_transport_reset(vscsi, event);
> +		break;

Please handle VIRTIO_SCSI_T_NO_EVENT too here, and mask out
VIRTIO_SCSI_T_EVENTS_MISSED even if you do not handle it by triggering a
full rescan.

Paolo

> +	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)
>  {
> -	virtscsi_vq_done(vq, virtscsi_complete_free);
> +	virtscsi_vq_done(vq, virtscsi_complete_event);
>  };
>  
>  static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
> @@ -435,6 +529,11 @@ 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);
> +	}
> +
>  	return 0;
>  }
>  
> @@ -532,7 +631,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
> 

Thanks,

Paolo

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

* Re: [PATCH] virtio-scsi: hotplug suppot for virtio-scsi
  2012-07-01 13:24 ` Paolo Bonzini
@ 2012-07-02  7:20   ` mc
  2012-07-02  8:11     ` Paolo Bonzini
  0 siblings, 1 reply; 4+ messages in thread
From: mc @ 2012-07-02  7:20 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Rusty Russell, Nicholas A. Bellinger, stefanha, linuxram,
	Anthony Liguori, senwang, zwanp, James E.J. Bottomley,
	virtualization, linux-kernel, linux-scsi


Quoting Paolo Bonzini <pbonzini@redhat.com>:

> Il 20/06/2012 08:55, 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.
>>
>> Signed-off-by: Cong Meng <mc@linux.vnet.ibm.com>
>> Signed-off-by: Sen Wang <senwang@linux.vnet.ibm.com>
>
> Looks good (with one nit below), but please rebase over the four patches
> at http://permalink.gmane.org/gmane.linux.kernel/1312496
>
>> ---
>>  drivers/scsi/virtio_scsi.c  |  109  
>> ++++++++++++++++++++++++++++++++++++++++++-
>>  include/linux/virtio_scsi.h |    9 ++++
>>  2 files changed, 116 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
>> index 1b38431..6dad625 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,9 +44,15 @@ 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;
>> +};
>> +
>>  /* Driver instance state */
>>  struct virtio_scsi {
>> -	/* Protects ctrl_vq, req_vq and sg[] */
>> +	/* Protects ctrl_vq, event_vq, req_vq and sg[] */
>>  	spinlock_t vq_lock;
>>
>>  	struct virtio_device *vdev;
>> @@ -53,6 +60,9 @@ struct virtio_scsi {
>>  	struct virtqueue *event_vq;
>>  	struct virtqueue *req_vq;
>>
>> +	/* Get some buffers reday for event vq */
>> +	struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
>> +
>>  	/* For sglist construction when adding commands to the virtqueue.  */
>>  	struct scatterlist sg[];
>>  };
>> @@ -184,9 +194,93 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
>>  	virtscsi_vq_done(vq, virtscsi_complete_free);
>>  };
>>
>> +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->vq_lock, flags);
>> +
>> +	ret = virtqueue_add_buf(vscsi->event_vq, &sg, 0, 1, event_node,  
>> GFP_ATOMIC);
>> +	if (ret >= 0)
>> +		virtqueue_kick(vscsi->event_vq);
>> +
>> +	spin_unlock_irqrestore(&vscsi->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;
>> +
>> +	switch (event->event) {
>> +	case VIRTIO_SCSI_T_TRANSPORT_RESET:
>> +		virtscsi_handle_transport_reset(vscsi, event);
>> +		break;
>
> Please handle VIRTIO_SCSI_T_NO_EVENT too here, and mask out
> VIRTIO_SCSI_T_EVENTS_MISSED even if you do not handle it by triggering a
> full rescan.
>
Paolo, what's the appropriate action to response VIRTIO_SCSI_T_NO_EVENT
event? An error message?

I also have some confusion on VIRTIO_SCSI_T_EVENTS_MISSED:
Should VIRTIO_SCSI_T_EVENTS_MISSED always be used with other event flag?
For instanse:
(VIRTIO_SCSI_T_EVENTS_MISSED|VIRTIO_SCSI_T_TRANSPORT_RESET) is used to report
hotplug event dropped when a buffer available.

Thanks.
Cong.

> Paolo
>
>> +	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)
>>  {
>> -	virtscsi_vq_done(vq, virtscsi_complete_free);
>> +	virtscsi_vq_done(vq, virtscsi_complete_event);
>>  };
>>
>>  static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
>> @@ -435,6 +529,11 @@ 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);
>> +	}
>> +
>>  	return 0;
>>  }
>>
>> @@ -532,7 +631,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
>>
>
> Thanks,
>
> Paolo




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

* Re: [PATCH] virtio-scsi: hotplug suppot for virtio-scsi
  2012-07-02  7:20   ` mc
@ 2012-07-02  8:11     ` Paolo Bonzini
  0 siblings, 0 replies; 4+ messages in thread
From: Paolo Bonzini @ 2012-07-02  8:11 UTC (permalink / raw)
  To: mc
  Cc: Rusty Russell, Nicholas A. Bellinger, stefanha, linuxram,
	Anthony Liguori, senwang, zwanp, James E.J. Bottomley,
	virtualization, linux-kernel, linux-scsi

Il 02/07/2012 09:20, mc@linux.vnet.ibm.com ha scritto:
>>> +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;
>>> +
>>> +    switch (event->event) {
>>> +    case VIRTIO_SCSI_T_TRANSPORT_RESET:
>>> +        virtscsi_handle_transport_reset(vscsi, event);
>>> +        break;
>>
>> Please handle VIRTIO_SCSI_T_NO_EVENT too here, and mask out
>> VIRTIO_SCSI_T_EVENTS_MISSED even if you do not handle it by triggering a
>> full rescan.
>>
> Paolo, what's the appropriate action to response VIRTIO_SCSI_T_NO_EVENT
> event? An error message?

No, just do nothing.

> I also have some confusion on VIRTIO_SCSI_T_EVENTS_MISSED:
> Should VIRTIO_SCSI_T_EVENTS_MISSED always be used with other event flag?

Yes.

> For instanse:
> (VIRTIO_SCSI_T_EVENTS_MISSED|VIRTIO_SCSI_T_TRANSPORT_RESET) is used to
> report hotplug event dropped when a buffer available.

The idea in the spec was that QEMU would report VIRTIO_SCSI_T_NO_EVENT |
VIRTIO_SCSI_T_EVENTS_MISSED as soon as a buffer becomes available, but
technically this is indeed possible.  So you need to handle
VIRTIO_SCSI_T_EVENTS_MISSED first, and the other bits separately.

Paolo

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

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

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-20  6:55 [PATCH] virtio-scsi: hotplug suppot for virtio-scsi Cong Meng
2012-07-01 13:24 ` Paolo Bonzini
2012-07-02  7:20   ` mc
2012-07-02  8:11     ` Paolo Bonzini

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).