diff options
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 133 |
1 files changed, 125 insertions, 8 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 460d4024c46c..aa4e77c25273 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -498,6 +498,11 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) | |||
498 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && | 498 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && |
499 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { | 499 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { |
500 | fsa_dev_ptr->valid = 1; | 500 | fsa_dev_ptr->valid = 1; |
501 | /* sense_key holds the current state of the spin-up */ | ||
502 | if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) | ||
503 | fsa_dev_ptr->sense_data.sense_key = NOT_READY; | ||
504 | else if (fsa_dev_ptr->sense_data.sense_key == NOT_READY) | ||
505 | fsa_dev_ptr->sense_data.sense_key = NO_SENSE; | ||
501 | fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); | 506 | fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); |
502 | fsa_dev_ptr->size | 507 | fsa_dev_ptr->size |
503 | = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + | 508 | = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + |
@@ -1509,20 +1514,35 @@ static void io_callback(void *context, struct fib * fibptr) | |||
1509 | scsi_dma_unmap(scsicmd); | 1514 | scsi_dma_unmap(scsicmd); |
1510 | 1515 | ||
1511 | readreply = (struct aac_read_reply *)fib_data(fibptr); | 1516 | readreply = (struct aac_read_reply *)fib_data(fibptr); |
1512 | if (le32_to_cpu(readreply->status) == ST_OK) | 1517 | switch (le32_to_cpu(readreply->status)) { |
1513 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1518 | case ST_OK: |
1514 | else { | 1519 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | |
1520 | SAM_STAT_GOOD; | ||
1521 | dev->fsa_dev[cid].sense_data.sense_key = NO_SENSE; | ||
1522 | break; | ||
1523 | case ST_NOT_READY: | ||
1524 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | ||
1525 | SAM_STAT_CHECK_CONDITION; | ||
1526 | set_sense(&dev->fsa_dev[cid].sense_data, NOT_READY, | ||
1527 | SENCODE_BECOMING_READY, ASENCODE_BECOMING_READY, 0, 0); | ||
1528 | memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | ||
1529 | min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), | ||
1530 | SCSI_SENSE_BUFFERSIZE)); | ||
1531 | break; | ||
1532 | default: | ||
1515 | #ifdef AAC_DETAILED_STATUS_INFO | 1533 | #ifdef AAC_DETAILED_STATUS_INFO |
1516 | printk(KERN_WARNING "io_callback: io failed, status = %d\n", | 1534 | printk(KERN_WARNING "io_callback: io failed, status = %d\n", |
1517 | le32_to_cpu(readreply->status)); | 1535 | le32_to_cpu(readreply->status)); |
1518 | #endif | 1536 | #endif |
1519 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; | 1537 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | |
1538 | SAM_STAT_CHECK_CONDITION; | ||
1520 | set_sense(&dev->fsa_dev[cid].sense_data, | 1539 | set_sense(&dev->fsa_dev[cid].sense_data, |
1521 | HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, | 1540 | HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, |
1522 | ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0); | 1541 | ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0); |
1523 | memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, | 1542 | memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, |
1524 | min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), | 1543 | min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), |
1525 | SCSI_SENSE_BUFFERSIZE)); | 1544 | SCSI_SENSE_BUFFERSIZE)); |
1545 | break; | ||
1526 | } | 1546 | } |
1527 | aac_fib_complete(fibptr); | 1547 | aac_fib_complete(fibptr); |
1528 | aac_fib_free(fibptr); | 1548 | aac_fib_free(fibptr); |
@@ -1863,6 +1883,84 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) | |||
1863 | return SCSI_MLQUEUE_HOST_BUSY; | 1883 | return SCSI_MLQUEUE_HOST_BUSY; |
1864 | } | 1884 | } |
1865 | 1885 | ||
1886 | static void aac_start_stop_callback(void *context, struct fib *fibptr) | ||
1887 | { | ||
1888 | struct scsi_cmnd *scsicmd = context; | ||
1889 | |||
1890 | if (!aac_valid_context(scsicmd, fibptr)) | ||
1891 | return; | ||
1892 | |||
1893 | BUG_ON(fibptr == NULL); | ||
1894 | |||
1895 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | ||
1896 | |||
1897 | aac_fib_complete(fibptr); | ||
1898 | aac_fib_free(fibptr); | ||
1899 | scsicmd->scsi_done(scsicmd); | ||
1900 | } | ||
1901 | |||
1902 | static int aac_start_stop(struct scsi_cmnd *scsicmd) | ||
1903 | { | ||
1904 | int status; | ||
1905 | struct fib *cmd_fibcontext; | ||
1906 | struct aac_power_management *pmcmd; | ||
1907 | struct scsi_device *sdev = scsicmd->device; | ||
1908 | struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; | ||
1909 | |||
1910 | if (!(aac->supplement_adapter_info.SupportedOptions2 & | ||
1911 | AAC_OPTION_POWER_MANAGEMENT)) { | ||
1912 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | ||
1913 | SAM_STAT_GOOD; | ||
1914 | scsicmd->scsi_done(scsicmd); | ||
1915 | return 0; | ||
1916 | } | ||
1917 | |||
1918 | if (aac->in_reset) | ||
1919 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1920 | |||
1921 | /* | ||
1922 | * Allocate and initialize a Fib | ||
1923 | */ | ||
1924 | cmd_fibcontext = aac_fib_alloc(aac); | ||
1925 | if (!cmd_fibcontext) | ||
1926 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1927 | |||
1928 | aac_fib_init(cmd_fibcontext); | ||
1929 | |||
1930 | pmcmd = fib_data(cmd_fibcontext); | ||
1931 | pmcmd->command = cpu_to_le32(VM_ContainerConfig); | ||
1932 | pmcmd->type = cpu_to_le32(CT_POWER_MANAGEMENT); | ||
1933 | /* Eject bit ignored, not relevant */ | ||
1934 | pmcmd->sub = (scsicmd->cmnd[4] & 1) ? | ||
1935 | cpu_to_le32(CT_PM_START_UNIT) : cpu_to_le32(CT_PM_STOP_UNIT); | ||
1936 | pmcmd->cid = cpu_to_le32(sdev_id(sdev)); | ||
1937 | pmcmd->parm = (scsicmd->cmnd[1] & 1) ? | ||
1938 | cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0; | ||
1939 | |||
1940 | /* | ||
1941 | * Now send the Fib to the adapter | ||
1942 | */ | ||
1943 | status = aac_fib_send(ContainerCommand, | ||
1944 | cmd_fibcontext, | ||
1945 | sizeof(struct aac_power_management), | ||
1946 | FsaNormal, | ||
1947 | 0, 1, | ||
1948 | (fib_callback)aac_start_stop_callback, | ||
1949 | (void *)scsicmd); | ||
1950 | |||
1951 | /* | ||
1952 | * Check that the command queued to the controller | ||
1953 | */ | ||
1954 | if (status == -EINPROGRESS) { | ||
1955 | scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; | ||
1956 | return 0; | ||
1957 | } | ||
1958 | |||
1959 | aac_fib_complete(cmd_fibcontext); | ||
1960 | aac_fib_free(cmd_fibcontext); | ||
1961 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1962 | } | ||
1963 | |||
1866 | /** | 1964 | /** |
1867 | * aac_scsi_cmd() - Process SCSI command | 1965 | * aac_scsi_cmd() - Process SCSI command |
1868 | * @scsicmd: SCSI command block | 1966 | * @scsicmd: SCSI command block |
@@ -1899,7 +1997,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1899 | * If the target container doesn't exist, it may have | 1997 | * If the target container doesn't exist, it may have |
1900 | * been newly created | 1998 | * been newly created |
1901 | */ | 1999 | */ |
1902 | if ((fsa_dev_ptr[cid].valid & 1) == 0) { | 2000 | if (((fsa_dev_ptr[cid].valid & 1) == 0) || |
2001 | (fsa_dev_ptr[cid].sense_data.sense_key == | ||
2002 | NOT_READY)) { | ||
1903 | switch (scsicmd->cmnd[0]) { | 2003 | switch (scsicmd->cmnd[0]) { |
1904 | case SERVICE_ACTION_IN: | 2004 | case SERVICE_ACTION_IN: |
1905 | if (!(dev->raw_io_interface) || | 2005 | if (!(dev->raw_io_interface) || |
@@ -2091,8 +2191,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2091 | scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); | 2191 | scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); |
2092 | /* Do not cache partition table for arrays */ | 2192 | /* Do not cache partition table for arrays */ |
2093 | scsicmd->device->removable = 1; | 2193 | scsicmd->device->removable = 1; |
2094 | 2194 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | |
2095 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2195 | SAM_STAT_GOOD; |
2096 | scsicmd->scsi_done(scsicmd); | 2196 | scsicmd->scsi_done(scsicmd); |
2097 | 2197 | ||
2098 | return 0; | 2198 | return 0; |
@@ -2187,15 +2287,32 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2187 | * These commands are all No-Ops | 2287 | * These commands are all No-Ops |
2188 | */ | 2288 | */ |
2189 | case TEST_UNIT_READY: | 2289 | case TEST_UNIT_READY: |
2290 | if (fsa_dev_ptr[cid].sense_data.sense_key == NOT_READY) { | ||
2291 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | | ||
2292 | SAM_STAT_CHECK_CONDITION; | ||
2293 | set_sense(&dev->fsa_dev[cid].sense_data, | ||
2294 | NOT_READY, SENCODE_BECOMING_READY, | ||
2295 | ASENCODE_BECOMING_READY, 0, 0); | ||
2296 | memcpy(scsicmd->sense_buffer, | ||
2297 | &dev->fsa_dev[cid].sense_data, | ||
2298 | min_t(size_t, | ||
2299 | sizeof(dev->fsa_dev[cid].sense_data), | ||
2300 | SCSI_SENSE_BUFFERSIZE)); | ||
2301 | scsicmd->scsi_done(scsicmd); | ||
2302 | return 0; | ||
2303 | } | ||
2304 | /* FALLTHRU */ | ||
2190 | case RESERVE: | 2305 | case RESERVE: |
2191 | case RELEASE: | 2306 | case RELEASE: |
2192 | case REZERO_UNIT: | 2307 | case REZERO_UNIT: |
2193 | case REASSIGN_BLOCKS: | 2308 | case REASSIGN_BLOCKS: |
2194 | case SEEK_10: | 2309 | case SEEK_10: |
2195 | case START_STOP: | ||
2196 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2310 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
2197 | scsicmd->scsi_done(scsicmd); | 2311 | scsicmd->scsi_done(scsicmd); |
2198 | return 0; | 2312 | return 0; |
2313 | |||
2314 | case START_STOP: | ||
2315 | return aac_start_stop(scsicmd); | ||
2199 | } | 2316 | } |
2200 | 2317 | ||
2201 | switch (scsicmd->cmnd[0]) | 2318 | switch (scsicmd->cmnd[0]) |