linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel.
@ 2007-07-25 14:41 David Woodhouse
  2007-07-26  1:27 ` Michael Ellerman
  0 siblings, 1 reply; 6+ messages in thread
From: David Woodhouse @ 2007-07-25 14:41 UTC (permalink / raw)
  To: Stephen Rothwell, Paul Mackerras; +Cc: linuxppc-dev

If you build a multiplatform kernel for iSeries and pSeries, with
ibmvscsic support, the resulting client doesn't work on iSeries.

This patch should fix that, using the appropriate low-level operations
for the machine detected at runtime.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/rpa_vscsi.c~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/rpa_vscsi.c	2006-12-19 15:42:57.000000000 +0000
@@ -42,14 +42,14 @@ static unsigned int partition_number = -
  * Routines for managing the command/response queue
  */
 /**
- * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * rpavscsi_handle_event: - Interrupt handler for crq events
  * @irq:	number of irq to handle, not used
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
  *
  * Disables interrupts and schedules srp_task
  * Always returns IRQ_HANDLED
  */
-static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
+static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
 {
 	struct ibmvscsi_host_data *hostdata =
 	    (struct ibmvscsi_host_data *)dev_instance;
@@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event
  * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
  * the crq with the hypervisor.
  */
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests)
+static void rpavscsi_release_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata,
+				       int max_requests)
 {
 	long rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * rpavscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word2:	the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+			     u64 word1, u64 word2)
 {
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 
@@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_ho
 }
 
 /**
- * ibmvscsi_task: - Process srps asynchronously
+ * rpavscsi_task: - Process srps asynchronously
  * @data:	ibmvscsi_host_data of host
  */
-static void ibmvscsi_task(void *data)
+static void rpavscsi_task(void *data)
 {
 	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -189,6 +190,42 @@ static void set_adapter_info(struct ibmv
 }
 
 /**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ */
+static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
+				    struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	/* Close the CRQ */
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
+
+	/* Clean out the queue */
+	memset(queue->msgs, 0x00, PAGE_SIZE);
+	queue->cur = 0;
+
+	set_adapter_info(hostdata);
+
+	/* And re-open it again */
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+	} else if (rc != 0) {
+		printk(KERN_WARNING
+		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+	}
+	return rc;
+}
+/**
  * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
  * @queue:	crq_queue to initialize and register
  * @hostdata:	ibmvscsi_host_data of host
@@ -197,9 +234,9 @@ static void set_adapter_info(struct ibmv
  * the crq with the hypervisor.
  * Returns zero on success.
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests)
+static int rpavscsi_init_crq_queue(struct crq_queue *queue,
+				   struct ibmvscsi_host_data *hostdata,
+				   int max_requests)
 {
 	int rc;
 	int retrc;
@@ -226,7 +263,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 				queue->msg_token, PAGE_SIZE);
 	if (rc == H_RESOURCE)
 		/* maybe kexecing and resource is busy. try a reset */
-		rc = ibmvscsi_reset_crq_queue(queue,
+		rc = rpavscsi_reset_crq_queue(queue,
 					      hostdata);
 
 	if (rc == 2) {
@@ -239,7 +276,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 	}
 
 	if (request_irq(vdev->irq,
-			ibmvscsi_handle_event,
+			rpavscsi_handle_event,
 			0, "ibmvscsi", (void *)hostdata) != 0) {
 		printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
 		       vdev->irq);
@@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 	queue->cur = 0;
 	spin_lock_init(&queue->lock);
 
-	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
 		     (unsigned long)hostdata);
 
 	return retrc;
@@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_q
  * @hostdata:	ibmvscsi_host_data of host
  *
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				 struct ibmvscsi_host_data *hostdata)
+static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata)
 {
 	int rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -297,39 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct c
 	return rc;
 }
 
-/**
- * reset_crq_queue: - resets a crq after a failure
- * @queue:	crq_queue to initialize and register
- * @hostdata:	ibmvscsi_host_data of host
- *
- */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata)
-{
-	int rc;
-	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
-
-	/* Close the CRQ */
-	do {
-		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
-
-	/* Clean out the queue */
-	memset(queue->msgs, 0x00, PAGE_SIZE);
-	queue->cur = 0;
-
-	set_adapter_info(hostdata);
-
-	/* And re-open it again */
-	rc = plpar_hcall_norets(H_REG_CRQ,
-				vdev->unit_address,
-				queue->msg_token, PAGE_SIZE);
-	if (rc == 2) {
-		/* Adapter is good, but other end is not ready */
-		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
-	} else if (rc != 0) {
-		printk(KERN_WARNING
-		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
-	}
-	return rc;
-}
+struct ibmvscsi_ops rpavscsi_ops = {
+	.init_crq_queue = rpavscsi_init_crq_queue,
+	.release_crq_queue = rpavscsi_release_crq_queue,
+	.reset_crq_queue = rpavscsi_reset_crq_queue,
+	.reenable_crq_queue = rpavscsi_reenable_crq_queue,
+	.send_crq = rpavscsi_send_crq,
+};
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.c~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.c	2006-12-19 15:53:59.000000000 +0000
@@ -89,6 +89,8 @@ static int max_requests = 50;
 
 #define IBMVSCSI_VERSION "1.5.8"
 
+static struct ibmvscsi_ops *ibmvscsi_ops;
+
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
 MODULE_LICENSE("GPL");
@@ -567,7 +569,7 @@ static int ibmvscsi_send_srp_event(struc
 	list_add_tail(&evt_struct->list, &hostdata->sent);
 
 	if ((rc =
-	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+	     ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
 		list_del(&evt_struct->list);
 
 		printk(KERN_ERR "ibmvscsi: send error %d\n",
@@ -1183,8 +1185,8 @@ void ibmvscsi_handle_crq(struct viosrp_c
 		case 0x01:	/* Initialization message */
 			printk(KERN_INFO "ibmvscsi: partner initialized\n");
 			/* Send back a response */
-			if (ibmvscsi_send_crq(hostdata,
-					      0xC002000000000000LL, 0) == 0) {
+			if (ibmvscsi_ops->send_crq(hostdata,
+						   0xC002000000000000LL, 0) == 0) {
 				/* Now login */
 				send_srp_login(hostdata);
 			} else {
@@ -1212,10 +1214,10 @@ void ibmvscsi_handle_crq(struct viosrp_c
 			printk(KERN_INFO
 			       "ibmvscsi: Re-enabling adapter!\n");
 			purge_requests(hostdata, DID_REQUEUE);
-			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
-							hostdata)) ||
-			    (ibmvscsi_send_crq(hostdata,
-					       0xC001000000000000LL, 0))) {
+			if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue,
+							      hostdata)) ||
+			    (ibmvscsi_ops->send_crq(hostdata,
+						    0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
 					printk(KERN_ERR
@@ -1228,10 +1230,10 @@ void ibmvscsi_handle_crq(struct viosrp_c
 			       crq->format);
 
 			purge_requests(hostdata, DID_ERROR);
-			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
-							hostdata)) ||
-			    (ibmvscsi_send_crq(hostdata,
-					       0xC001000000000000LL, 0))) {
+			if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue,
+							   hostdata)) ||
+			    (ibmvscsi_ops->send_crq(hostdata,
+						    0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
 					printk(KERN_ERR
@@ -1517,7 +1519,7 @@ static int ibmvscsi_probe(struct vio_dev
 	atomic_set(&hostdata->request_limit, -1);
 	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 
-	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+	rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
 	if (rc != 0 && rc != H_RESOURCE) {
 		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
 		goto init_crq_failed;
@@ -1538,7 +1540,7 @@ static int ibmvscsi_probe(struct vio_dev
 	 * to fail if the other end is not acive.  In that case we don't
 	 * want to scan
 	 */
-	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+	if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
 	    || rc == H_RESOURCE) {
 		/*
 		 * Wait around max init_timeout secs for the adapter to finish
@@ -1564,7 +1566,7 @@ static int ibmvscsi_probe(struct vio_dev
       add_host_failed:
 	release_event_pool(&hostdata->pool, hostdata);
       init_pool_failed:
-	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
       init_crq_failed:
 	scsi_host_put(host);
       scsi_host_alloc_failed:
@@ -1575,8 +1577,8 @@ static int ibmvscsi_remove(struct vio_de
 {
 	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
 	release_event_pool(&hostdata->pool, hostdata);
-	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
-				   max_requests);
+	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
+					max_requests);
 	
 	scsi_remove_host(hostdata->host);
 	scsi_host_put(hostdata->host);
@@ -1606,6 +1608,13 @@ static struct vio_driver ibmvscsi_driver
 
 int __init ibmvscsi_module_init(void)
 {
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		ibmvscsi_ops = &iseriesvscsi_ops;
+	else if (firmware_has_feature(FW_FEATURE_VIO))
+		ibmvscsi_ops = &rpavscsi_ops;
+	else
+		return -ENODEV;
+
 	return vio_register_driver(&ibmvscsi_driver);
 }
 
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.h~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.h	2006-12-19 15:54:18.000000000 +0000
@@ -94,21 +94,25 @@ struct ibmvscsi_host_data {
 };
 
 /* routines for managing a command/response queue */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests);
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests);
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata);
-
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata);
-
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			 struct ibmvscsi_host_data *hostdata);
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
-		      u64 word1, u64 word2);
+
+struct ibmvscsi_ops {
+	int (*init_crq_queue)(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata,
+			      int max_requests);
+	void (*release_crq_queue)(struct crq_queue *queue,
+				  struct ibmvscsi_host_data *hostdata,
+				  int max_requests);
+	int (*reset_crq_queue)(struct crq_queue *queue,
+			       struct ibmvscsi_host_data *hostdata);
+	int (*reenable_crq_queue)(struct crq_queue *queue,
+				  struct ibmvscsi_host_data *hostdata);
+	int (*send_crq)(struct ibmvscsi_host_data *hostdata,
+		       u64 word1, u64 word2);
+};
+
+extern struct ibmvscsi_ops iseriesvscsi_ops;
+extern struct ibmvscsi_ops rpavscsi_ops;
 
 #endif				/* IBMVSCSI_H */
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/iseries_vscsi.c~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/iseries_vscsi.c	2006-12-19 15:47:03.000000000 +0000
@@ -53,7 +53,7 @@ struct srp_lp_event {
 /** 
  * standard interface for handling logical partition events.
  */
-static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
 {
 	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
 
@@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct
 /* ------------------------------------------------------------
  * Routines for driver initialization
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests)
+static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata,
+				       int max_requests)
 {
 	int rc;
 
@@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 		goto viopath_open_failed;
 	}
 
-	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+	rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
 	if (rc < 0) {
 		printk("vio_setHandler failed with rc %d in open_event_path\n",
 		       rc);
@@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_q
 	return -1;
 }
 
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests)
+static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
+					   struct ibmvscsi_host_data *hostdata,
+					   int max_requests)
 {
 	vio_clearHandler(viomajorsubtype_scsi);
 	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
@@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct c
  *
  * no-op for iSeries
  */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
+					struct ibmvscsi_host_data *hostdata)
 {
 	return 0;
 }
@@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_
  *
  * no-op for iSeries
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
+					   struct ibmvscsi_host_data *hostdata)
 {
 	return 0;
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * iseriesvscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word2:	the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+				 u64 word1, u64 word2)
 {
 	single_host_data = hostdata;
 	return HvCallEvent_signalLpEventFast(viopath_hostLp,
@@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_ho
 					     VIOVERSION << 16, word1, word2, 0,
 					     0);
 }
+
+struct ibmvscsi_ops iseriesvscsi_ops = {
+	.init_crq_queue = iseriesvscsi_init_crq_queue,
+	.release_crq_queue = iseriesvscsi_release_crq_queue,
+	.reset_crq_queue = iseriesvscsi_reset_crq_queue,
+	.reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
+	.send_crq = iseriesvscsi_send_crq,
+};
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/Makefile.orig	2007-01-01 20:06:26.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/Makefile	2007-01-01 20:06:35.000000000 +0000
@@ -1,9 +1,7 @@
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
 
 ibmvscsic-y			+= ibmvscsi.o
-ifndef CONFIG_PPC_PSERIES
 ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
-endif
 ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
 
 obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o


-- 
dwmw2

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

* Re: [PATCH] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel.
  2007-07-25 14:41 [PATCH] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel David Woodhouse
@ 2007-07-26  1:27 ` Michael Ellerman
  2007-07-26  7:46   ` David Woodhouse
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Ellerman @ 2007-07-26  1:27 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Stephen Rothwell, Paul Mackerras, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 18694 bytes --]

On Wed, 2007-07-25 at 15:41 +0100, David Woodhouse wrote:
> If you build a multiplatform kernel for iSeries and pSeries, with
> ibmvscsic support, the resulting client doesn't work on iSeries.
> 
> This patch should fix that, using the appropriate low-level operations
> for the machine detected at runtime.
> 
> Signed-off-by: David Woodhouse <dwmw2@infradead.org>

Nice that someone finally fixed this up.

But I get:

drivers/scsi/ibmvscsi/ibmvscsi.c:1651: error: 'FW_FEATURE_ISERIES' undeclared (first use in this function)
drivers/scsi/ibmvscsi/ibmvscsi.c:1651: error: (Each undeclared identifier is reported only once
drivers/scsi/ibmvscsi/ibmvscsi.c:1651: error: for each function it appears in.)
drivers/scsi/ibmvscsi/ibmvscsi.c:1653: error: 'FW_FEATURE_VIO' undeclared (first use in this function)

Missing <asm/firmware.h> ?

cheers


> --- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/rpa_vscsi.c~	2006-11-29 21:57:37.000000000 +0000
> +++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/rpa_vscsi.c	2006-12-19 15:42:57.000000000 +0000
> @@ -42,14 +42,14 @@ static unsigned int partition_number = -
>   * Routines for managing the command/response queue
>   */
>  /**
> - * ibmvscsi_handle_event: - Interrupt handler for crq events
> + * rpavscsi_handle_event: - Interrupt handler for crq events
>   * @irq:	number of irq to handle, not used
>   * @dev_instance: ibmvscsi_host_data of host that received interrupt
>   *
>   * Disables interrupts and schedules srp_task
>   * Always returns IRQ_HANDLED
>   */
> -static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
> +static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
>  {
>  	struct ibmvscsi_host_data *hostdata =
>  	    (struct ibmvscsi_host_data *)dev_instance;
> @@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event
>   * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
>   * the crq with the hypervisor.
>   */
> -void ibmvscsi_release_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata,
> -				int max_requests)
> +static void rpavscsi_release_crq_queue(struct crq_queue *queue,
> +				       struct ibmvscsi_host_data *hostdata,
> +				       int max_requests)
>  {
>  	long rc;
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> @@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next
>  }
>  
>  /**
> - * ibmvscsi_send_crq: - Send a CRQ
> + * rpavscsi_send_crq: - Send a CRQ
>   * @hostdata:	the adapter
>   * @word1:	the first 64 bits of the data
>   * @word2:	the second 64 bits of the data
>   */
> -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
> +static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
> +			     u64 word1, u64 word2)
>  {
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
>  
> @@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_ho
>  }
>  
>  /**
> - * ibmvscsi_task: - Process srps asynchronously
> + * rpavscsi_task: - Process srps asynchronously
>   * @data:	ibmvscsi_host_data of host
>   */
> -static void ibmvscsi_task(void *data)
> +static void rpavscsi_task(void *data)
>  {
>  	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> @@ -189,6 +190,42 @@ static void set_adapter_info(struct ibmv
>  }
>  
>  /**
> + * reset_crq_queue: - resets a crq after a failure
> + * @queue:	crq_queue to initialize and register
> + * @hostdata:	ibmvscsi_host_data of host
> + *
> + */
> +static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
> +				    struct ibmvscsi_host_data *hostdata)
> +{
> +	int rc;
> +	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> +
> +	/* Close the CRQ */
> +	do {
> +		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
> +	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
> +
> +	/* Clean out the queue */
> +	memset(queue->msgs, 0x00, PAGE_SIZE);
> +	queue->cur = 0;
> +
> +	set_adapter_info(hostdata);
> +
> +	/* And re-open it again */
> +	rc = plpar_hcall_norets(H_REG_CRQ,
> +				vdev->unit_address,
> +				queue->msg_token, PAGE_SIZE);
> +	if (rc == 2) {
> +		/* Adapter is good, but other end is not ready */
> +		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
> +	} else if (rc != 0) {
> +		printk(KERN_WARNING
> +		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
> +	}
> +	return rc;
> +}
> +/**
>   * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
>   * @queue:	crq_queue to initialize and register
>   * @hostdata:	ibmvscsi_host_data of host
> @@ -197,9 +234,9 @@ static void set_adapter_info(struct ibmv
>   * the crq with the hypervisor.
>   * Returns zero on success.
>   */
> -int ibmvscsi_init_crq_queue(struct crq_queue *queue,
> -			    struct ibmvscsi_host_data *hostdata,
> -			    int max_requests)
> +static int rpavscsi_init_crq_queue(struct crq_queue *queue,
> +				   struct ibmvscsi_host_data *hostdata,
> +				   int max_requests)
>  {
>  	int rc;
>  	int retrc;
> @@ -226,7 +263,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
>  				queue->msg_token, PAGE_SIZE);
>  	if (rc == H_RESOURCE)
>  		/* maybe kexecing and resource is busy. try a reset */
> -		rc = ibmvscsi_reset_crq_queue(queue,
> +		rc = rpavscsi_reset_crq_queue(queue,
>  					      hostdata);
>  
>  	if (rc == 2) {
> @@ -239,7 +276,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
>  	}
>  
>  	if (request_irq(vdev->irq,
> -			ibmvscsi_handle_event,
> +			rpavscsi_handle_event,
>  			0, "ibmvscsi", (void *)hostdata) != 0) {
>  		printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
>  		       vdev->irq);
> @@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
>  	queue->cur = 0;
>  	spin_lock_init(&queue->lock);
>  
> -	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
> +	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
>  		     (unsigned long)hostdata);
>  
>  	return retrc;
> @@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_q
>   * @hostdata:	ibmvscsi_host_data of host
>   *
>   */
> -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
> -				 struct ibmvscsi_host_data *hostdata)
> +static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
> +				       struct ibmvscsi_host_data *hostdata)
>  {
>  	int rc;
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> @@ -297,39 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct c
>  	return rc;
>  }
>  
> -/**
> - * reset_crq_queue: - resets a crq after a failure
> - * @queue:	crq_queue to initialize and register
> - * @hostdata:	ibmvscsi_host_data of host
> - *
> - */
> -int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
> -			      struct ibmvscsi_host_data *hostdata)
> -{
> -	int rc;
> -	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> -
> -	/* Close the CRQ */
> -	do {
> -		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
> -	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
> -
> -	/* Clean out the queue */
> -	memset(queue->msgs, 0x00, PAGE_SIZE);
> -	queue->cur = 0;
> -
> -	set_adapter_info(hostdata);
> -
> -	/* And re-open it again */
> -	rc = plpar_hcall_norets(H_REG_CRQ,
> -				vdev->unit_address,
> -				queue->msg_token, PAGE_SIZE);
> -	if (rc == 2) {
> -		/* Adapter is good, but other end is not ready */
> -		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
> -	} else if (rc != 0) {
> -		printk(KERN_WARNING
> -		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
> -	}
> -	return rc;
> -}
> +struct ibmvscsi_ops rpavscsi_ops = {
> +	.init_crq_queue = rpavscsi_init_crq_queue,
> +	.release_crq_queue = rpavscsi_release_crq_queue,
> +	.reset_crq_queue = rpavscsi_reset_crq_queue,
> +	.reenable_crq_queue = rpavscsi_reenable_crq_queue,
> +	.send_crq = rpavscsi_send_crq,
> +};
> --- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.c~	2006-11-29 21:57:37.000000000 +0000
> +++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.c	2006-12-19 15:53:59.000000000 +0000
> @@ -89,6 +89,8 @@ static int max_requests = 50;
>  
>  #define IBMVSCSI_VERSION "1.5.8"
>  
> +static struct ibmvscsi_ops *ibmvscsi_ops;
> +
>  MODULE_DESCRIPTION("IBM Virtual SCSI");
>  MODULE_AUTHOR("Dave Boutcher");
>  MODULE_LICENSE("GPL");
> @@ -567,7 +569,7 @@ static int ibmvscsi_send_srp_event(struc
>  	list_add_tail(&evt_struct->list, &hostdata->sent);
>  
>  	if ((rc =
> -	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
> +	     ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
>  		list_del(&evt_struct->list);
>  
>  		printk(KERN_ERR "ibmvscsi: send error %d\n",
> @@ -1183,8 +1185,8 @@ void ibmvscsi_handle_crq(struct viosrp_c
>  		case 0x01:	/* Initialization message */
>  			printk(KERN_INFO "ibmvscsi: partner initialized\n");
>  			/* Send back a response */
> -			if (ibmvscsi_send_crq(hostdata,
> -					      0xC002000000000000LL, 0) == 0) {
> +			if (ibmvscsi_ops->send_crq(hostdata,
> +						   0xC002000000000000LL, 0) == 0) {
>  				/* Now login */
>  				send_srp_login(hostdata);
>  			} else {
> @@ -1212,10 +1214,10 @@ void ibmvscsi_handle_crq(struct viosrp_c
>  			printk(KERN_INFO
>  			       "ibmvscsi: Re-enabling adapter!\n");
>  			purge_requests(hostdata, DID_REQUEUE);
> -			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
> -							hostdata)) ||
> -			    (ibmvscsi_send_crq(hostdata,
> -					       0xC001000000000000LL, 0))) {
> +			if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue,
> +							      hostdata)) ||
> +			    (ibmvscsi_ops->send_crq(hostdata,
> +						    0xC001000000000000LL, 0))) {
>  					atomic_set(&hostdata->request_limit,
>  						   -1);
>  					printk(KERN_ERR
> @@ -1228,10 +1230,10 @@ void ibmvscsi_handle_crq(struct viosrp_c
>  			       crq->format);
>  
>  			purge_requests(hostdata, DID_ERROR);
> -			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
> -							hostdata)) ||
> -			    (ibmvscsi_send_crq(hostdata,
> -					       0xC001000000000000LL, 0))) {
> +			if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue,
> +							   hostdata)) ||
> +			    (ibmvscsi_ops->send_crq(hostdata,
> +						    0xC001000000000000LL, 0))) {
>  					atomic_set(&hostdata->request_limit,
>  						   -1);
>  					printk(KERN_ERR
> @@ -1517,7 +1519,7 @@ static int ibmvscsi_probe(struct vio_dev
>  	atomic_set(&hostdata->request_limit, -1);
>  	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
>  
> -	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
> +	rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
>  	if (rc != 0 && rc != H_RESOURCE) {
>  		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
>  		goto init_crq_failed;
> @@ -1538,7 +1540,7 @@ static int ibmvscsi_probe(struct vio_dev
>  	 * to fail if the other end is not acive.  In that case we don't
>  	 * want to scan
>  	 */
> -	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
> +	if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
>  	    || rc == H_RESOURCE) {
>  		/*
>  		 * Wait around max init_timeout secs for the adapter to finish
> @@ -1564,7 +1566,7 @@ static int ibmvscsi_probe(struct vio_dev
>        add_host_failed:
>  	release_event_pool(&hostdata->pool, hostdata);
>        init_pool_failed:
> -	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
> +	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
>        init_crq_failed:
>  	scsi_host_put(host);
>        scsi_host_alloc_failed:
> @@ -1575,8 +1577,8 @@ static int ibmvscsi_remove(struct vio_de
>  {
>  	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
>  	release_event_pool(&hostdata->pool, hostdata);
> -	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
> -				   max_requests);
> +	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
> +					max_requests);
>  	
>  	scsi_remove_host(hostdata->host);
>  	scsi_host_put(hostdata->host);
> @@ -1606,6 +1608,13 @@ static struct vio_driver ibmvscsi_driver
>  
>  int __init ibmvscsi_module_init(void)
>  {
> +	if (firmware_has_feature(FW_FEATURE_ISERIES))
> +		ibmvscsi_ops = &iseriesvscsi_ops;
> +	else if (firmware_has_feature(FW_FEATURE_VIO))
> +		ibmvscsi_ops = &rpavscsi_ops;
> +	else
> +		return -ENODEV;
> +
>  	return vio_register_driver(&ibmvscsi_driver);
>  }
>  
> --- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.h~	2006-11-29 21:57:37.000000000 +0000
> +++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.h	2006-12-19 15:54:18.000000000 +0000
> @@ -94,21 +94,25 @@ struct ibmvscsi_host_data {
>  };
>  
>  /* routines for managing a command/response queue */
> -int ibmvscsi_init_crq_queue(struct crq_queue *queue,
> -			    struct ibmvscsi_host_data *hostdata,
> -			    int max_requests);
> -void ibmvscsi_release_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata,
> -				int max_requests);
> -int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
> -			      struct ibmvscsi_host_data *hostdata);
> -
> -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata);
> -
>  void ibmvscsi_handle_crq(struct viosrp_crq *crq,
>  			 struct ibmvscsi_host_data *hostdata);
> -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
> -		      u64 word1, u64 word2);
> +
> +struct ibmvscsi_ops {
> +	int (*init_crq_queue)(struct crq_queue *queue,
> +			      struct ibmvscsi_host_data *hostdata,
> +			      int max_requests);
> +	void (*release_crq_queue)(struct crq_queue *queue,
> +				  struct ibmvscsi_host_data *hostdata,
> +				  int max_requests);
> +	int (*reset_crq_queue)(struct crq_queue *queue,
> +			       struct ibmvscsi_host_data *hostdata);
> +	int (*reenable_crq_queue)(struct crq_queue *queue,
> +				  struct ibmvscsi_host_data *hostdata);
> +	int (*send_crq)(struct ibmvscsi_host_data *hostdata,
> +		       u64 word1, u64 word2);
> +};
> +
> +extern struct ibmvscsi_ops iseriesvscsi_ops;
> +extern struct ibmvscsi_ops rpavscsi_ops;
>  
>  #endif				/* IBMVSCSI_H */
> --- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/iseries_vscsi.c~	2006-11-29 21:57:37.000000000 +0000
> +++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/iseries_vscsi.c	2006-12-19 15:47:03.000000000 +0000
> @@ -53,7 +53,7 @@ struct srp_lp_event {
>  /** 
>   * standard interface for handling logical partition events.
>   */
> -static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
> +static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
>  {
>  	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
>  
> @@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct
>  /* ------------------------------------------------------------
>   * Routines for driver initialization
>   */
> -int ibmvscsi_init_crq_queue(struct crq_queue *queue,
> -			    struct ibmvscsi_host_data *hostdata,
> -			    int max_requests)
> +static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
> +				       struct ibmvscsi_host_data *hostdata,
> +				       int max_requests)
>  {
>  	int rc;
>  
> @@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
>  		goto viopath_open_failed;
>  	}
>  
> -	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
> +	rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
>  	if (rc < 0) {
>  		printk("vio_setHandler failed with rc %d in open_event_path\n",
>  		       rc);
> @@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_q
>  	return -1;
>  }
>  
> -void ibmvscsi_release_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata,
> -				int max_requests)
> +static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
> +					   struct ibmvscsi_host_data *hostdata,
> +					   int max_requests)
>  {
>  	vio_clearHandler(viomajorsubtype_scsi);
>  	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
> @@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct c
>   *
>   * no-op for iSeries
>   */
> -int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
> -			      struct ibmvscsi_host_data *hostdata)
> +static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
> +					struct ibmvscsi_host_data *hostdata)
>  {
>  	return 0;
>  }
> @@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_
>   *
>   * no-op for iSeries
>   */
> -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata)
> +static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
> +					   struct ibmvscsi_host_data *hostdata)
>  {
>  	return 0;
>  }
>  
>  /**
> - * ibmvscsi_send_crq: - Send a CRQ
> + * iseriesvscsi_send_crq: - Send a CRQ
>   * @hostdata:	the adapter
>   * @word1:	the first 64 bits of the data
>   * @word2:	the second 64 bits of the data
>   */
> -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
> +static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
> +				 u64 word1, u64 word2)
>  {
>  	single_host_data = hostdata;
>  	return HvCallEvent_signalLpEventFast(viopath_hostLp,
> @@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_ho
>  					     VIOVERSION << 16, word1, word2, 0,
>  					     0);
>  }
> +
> +struct ibmvscsi_ops iseriesvscsi_ops = {
> +	.init_crq_queue = iseriesvscsi_init_crq_queue,
> +	.release_crq_queue = iseriesvscsi_release_crq_queue,
> +	.reset_crq_queue = iseriesvscsi_reset_crq_queue,
> +	.reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
> +	.send_crq = iseriesvscsi_send_crq,
> +};
> --- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/Makefile.orig	2007-01-01 20:06:26.000000000 +0000
> +++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/Makefile	2007-01-01 20:06:35.000000000 +0000
> @@ -1,9 +1,7 @@
>  obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
>  
>  ibmvscsic-y			+= ibmvscsi.o
> -ifndef CONFIG_PPC_PSERIES
>  ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
> -endif
>  ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
>  
>  obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o
> 
> 
-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [PATCH] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel.
  2007-07-26  1:27 ` Michael Ellerman
@ 2007-07-26  7:46   ` David Woodhouse
  2007-07-26  8:00     ` [PATCH v2] " David Woodhouse
  0 siblings, 1 reply; 6+ messages in thread
From: David Woodhouse @ 2007-07-26  7:46 UTC (permalink / raw)
  To: michael; +Cc: Stephen Rothwell, Paul Mackerras, linuxppc-dev

On Thu, 2007-07-26 at 11:27 +1000, Michael Ellerman wrote:
> Nice that someone finally fixed this up.
> 
> But I get:
> 
> drivers/scsi/ibmvscsi/ibmvscsi.c:1651: error: 'FW_FEATURE_ISERIES' undeclared (first use in this function)
> drivers/scsi/ibmvscsi/ibmvscsi.c:1651: error: (Each undeclared identifier is reported only once
> drivers/scsi/ibmvscsi/ibmvscsi.c:1651: error: for each function it appears in.)
> drivers/scsi/ibmvscsi/ibmvscsi.c:1653: error: 'FW_FEATURE_VIO' undeclared (first use in this function)
> 
> Missing <asm/firmware.h> ? 

Hm, I wonder why it ever worked for me then...

Ah, it seems that <asm/time.h> only includes <asm/firmware.h> if
CONFIG_PPC_ISERIES. We should include <asm/firmware.h> directly from
ibmvscsi.c rather than relying on it being pulled in indirectly. I'll
send a new patch. Thanks.

-- 
dwmw2

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

* [PATCH v2] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel.
  2007-07-26  7:46   ` David Woodhouse
@ 2007-07-26  8:00     ` David Woodhouse
  2007-07-31 11:42       ` [PATCH v3] " David Woodhouse
  0 siblings, 1 reply; 6+ messages in thread
From: David Woodhouse @ 2007-07-26  8:00 UTC (permalink / raw)
  To: michael; +Cc: Stephen Rothwell, Paul Mackerras, linuxppc-dev

If you build a multiplatform kernel for iSeries and pSeries, with
ibmvscsic support, the resulting client doesn't work on iSeries.

This patch should fix that, using the appropriate low-level operations
for the machine detected at runtime.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/rpa_vscsi.c~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/rpa_vscsi.c	2006-12-19 15:42:57.000000000 +0000
@@ -42,14 +42,14 @@ static unsigned int partition_number = -
  * Routines for managing the command/response queue
  */
 /**
- * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * rpavscsi_handle_event: - Interrupt handler for crq events
  * @irq:	number of irq to handle, not used
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
  *
  * Disables interrupts and schedules srp_task
  * Always returns IRQ_HANDLED
  */
-static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
+static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
 {
 	struct ibmvscsi_host_data *hostdata =
 	    (struct ibmvscsi_host_data *)dev_instance;
@@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event
  * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
  * the crq with the hypervisor.
  */
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests)
+static void rpavscsi_release_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata,
+				       int max_requests)
 {
 	long rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * rpavscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word2:	the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+			     u64 word1, u64 word2)
 {
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 
@@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_ho
 }
 
 /**
- * ibmvscsi_task: - Process srps asynchronously
+ * rpavscsi_task: - Process srps asynchronously
  * @data:	ibmvscsi_host_data of host
  */
-static void ibmvscsi_task(void *data)
+static void rpavscsi_task(void *data)
 {
 	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -189,6 +190,42 @@ static void set_adapter_info(struct ibmv
 }
 
 /**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ */
+static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
+				    struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	/* Close the CRQ */
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
+
+	/* Clean out the queue */
+	memset(queue->msgs, 0x00, PAGE_SIZE);
+	queue->cur = 0;
+
+	set_adapter_info(hostdata);
+
+	/* And re-open it again */
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+	} else if (rc != 0) {
+		printk(KERN_WARNING
+		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+	}
+	return rc;
+}
+/**
  * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
  * @queue:	crq_queue to initialize and register
  * @hostdata:	ibmvscsi_host_data of host
@@ -197,9 +234,9 @@ static void set_adapter_info(struct ibmv
  * the crq with the hypervisor.
  * Returns zero on success.
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests)
+static int rpavscsi_init_crq_queue(struct crq_queue *queue,
+				   struct ibmvscsi_host_data *hostdata,
+				   int max_requests)
 {
 	int rc;
 	int retrc;
@@ -226,7 +263,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 				queue->msg_token, PAGE_SIZE);
 	if (rc == H_RESOURCE)
 		/* maybe kexecing and resource is busy. try a reset */
-		rc = ibmvscsi_reset_crq_queue(queue,
+		rc = rpavscsi_reset_crq_queue(queue,
 					      hostdata);
 
 	if (rc == 2) {
@@ -239,7 +276,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 	}
 
 	if (request_irq(vdev->irq,
-			ibmvscsi_handle_event,
+			rpavscsi_handle_event,
 			0, "ibmvscsi", (void *)hostdata) != 0) {
 		printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
 		       vdev->irq);
@@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 	queue->cur = 0;
 	spin_lock_init(&queue->lock);
 
-	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
 		     (unsigned long)hostdata);
 
 	return retrc;
@@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_q
  * @hostdata:	ibmvscsi_host_data of host
  *
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				 struct ibmvscsi_host_data *hostdata)
+static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata)
 {
 	int rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -297,39 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct c
 	return rc;
 }
 
-/**
- * reset_crq_queue: - resets a crq after a failure
- * @queue:	crq_queue to initialize and register
- * @hostdata:	ibmvscsi_host_data of host
- *
- */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata)
-{
-	int rc;
-	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
-
-	/* Close the CRQ */
-	do {
-		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
-
-	/* Clean out the queue */
-	memset(queue->msgs, 0x00, PAGE_SIZE);
-	queue->cur = 0;
-
-	set_adapter_info(hostdata);
-
-	/* And re-open it again */
-	rc = plpar_hcall_norets(H_REG_CRQ,
-				vdev->unit_address,
-				queue->msg_token, PAGE_SIZE);
-	if (rc == 2) {
-		/* Adapter is good, but other end is not ready */
-		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
-	} else if (rc != 0) {
-		printk(KERN_WARNING
-		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
-	}
-	return rc;
-}
+struct ibmvscsi_ops rpavscsi_ops = {
+	.init_crq_queue = rpavscsi_init_crq_queue,
+	.release_crq_queue = rpavscsi_release_crq_queue,
+	.reset_crq_queue = rpavscsi_reset_crq_queue,
+	.reenable_crq_queue = rpavscsi_reenable_crq_queue,
+	.send_crq = rpavscsi_send_crq,
+};
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.c~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.c	2006-12-19 15:53:59.000000000 +0000
@@ -70,6 +70,7 @@
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <asm/firmware.h>
 #include <asm/vio.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -89,6 +89,8 @@ static int max_requests = 50;
 
 #define IBMVSCSI_VERSION "1.5.8"
 
+static struct ibmvscsi_ops *ibmvscsi_ops;
+
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
 MODULE_LICENSE("GPL");
@@ -567,7 +569,7 @@ static int ibmvscsi_send_srp_event(struc
 	list_add_tail(&evt_struct->list, &hostdata->sent);
 
 	if ((rc =
-	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+	     ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
 		list_del(&evt_struct->list);
 
 		printk(KERN_ERR "ibmvscsi: send error %d\n",
@@ -1183,8 +1185,8 @@ void ibmvscsi_handle_crq(struct viosrp_c
 		case 0x01:	/* Initialization message */
 			printk(KERN_INFO "ibmvscsi: partner initialized\n");
 			/* Send back a response */
-			if (ibmvscsi_send_crq(hostdata,
-					      0xC002000000000000LL, 0) == 0) {
+			if (ibmvscsi_ops->send_crq(hostdata,
+						   0xC002000000000000LL, 0) == 0) {
 				/* Now login */
 				send_srp_login(hostdata);
 			} else {
@@ -1212,10 +1214,10 @@ void ibmvscsi_handle_crq(struct viosrp_c
 			printk(KERN_INFO
 			       "ibmvscsi: Re-enabling adapter!\n");
 			purge_requests(hostdata, DID_REQUEUE);
-			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
-							hostdata)) ||
-			    (ibmvscsi_send_crq(hostdata,
-					       0xC001000000000000LL, 0))) {
+			if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue,
+							      hostdata)) ||
+			    (ibmvscsi_ops->send_crq(hostdata,
+						    0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
 					printk(KERN_ERR
@@ -1228,10 +1230,10 @@ void ibmvscsi_handle_crq(struct viosrp_c
 			       crq->format);
 
 			purge_requests(hostdata, DID_ERROR);
-			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
-							hostdata)) ||
-			    (ibmvscsi_send_crq(hostdata,
-					       0xC001000000000000LL, 0))) {
+			if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue,
+							   hostdata)) ||
+			    (ibmvscsi_ops->send_crq(hostdata,
+						    0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
 					printk(KERN_ERR
@@ -1517,7 +1519,7 @@ static int ibmvscsi_probe(struct vio_dev
 	atomic_set(&hostdata->request_limit, -1);
 	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 
-	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+	rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
 	if (rc != 0 && rc != H_RESOURCE) {
 		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
 		goto init_crq_failed;
@@ -1538,7 +1540,7 @@ static int ibmvscsi_probe(struct vio_dev
 	 * to fail if the other end is not acive.  In that case we don't
 	 * want to scan
 	 */
-	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+	if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
 	    || rc == H_RESOURCE) {
 		/*
 		 * Wait around max init_timeout secs for the adapter to finish
@@ -1564,7 +1566,7 @@ static int ibmvscsi_probe(struct vio_dev
       add_host_failed:
 	release_event_pool(&hostdata->pool, hostdata);
       init_pool_failed:
-	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
       init_crq_failed:
 	scsi_host_put(host);
       scsi_host_alloc_failed:
@@ -1575,8 +1577,8 @@ static int ibmvscsi_remove(struct vio_de
 {
 	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
 	release_event_pool(&hostdata->pool, hostdata);
-	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
-				   max_requests);
+	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
+					max_requests);
 	
 	scsi_remove_host(hostdata->host);
 	scsi_host_put(hostdata->host);
@@ -1606,6 +1608,13 @@ static struct vio_driver ibmvscsi_driver
 
 int __init ibmvscsi_module_init(void)
 {
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		ibmvscsi_ops = &iseriesvscsi_ops;
+	else if (firmware_has_feature(FW_FEATURE_VIO))
+		ibmvscsi_ops = &rpavscsi_ops;
+	else
+		return -ENODEV;
+
 	return vio_register_driver(&ibmvscsi_driver);
 }
 
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.h~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/ibmvscsi.h	2006-12-19 15:54:18.000000000 +0000
@@ -94,21 +94,25 @@ struct ibmvscsi_host_data {
 };
 
 /* routines for managing a command/response queue */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests);
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests);
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata);
-
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata);
-
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			 struct ibmvscsi_host_data *hostdata);
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
-		      u64 word1, u64 word2);
+
+struct ibmvscsi_ops {
+	int (*init_crq_queue)(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata,
+			      int max_requests);
+	void (*release_crq_queue)(struct crq_queue *queue,
+				  struct ibmvscsi_host_data *hostdata,
+				  int max_requests);
+	int (*reset_crq_queue)(struct crq_queue *queue,
+			       struct ibmvscsi_host_data *hostdata);
+	int (*reenable_crq_queue)(struct crq_queue *queue,
+				  struct ibmvscsi_host_data *hostdata);
+	int (*send_crq)(struct ibmvscsi_host_data *hostdata,
+		       u64 word1, u64 word2);
+};
+
+extern struct ibmvscsi_ops iseriesvscsi_ops;
+extern struct ibmvscsi_ops rpavscsi_ops;
 
 #endif				/* IBMVSCSI_H */
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/iseries_vscsi.c~	2006-11-29 21:57:37.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/iseries_vscsi.c	2006-12-19 15:47:03.000000000 +0000
@@ -53,7 +53,7 @@ struct srp_lp_event {
 /** 
  * standard interface for handling logical partition events.
  */
-static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
 {
 	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
 
@@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct
 /* ------------------------------------------------------------
  * Routines for driver initialization
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests)
+static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata,
+				       int max_requests)
 {
 	int rc;
 
@@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_q
 		goto viopath_open_failed;
 	}
 
-	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+	rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
 	if (rc < 0) {
 		printk("vio_setHandler failed with rc %d in open_event_path\n",
 		       rc);
@@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_q
 	return -1;
 }
 
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests)
+static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
+					   struct ibmvscsi_host_data *hostdata,
+					   int max_requests)
 {
 	vio_clearHandler(viomajorsubtype_scsi);
 	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
@@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct c
  *
  * no-op for iSeries
  */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
+					struct ibmvscsi_host_data *hostdata)
 {
 	return 0;
 }
@@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_
  *
  * no-op for iSeries
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
+					   struct ibmvscsi_host_data *hostdata)
 {
 	return 0;
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * iseriesvscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word2:	the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+				 u64 word1, u64 word2)
 {
 	single_host_data = hostdata;
 	return HvCallEvent_signalLpEventFast(viopath_hostLp,
@@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_ho
 					     VIOVERSION << 16, word1, word2, 0,
 					     0);
 }
+
+struct ibmvscsi_ops iseriesvscsi_ops = {
+	.init_crq_queue = iseriesvscsi_init_crq_queue,
+	.release_crq_queue = iseriesvscsi_release_crq_queue,
+	.reset_crq_queue = iseriesvscsi_reset_crq_queue,
+	.reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
+	.send_crq = iseriesvscsi_send_crq,
+};
--- linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/Makefile.orig	2007-01-01 20:06:26.000000000 +0000
+++ linux-2.6.19.ppc64/drivers/scsi/ibmvscsi/Makefile	2007-01-01 20:06:35.000000000 +0000
@@ -1,9 +1,7 @@
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
 
 ibmvscsic-y			+= ibmvscsi.o
-ifndef CONFIG_PPC_PSERIES
 ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
-endif
 ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
 
 obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o


-- 
dwmw2

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

* [PATCH v3] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel.
  2007-07-26  8:00     ` [PATCH v2] " David Woodhouse
@ 2007-07-31 11:42       ` David Woodhouse
  2007-08-03 20:51         ` Brian King
  0 siblings, 1 reply; 6+ messages in thread
From: David Woodhouse @ 2007-07-31 11:42 UTC (permalink / raw)
  To: michael, Brian King; +Cc: Stephen Rothwell, Paul Mackerras, linuxppc-dev

If you build a multiplatform kernel for iSeries and pSeries, with
ibmvscsic support, the resulting client doesn't work on iSeries.

This patch should fix that, using the appropriate low-level operations
for the machine detected at runtime.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

---
This third version of the patch is updated to apply to Linus' current
git tree following the recent ibmvscsi updates.

diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 9c14e78..1821461 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -42,14 +42,14 @@ static unsigned int partition_number = -1;
  * Routines for managing the command/response queue
  */
 /**
- * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * rpavscsi_handle_event: - Interrupt handler for crq events
  * @irq:	number of irq to handle, not used
  * @dev_instance: ibmvscsi_host_data of host that received interrupt
  *
  * Disables interrupts and schedules srp_task
  * Always returns IRQ_HANDLED
  */
-static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
+static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
 {
 	struct ibmvscsi_host_data *hostdata =
 	    (struct ibmvscsi_host_data *)dev_instance;
@@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
  * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
  * the crq with the hypervisor.
  */
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests)
+static void rpavscsi_release_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata,
+				       int max_requests)
 {
 	long rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * rpavscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word2:	the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+			     u64 word1, u64 word2)
 {
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 
@@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
 }
 
 /**
- * ibmvscsi_task: - Process srps asynchronously
+ * rpavscsi_task: - Process srps asynchronously
  * @data:	ibmvscsi_host_data of host
  */
-static void ibmvscsi_task(void *data)
+static void rpavscsi_task(void *data)
 {
 	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -190,6 +191,42 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
 }
 
 /**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ */
+static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
+				    struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	/* Close the CRQ */
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
+
+	/* Clean out the queue */
+	memset(queue->msgs, 0x00, PAGE_SIZE);
+	queue->cur = 0;
+
+	set_adapter_info(hostdata);
+
+	/* And re-open it again */
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		dev_warn(hostdata->dev, "Partner adapter not ready\n");
+	} else if (rc != 0) {
+		dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
+	}
+	return rc;
+}
+
+/**
  * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
  * @queue:	crq_queue to initialize and register
  * @hostdata:	ibmvscsi_host_data of host
@@ -198,9 +235,9 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
  * the crq with the hypervisor.
  * Returns zero on success.
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests)
+static int rpavscsi_init_crq_queue(struct crq_queue *queue,
+				   struct ibmvscsi_host_data *hostdata,
+				   int max_requests)
 {
 	int rc;
 	int retrc;
@@ -227,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 				queue->msg_token, PAGE_SIZE);
 	if (rc == H_RESOURCE)
 		/* maybe kexecing and resource is busy. try a reset */
-		rc = ibmvscsi_reset_crq_queue(queue,
+		rc = rpavscsi_reset_crq_queue(queue,
 					      hostdata);
 
 	if (rc == 2) {
@@ -240,7 +277,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 	}
 
 	if (request_irq(vdev->irq,
-			ibmvscsi_handle_event,
+			rpavscsi_handle_event,
 			0, "ibmvscsi", (void *)hostdata) != 0) {
 		dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
 			vdev->irq);
@@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 	queue->cur = 0;
 	spin_lock_init(&queue->lock);
 
-	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
 		     (unsigned long)hostdata);
 
 	return retrc;
@@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
  * @hostdata:	ibmvscsi_host_data of host
  *
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				 struct ibmvscsi_host_data *hostdata)
+static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata)
 {
 	int rc;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
@@ -297,38 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
 	return rc;
 }
 
-/**
- * reset_crq_queue: - resets a crq after a failure
- * @queue:	crq_queue to initialize and register
- * @hostdata:	ibmvscsi_host_data of host
- *
- */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata)
-{
-	int rc;
-	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
-
-	/* Close the CRQ */
-	do {
-		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
-
-	/* Clean out the queue */
-	memset(queue->msgs, 0x00, PAGE_SIZE);
-	queue->cur = 0;
-
-	set_adapter_info(hostdata);
-
-	/* And re-open it again */
-	rc = plpar_hcall_norets(H_REG_CRQ,
-				vdev->unit_address,
-				queue->msg_token, PAGE_SIZE);
-	if (rc == 2) {
-		/* Adapter is good, but other end is not ready */
-		dev_warn(hostdata->dev, "Partner adapter not ready\n");
-	} else if (rc != 0) {
-		dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
-	}
-	return rc;
-}
+struct ibmvscsi_ops rpavscsi_ops = {
+	.init_crq_queue = rpavscsi_init_crq_queue,
+	.release_crq_queue = rpavscsi_release_crq_queue,
+	.reset_crq_queue = rpavscsi_reset_crq_queue,
+	.reenable_crq_queue = rpavscsi_reenable_crq_queue,
+	.send_crq = rpavscsi_send_crq,
+};
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 5870866..ed9b675 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -70,6 +70,7 @@
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <asm/firmware.h>
 #include <asm/vio.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -89,6 +90,8 @@ static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
 
 #define IBMVSCSI_VERSION "1.5.8"
 
+static struct ibmvscsi_ops *ibmvscsi_ops;
+
 MODULE_DESCRIPTION("IBM Virtual SCSI");
 MODULE_AUTHOR("Dave Boutcher");
 MODULE_LICENSE("GPL");
@@ -512,8 +515,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
 	atomic_set(&hostdata->request_limit, 0);
 
 	purge_requests(hostdata, DID_ERROR);
-	if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) ||
-	    (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) ||
+	if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) ||
+	    (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) ||
 	    (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
 		atomic_set(&hostdata->request_limit, -1);
 		dev_err(hostdata->dev, "error after reset\n");
@@ -618,7 +621,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
 	}
 
 	if ((rc =
-	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+	     ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
 		list_del(&evt_struct->list);
 		del_timer(&evt_struct->timer);
 
@@ -1222,8 +1225,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 		case 0x01:	/* Initialization message */
 			dev_info(hostdata->dev, "partner initialized\n");
 			/* Send back a response */
-			if ((rc = ibmvscsi_send_crq(hostdata,
-						    0xC002000000000000LL, 0)) == 0) {
+			if ((rc = ibmvscsi_ops->send_crq(hostdata,
+							 0xC002000000000000LL, 0)) == 0) {
 				/* Now login */
 				send_srp_login(hostdata);
 			} else {
@@ -1248,10 +1251,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			/* We need to re-setup the interpartition connection */
 			dev_info(hostdata->dev, "Re-enabling adapter!\n");
 			purge_requests(hostdata, DID_REQUEUE);
-			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
-							hostdata)) ||
-			    (ibmvscsi_send_crq(hostdata,
-					       0xC001000000000000LL, 0))) {
+			if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue,
+							      hostdata)) ||
+			    (ibmvscsi_ops->send_crq(hostdata,
+						    0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
 					dev_err(hostdata->dev, "error after enable\n");
@@ -1261,10 +1264,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 				crq->format);
 
 			purge_requests(hostdata, DID_ERROR);
-			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
-							hostdata)) ||
-			    (ibmvscsi_send_crq(hostdata,
-					       0xC001000000000000LL, 0))) {
+			if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue,
+							   hostdata)) ||
+			    (ibmvscsi_ops->send_crq(hostdata,
+						    0xC001000000000000LL, 0))) {
 					atomic_set(&hostdata->request_limit,
 						   -1);
 					dev_err(hostdata->dev, "error after reset\n");
@@ -1590,7 +1593,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 	atomic_set(&hostdata->request_limit, -1);
 	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
 
-	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
+	rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
 	if (rc != 0 && rc != H_RESOURCE) {
 		dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
 		goto init_crq_failed;
@@ -1611,7 +1614,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 	 * to fail if the other end is not acive.  In that case we don't
 	 * want to scan
 	 */
-	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
+	if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
 	    || rc == H_RESOURCE) {
 		/*
 		 * Wait around max init_timeout secs for the adapter to finish
@@ -1637,7 +1640,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
       add_host_failed:
 	release_event_pool(&hostdata->pool, hostdata);
       init_pool_failed:
-	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
       init_crq_failed:
 	scsi_host_put(host);
       scsi_host_alloc_failed:
@@ -1648,8 +1651,8 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
 {
 	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
 	release_event_pool(&hostdata->pool, hostdata);
-	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
-				   max_requests);
+	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
+					max_requests);
 	
 	scsi_remove_host(hostdata->host);
 	scsi_host_put(hostdata->host);
@@ -1679,6 +1682,13 @@ static struct vio_driver ibmvscsi_driver = {
 
 int __init ibmvscsi_module_init(void)
 {
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		ibmvscsi_ops = &iseriesvscsi_ops;
+	else if (firmware_has_feature(FW_FEATURE_VIO))
+		ibmvscsi_ops = &rpavscsi_ops;
+	else
+		return -ENODEV;
+
 	return vio_register_driver(&ibmvscsi_driver);
 }
 
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index b19c2e2..46e850e 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -98,21 +98,25 @@ struct ibmvscsi_host_data {
 };
 
 /* routines for managing a command/response queue */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests);
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests);
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata);
-
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata);
-
 void ibmvscsi_handle_crq(struct viosrp_crq *crq,
 			 struct ibmvscsi_host_data *hostdata);
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
-		      u64 word1, u64 word2);
+
+struct ibmvscsi_ops {
+	int (*init_crq_queue)(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata,
+			      int max_requests);
+	void (*release_crq_queue)(struct crq_queue *queue,
+				  struct ibmvscsi_host_data *hostdata,
+				  int max_requests);
+	int (*reset_crq_queue)(struct crq_queue *queue,
+			       struct ibmvscsi_host_data *hostdata);
+	int (*reenable_crq_queue)(struct crq_queue *queue,
+				  struct ibmvscsi_host_data *hostdata);
+	int (*send_crq)(struct ibmvscsi_host_data *hostdata,
+		       u64 word1, u64 word2);
+};
+
+extern struct ibmvscsi_ops iseriesvscsi_ops;
+extern struct ibmvscsi_ops rpavscsi_ops;
 
 #endif				/* IBMVSCSI_H */
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index 6aeb5f0..0775fde 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -53,7 +53,7 @@ struct srp_lp_event {
 /** 
  * standard interface for handling logical partition events.
  */
-static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
 {
 	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
 
@@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
 /* ------------------------------------------------------------
  * Routines for driver initialization
  */
-int ibmvscsi_init_crq_queue(struct crq_queue *queue,
-			    struct ibmvscsi_host_data *hostdata,
-			    int max_requests)
+static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
+				       struct ibmvscsi_host_data *hostdata,
+				       int max_requests)
 {
 	int rc;
 
@@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 		goto viopath_open_failed;
 	}
 
-	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+	rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
 	if (rc < 0) {
 		printk("vio_setHandler failed with rc %d in open_event_path\n",
 		       rc);
@@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
 	return -1;
 }
 
-void ibmvscsi_release_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata,
-				int max_requests)
+static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
+					   struct ibmvscsi_host_data *hostdata,
+					   int max_requests)
 {
 	vio_clearHandler(viomajorsubtype_scsi);
 	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
@@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
  *
  * no-op for iSeries
  */
-int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
-			      struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
+					struct ibmvscsi_host_data *hostdata)
 {
 	return 0;
 }
@@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
  *
  * no-op for iSeries
  */
-int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
-				struct ibmvscsi_host_data *hostdata)
+static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
+					   struct ibmvscsi_host_data *hostdata)
 {
 	return 0;
 }
 
 /**
- * ibmvscsi_send_crq: - Send a CRQ
+ * iseriesvscsi_send_crq: - Send a CRQ
  * @hostdata:	the adapter
  * @word1:	the first 64 bits of the data
  * @word2:	the second 64 bits of the data
  */
-int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+				 u64 word1, u64 word2)
 {
 	single_host_data = hostdata;
 	return HvCallEvent_signalLpEventFast(viopath_hostLp,
@@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
 					     VIOVERSION << 16, word1, word2, 0,
 					     0);
 }
+
+struct ibmvscsi_ops iseriesvscsi_ops = {
+	.init_crq_queue = iseriesvscsi_init_crq_queue,
+	.release_crq_queue = iseriesvscsi_release_crq_queue,
+	.reset_crq_queue = iseriesvscsi_reset_crq_queue,
+	.reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
+	.send_crq = iseriesvscsi_send_crq,
+};
diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
index f67d9ef..6ac0633 100644
--- a/drivers/scsi/ibmvscsi/Makefile
+++ b/drivers/scsi/ibmvscsi/Makefile
@@ -1,9 +1,7 @@
 obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
 
 ibmvscsic-y			+= ibmvscsi.o
-ifndef CONFIG_PPC_PSERIES
 ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
-endif
 ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
 
 obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o

-- 
dwmw2

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

* Re: [PATCH v3] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel.
  2007-07-31 11:42       ` [PATCH v3] " David Woodhouse
@ 2007-08-03 20:51         ` Brian King
  0 siblings, 0 replies; 6+ messages in thread
From: Brian King @ 2007-08-03 20:51 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Stephen Rothwell, Paul Mackerras, linuxppc-dev

Acked by: Brian King <brking@linux.vnet.ibm.com>

David Woodhouse wrote:
> If you build a multiplatform kernel for iSeries and pSeries, with
> ibmvscsic support, the resulting client doesn't work on iSeries.
> 
> This patch should fix that, using the appropriate low-level operations
> for the machine detected at runtime.
> 
> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
> 
> ---
> This third version of the patch is updated to apply to Linus' current
> git tree following the recent ibmvscsi updates.
> 
> diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
> index 9c14e78..1821461 100644
> --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
> +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
> @@ -42,14 +42,14 @@ static unsigned int partition_number = -1;
>   * Routines for managing the command/response queue
>   */
>  /**
> - * ibmvscsi_handle_event: - Interrupt handler for crq events
> + * rpavscsi_handle_event: - Interrupt handler for crq events
>   * @irq:	number of irq to handle, not used
>   * @dev_instance: ibmvscsi_host_data of host that received interrupt
>   *
>   * Disables interrupts and schedules srp_task
>   * Always returns IRQ_HANDLED
>   */
> -static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
> +static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
>  {
>  	struct ibmvscsi_host_data *hostdata =
>  	    (struct ibmvscsi_host_data *)dev_instance;
> @@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance)
>   * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
>   * the crq with the hypervisor.
>   */
> -void ibmvscsi_release_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata,
> -				int max_requests)
> +static void rpavscsi_release_crq_queue(struct crq_queue *queue,
> +				       struct ibmvscsi_host_data *hostdata,
> +				       int max_requests)
>  {
>  	long rc;
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> @@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
>  }
> 
>  /**
> - * ibmvscsi_send_crq: - Send a CRQ
> + * rpavscsi_send_crq: - Send a CRQ
>   * @hostdata:	the adapter
>   * @word1:	the first 64 bits of the data
>   * @word2:	the second 64 bits of the data
>   */
> -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
> +static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
> +			     u64 word1, u64 word2)
>  {
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> 
> @@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
>  }
> 
>  /**
> - * ibmvscsi_task: - Process srps asynchronously
> + * rpavscsi_task: - Process srps asynchronously
>   * @data:	ibmvscsi_host_data of host
>   */
> -static void ibmvscsi_task(void *data)
> +static void rpavscsi_task(void *data)
>  {
>  	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> @@ -190,6 +191,42 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
>  }
> 
>  /**
> + * reset_crq_queue: - resets a crq after a failure
> + * @queue:	crq_queue to initialize and register
> + * @hostdata:	ibmvscsi_host_data of host
> + *
> + */
> +static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
> +				    struct ibmvscsi_host_data *hostdata)
> +{
> +	int rc;
> +	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> +
> +	/* Close the CRQ */
> +	do {
> +		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
> +	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
> +
> +	/* Clean out the queue */
> +	memset(queue->msgs, 0x00, PAGE_SIZE);
> +	queue->cur = 0;
> +
> +	set_adapter_info(hostdata);
> +
> +	/* And re-open it again */
> +	rc = plpar_hcall_norets(H_REG_CRQ,
> +				vdev->unit_address,
> +				queue->msg_token, PAGE_SIZE);
> +	if (rc == 2) {
> +		/* Adapter is good, but other end is not ready */
> +		dev_warn(hostdata->dev, "Partner adapter not ready\n");
> +	} else if (rc != 0) {
> +		dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
> +	}
> +	return rc;
> +}
> +
> +/**
>   * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
>   * @queue:	crq_queue to initialize and register
>   * @hostdata:	ibmvscsi_host_data of host
> @@ -198,9 +235,9 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
>   * the crq with the hypervisor.
>   * Returns zero on success.
>   */
> -int ibmvscsi_init_crq_queue(struct crq_queue *queue,
> -			    struct ibmvscsi_host_data *hostdata,
> -			    int max_requests)
> +static int rpavscsi_init_crq_queue(struct crq_queue *queue,
> +				   struct ibmvscsi_host_data *hostdata,
> +				   int max_requests)
>  {
>  	int rc;
>  	int retrc;
> @@ -227,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
>  				queue->msg_token, PAGE_SIZE);
>  	if (rc == H_RESOURCE)
>  		/* maybe kexecing and resource is busy. try a reset */
> -		rc = ibmvscsi_reset_crq_queue(queue,
> +		rc = rpavscsi_reset_crq_queue(queue,
>  					      hostdata);
> 
>  	if (rc == 2) {
> @@ -240,7 +277,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
>  	}
> 
>  	if (request_irq(vdev->irq,
> -			ibmvscsi_handle_event,
> +			rpavscsi_handle_event,
>  			0, "ibmvscsi", (void *)hostdata) != 0) {
>  		dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
>  			vdev->irq);
> @@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
>  	queue->cur = 0;
>  	spin_lock_init(&queue->lock);
> 
> -	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
> +	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
>  		     (unsigned long)hostdata);
> 
>  	return retrc;
> @@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
>   * @hostdata:	ibmvscsi_host_data of host
>   *
>   */
> -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
> -				 struct ibmvscsi_host_data *hostdata)
> +static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
> +				       struct ibmvscsi_host_data *hostdata)
>  {
>  	int rc;
>  	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> @@ -297,38 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
>  	return rc;
>  }
> 
> -/**
> - * reset_crq_queue: - resets a crq after a failure
> - * @queue:	crq_queue to initialize and register
> - * @hostdata:	ibmvscsi_host_data of host
> - *
> - */
> -int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
> -			      struct ibmvscsi_host_data *hostdata)
> -{
> -	int rc;
> -	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
> -
> -	/* Close the CRQ */
> -	do {
> -		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
> -	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
> -
> -	/* Clean out the queue */
> -	memset(queue->msgs, 0x00, PAGE_SIZE);
> -	queue->cur = 0;
> -
> -	set_adapter_info(hostdata);
> -
> -	/* And re-open it again */
> -	rc = plpar_hcall_norets(H_REG_CRQ,
> -				vdev->unit_address,
> -				queue->msg_token, PAGE_SIZE);
> -	if (rc == 2) {
> -		/* Adapter is good, but other end is not ready */
> -		dev_warn(hostdata->dev, "Partner adapter not ready\n");
> -	} else if (rc != 0) {
> -		dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
> -	}
> -	return rc;
> -}
> +struct ibmvscsi_ops rpavscsi_ops = {
> +	.init_crq_queue = rpavscsi_init_crq_queue,
> +	.release_crq_queue = rpavscsi_release_crq_queue,
> +	.reset_crq_queue = rpavscsi_reset_crq_queue,
> +	.reenable_crq_queue = rpavscsi_reenable_crq_queue,
> +	.send_crq = rpavscsi_send_crq,
> +};
> diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
> index 5870866..ed9b675 100644
> --- a/drivers/scsi/ibmvscsi/ibmvscsi.c
> +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
> @@ -70,6 +70,7 @@
>  #include <linux/moduleparam.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/delay.h>
> +#include <asm/firmware.h>
>  #include <asm/vio.h>
>  #include <scsi/scsi.h>
>  #include <scsi/scsi_cmnd.h>
> @@ -89,6 +90,8 @@ static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
> 
>  #define IBMVSCSI_VERSION "1.5.8"
> 
> +static struct ibmvscsi_ops *ibmvscsi_ops;
> +
>  MODULE_DESCRIPTION("IBM Virtual SCSI");
>  MODULE_AUTHOR("Dave Boutcher");
>  MODULE_LICENSE("GPL");
> @@ -512,8 +515,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
>  	atomic_set(&hostdata->request_limit, 0);
> 
>  	purge_requests(hostdata, DID_ERROR);
> -	if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) ||
> -	    (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) ||
> +	if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) ||
> +	    (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) ||
>  	    (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) {
>  		atomic_set(&hostdata->request_limit, -1);
>  		dev_err(hostdata->dev, "error after reset\n");
> @@ -618,7 +621,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
>  	}
> 
>  	if ((rc =
> -	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
> +	     ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
>  		list_del(&evt_struct->list);
>  		del_timer(&evt_struct->timer);
> 
> @@ -1222,8 +1225,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
>  		case 0x01:	/* Initialization message */
>  			dev_info(hostdata->dev, "partner initialized\n");
>  			/* Send back a response */
> -			if ((rc = ibmvscsi_send_crq(hostdata,
> -						    0xC002000000000000LL, 0)) == 0) {
> +			if ((rc = ibmvscsi_ops->send_crq(hostdata,
> +							 0xC002000000000000LL, 0)) == 0) {
>  				/* Now login */
>  				send_srp_login(hostdata);
>  			} else {
> @@ -1248,10 +1251,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
>  			/* We need to re-setup the interpartition connection */
>  			dev_info(hostdata->dev, "Re-enabling adapter!\n");
>  			purge_requests(hostdata, DID_REQUEUE);
> -			if ((ibmvscsi_reenable_crq_queue(&hostdata->queue,
> -							hostdata)) ||
> -			    (ibmvscsi_send_crq(hostdata,
> -					       0xC001000000000000LL, 0))) {
> +			if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue,
> +							      hostdata)) ||
> +			    (ibmvscsi_ops->send_crq(hostdata,
> +						    0xC001000000000000LL, 0))) {
>  					atomic_set(&hostdata->request_limit,
>  						   -1);
>  					dev_err(hostdata->dev, "error after enable\n");
> @@ -1261,10 +1264,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
>  				crq->format);
> 
>  			purge_requests(hostdata, DID_ERROR);
> -			if ((ibmvscsi_reset_crq_queue(&hostdata->queue,
> -							hostdata)) ||
> -			    (ibmvscsi_send_crq(hostdata,
> -					       0xC001000000000000LL, 0))) {
> +			if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue,
> +							   hostdata)) ||
> +			    (ibmvscsi_ops->send_crq(hostdata,
> +						    0xC001000000000000LL, 0))) {
>  					atomic_set(&hostdata->request_limit,
>  						   -1);
>  					dev_err(hostdata->dev, "error after reset\n");
> @@ -1590,7 +1593,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
>  	atomic_set(&hostdata->request_limit, -1);
>  	hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
> 
> -	rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests);
> +	rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
>  	if (rc != 0 && rc != H_RESOURCE) {
>  		dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
>  		goto init_crq_failed;
> @@ -1611,7 +1614,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
>  	 * to fail if the other end is not acive.  In that case we don't
>  	 * want to scan
>  	 */
> -	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0
> +	if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0
>  	    || rc == H_RESOURCE) {
>  		/*
>  		 * Wait around max init_timeout secs for the adapter to finish
> @@ -1637,7 +1640,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
>        add_host_failed:
>  	release_event_pool(&hostdata->pool, hostdata);
>        init_pool_failed:
> -	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
> +	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
>        init_crq_failed:
>  	scsi_host_put(host);
>        scsi_host_alloc_failed:
> @@ -1648,8 +1651,8 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
>  {
>  	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
>  	release_event_pool(&hostdata->pool, hostdata);
> -	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
> -				   max_requests);
> +	ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
> +					max_requests);
>  	
>  	scsi_remove_host(hostdata->host);
>  	scsi_host_put(hostdata->host);
> @@ -1679,6 +1682,13 @@ static struct vio_driver ibmvscsi_driver = {
> 
>  int __init ibmvscsi_module_init(void)
>  {
> +	if (firmware_has_feature(FW_FEATURE_ISERIES))
> +		ibmvscsi_ops = &iseriesvscsi_ops;
> +	else if (firmware_has_feature(FW_FEATURE_VIO))
> +		ibmvscsi_ops = &rpavscsi_ops;
> +	else
> +		return -ENODEV;
> +
>  	return vio_register_driver(&ibmvscsi_driver);
>  }
> 
> diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
> index b19c2e2..46e850e 100644
> --- a/drivers/scsi/ibmvscsi/ibmvscsi.h
> +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
> @@ -98,21 +98,25 @@ struct ibmvscsi_host_data {
>  };
> 
>  /* routines for managing a command/response queue */
> -int ibmvscsi_init_crq_queue(struct crq_queue *queue,
> -			    struct ibmvscsi_host_data *hostdata,
> -			    int max_requests);
> -void ibmvscsi_release_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata,
> -				int max_requests);
> -int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
> -			      struct ibmvscsi_host_data *hostdata);
> -
> -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata);
> -
>  void ibmvscsi_handle_crq(struct viosrp_crq *crq,
>  			 struct ibmvscsi_host_data *hostdata);
> -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
> -		      u64 word1, u64 word2);
> +
> +struct ibmvscsi_ops {
> +	int (*init_crq_queue)(struct crq_queue *queue,
> +			      struct ibmvscsi_host_data *hostdata,
> +			      int max_requests);
> +	void (*release_crq_queue)(struct crq_queue *queue,
> +				  struct ibmvscsi_host_data *hostdata,
> +				  int max_requests);
> +	int (*reset_crq_queue)(struct crq_queue *queue,
> +			       struct ibmvscsi_host_data *hostdata);
> +	int (*reenable_crq_queue)(struct crq_queue *queue,
> +				  struct ibmvscsi_host_data *hostdata);
> +	int (*send_crq)(struct ibmvscsi_host_data *hostdata,
> +		       u64 word1, u64 word2);
> +};
> +
> +extern struct ibmvscsi_ops iseriesvscsi_ops;
> +extern struct ibmvscsi_ops rpavscsi_ops;
> 
>  #endif				/* IBMVSCSI_H */
> diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
> index 6aeb5f0..0775fde 100644
> --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
> +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
> @@ -53,7 +53,7 @@ struct srp_lp_event {
>  /** 
>   * standard interface for handling logical partition events.
>   */
> -static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
> +static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
>  {
>  	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
> 
> @@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
>  /* ------------------------------------------------------------
>   * Routines for driver initialization
>   */
> -int ibmvscsi_init_crq_queue(struct crq_queue *queue,
> -			    struct ibmvscsi_host_data *hostdata,
> -			    int max_requests)
> +static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
> +				       struct ibmvscsi_host_data *hostdata,
> +				       int max_requests)
>  {
>  	int rc;
> 
> @@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
>  		goto viopath_open_failed;
>  	}
> 
> -	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
> +	rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
>  	if (rc < 0) {
>  		printk("vio_setHandler failed with rc %d in open_event_path\n",
>  		       rc);
> @@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
>  	return -1;
>  }
> 
> -void ibmvscsi_release_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata,
> -				int max_requests)
> +static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
> +					   struct ibmvscsi_host_data *hostdata,
> +					   int max_requests)
>  {
>  	vio_clearHandler(viomajorsubtype_scsi);
>  	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
> @@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue,
>   *
>   * no-op for iSeries
>   */
> -int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
> -			      struct ibmvscsi_host_data *hostdata)
> +static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
> +					struct ibmvscsi_host_data *hostdata)
>  {
>  	return 0;
>  }
> @@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
>   *
>   * no-op for iSeries
>   */
> -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue,
> -				struct ibmvscsi_host_data *hostdata)
> +static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
> +					   struct ibmvscsi_host_data *hostdata)
>  {
>  	return 0;
>  }
> 
>  /**
> - * ibmvscsi_send_crq: - Send a CRQ
> + * iseriesvscsi_send_crq: - Send a CRQ
>   * @hostdata:	the adapter
>   * @word1:	the first 64 bits of the data
>   * @word2:	the second 64 bits of the data
>   */
> -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
> +static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
> +				 u64 word1, u64 word2)
>  {
>  	single_host_data = hostdata;
>  	return HvCallEvent_signalLpEventFast(viopath_hostLp,
> @@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
>  					     VIOVERSION << 16, word1, word2, 0,
>  					     0);
>  }
> +
> +struct ibmvscsi_ops iseriesvscsi_ops = {
> +	.init_crq_queue = iseriesvscsi_init_crq_queue,
> +	.release_crq_queue = iseriesvscsi_release_crq_queue,
> +	.reset_crq_queue = iseriesvscsi_reset_crq_queue,
> +	.reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
> +	.send_crq = iseriesvscsi_send_crq,
> +};
> diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
> index f67d9ef..6ac0633 100644
> --- a/drivers/scsi/ibmvscsi/Makefile
> +++ b/drivers/scsi/ibmvscsi/Makefile
> @@ -1,9 +1,7 @@
>  obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
> 
>  ibmvscsic-y			+= ibmvscsi.o
> -ifndef CONFIG_PPC_PSERIES
>  ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
> -endif
>  ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
> 
>  obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvstgt.o
> 


-- 
Brian King
Linux on Power Virtualization
IBM Linux Technology Center

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

end of thread, other threads:[~2007-08-03 20:51 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-25 14:41 [PATCH] Fix ibmvscsi client for multiplatform iSeries+pSeries kernel David Woodhouse
2007-07-26  1:27 ` Michael Ellerman
2007-07-26  7:46   ` David Woodhouse
2007-07-26  8:00     ` [PATCH v2] " David Woodhouse
2007-07-31 11:42       ` [PATCH v3] " David Woodhouse
2007-08-03 20:51         ` Brian King

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