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