X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fibmvscsi%2Frpa_vscsi.c;h=1a9992bdfef85ef944886e4a3f9fb334f34ed64f;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=50cb909f314f43ddfbb5436c752601c6adbe1b29;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 50cb909f3..1a9992bdf 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -28,12 +28,16 @@ */ #include +#include #include #include #include #include #include "ibmvscsi.h" +static char partition_name[97] = "UNKNOWN"; +static unsigned int partition_number = -1; + /* ------------------------------------------------------------ * Routines for managing the command/response queue */ @@ -75,7 +79,7 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue, tasklet_kill(&hostdata->srp_task); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); - } while ((rc == H_Busy) || (H_isLongBusy(rc))); + } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); dma_unmap_single(hostdata->dev, queue->msg_token, queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); @@ -148,6 +152,48 @@ static void ibmvscsi_task(void *data) } } +static void gather_partition_info(void) +{ + struct device_node *rootdn; + + char *ppartition_name; + unsigned int *p_number_ptr; + + /* Retrieve information about this partition */ + rootdn = find_path_device("/"); + if (!rootdn) { + return; + } + + ppartition_name = + get_property(rootdn, "ibm,partition-name", NULL); + if (ppartition_name) + strncpy(partition_name, ppartition_name, + sizeof(partition_name)); + p_number_ptr = + (unsigned int *)get_property(rootdn, "ibm,partition-no", + NULL); + if (p_number_ptr) + partition_number = *p_number_ptr; +} + +static void set_adapter_info(struct ibmvscsi_host_data *hostdata) +{ + memset(&hostdata->madapter_info, 0x00, + sizeof(hostdata->madapter_info)); + + printk(KERN_INFO "rpa_vscsi: SPR_VERSION: %s\n", SRP_VERSION); + strcpy(hostdata->madapter_info.srp_version, SRP_VERSION); + + strncpy(hostdata->madapter_info.partition_name, partition_name, + sizeof(hostdata->madapter_info.partition_name)); + + hostdata->madapter_info.partition_number = partition_number; + + hostdata->madapter_info.mad_version = 1; + hostdata->madapter_info.os_type = 2; +} + /** * initialize_crq_queue: - Initializes and registers CRQ with hypervisor * @queue: crq_queue to initialize and register @@ -177,9 +223,17 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, if (dma_mapping_error(queue->msg_token)) goto map_failed; + gather_partition_info(); + set_adapter_info(hostdata); + rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address, queue->msg_token, PAGE_SIZE); + if (rc == H_RESOURCE) + /* maybe kexecing and resource is busy. try a reset */ + rc = ibmvscsi_reset_crq_queue(queue, + hostdata); + if (rc == 2) { /* Adapter is good, but other end is not ready */ printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n"); @@ -214,7 +268,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, req_irq_failed: do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); - } while ((rc == H_Busy) || (H_isLongBusy(rc))); + } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); reg_crq_failed: dma_unmap_single(hostdata->dev, queue->msg_token, @@ -225,13 +279,35 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, return -1; } +/** + * reenable_crq_queue: - reenables a crq after + * @queue: crq_queue to initialize and register + * @hostdata: ibmvscsi_host_data of host + * + */ +int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) +{ + int rc; + struct vio_dev *vdev = to_vio_dev(hostdata->dev); + + /* Re-enable the CRQ */ + do { + rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); + } while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); + + if (rc) + printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc); + return rc; +} + /** * reset_crq_queue: - resets a crq after a failure * @queue: crq_queue to initialize and register * @hostdata: ibmvscsi_host_data of host * */ -void ibmvscsi_reset_crq_queue(struct crq_queue *queue, +int ibmvscsi_reset_crq_queue(struct crq_queue *queue, struct ibmvscsi_host_data *hostdata) { int rc; @@ -240,12 +316,14 @@ void ibmvscsi_reset_crq_queue(struct crq_queue *queue, /* Close the CRQ */ do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); - } while ((rc == H_Busy) || (H_isLongBusy(rc))); + } 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, @@ -257,4 +335,5 @@ void ibmvscsi_reset_crq_queue(struct crq_queue *queue, printk(KERN_WARNING "ibmvscsi: couldn't register crq--rc 0x%x\n", rc); } + return rc; }