diff options
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
| -rw-r--r-- | drivers/scsi/aacraid/aachba.c | 69 |
1 files changed, 27 insertions, 42 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index c05092fd3a9d..369fcf78f396 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
| @@ -205,7 +205,7 @@ MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health" | |||
| 205 | 205 | ||
| 206 | int aac_check_reset = 1; | 206 | int aac_check_reset = 1; |
| 207 | module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR); | 207 | module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR); |
| 208 | MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the" | 208 | MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the" |
| 209 | " adapter. a value of -1 forces the reset to adapters programmed to" | 209 | " adapter. a value of -1 forces the reset to adapters programmed to" |
| 210 | " ignore it."); | 210 | " ignore it."); |
| 211 | 211 | ||
| @@ -379,24 +379,6 @@ int aac_get_containers(struct aac_dev *dev) | |||
| 379 | return status; | 379 | return status; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len) | ||
| 383 | { | ||
| 384 | void *buf; | ||
| 385 | int transfer_len; | ||
| 386 | struct scatterlist *sg = scsi_sglist(scsicmd); | ||
| 387 | |||
| 388 | buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; | ||
| 389 | transfer_len = min(sg->length, len + offset); | ||
| 390 | |||
| 391 | transfer_len -= offset; | ||
| 392 | if (buf && transfer_len > 0) | ||
| 393 | memcpy(buf + offset, data, transfer_len); | ||
| 394 | |||
| 395 | flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset)); | ||
| 396 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
| 397 | |||
| 398 | } | ||
| 399 | |||
| 400 | static void get_container_name_callback(void *context, struct fib * fibptr) | 382 | static void get_container_name_callback(void *context, struct fib * fibptr) |
| 401 | { | 383 | { |
| 402 | struct aac_get_name_resp * get_name_reply; | 384 | struct aac_get_name_resp * get_name_reply; |
| @@ -419,14 +401,17 @@ static void get_container_name_callback(void *context, struct fib * fibptr) | |||
| 419 | while (*sp == ' ') | 401 | while (*sp == ' ') |
| 420 | ++sp; | 402 | ++sp; |
| 421 | if (*sp) { | 403 | if (*sp) { |
| 404 | struct inquiry_data inq; | ||
| 422 | char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)]; | 405 | char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)]; |
| 423 | int count = sizeof(d); | 406 | int count = sizeof(d); |
| 424 | char *dp = d; | 407 | char *dp = d; |
| 425 | do { | 408 | do { |
| 426 | *dp++ = (*sp) ? *sp++ : ' '; | 409 | *dp++ = (*sp) ? *sp++ : ' '; |
| 427 | } while (--count > 0); | 410 | } while (--count > 0); |
| 428 | aac_internal_transfer(scsicmd, d, | 411 | |
| 429 | offsetof(struct inquiry_data, inqd_pid), sizeof(d)); | 412 | scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq)); |
| 413 | memcpy(inq.inqd_pid, d, sizeof(d)); | ||
| 414 | scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq)); | ||
| 430 | } | 415 | } |
| 431 | } | 416 | } |
| 432 | 417 | ||
| @@ -811,7 +796,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) | |||
| 811 | sp[2] = 0; | 796 | sp[2] = 0; |
| 812 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", | 797 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", |
| 813 | le32_to_cpu(get_serial_reply->uid)); | 798 | le32_to_cpu(get_serial_reply->uid)); |
| 814 | aac_internal_transfer(scsicmd, sp, 0, sizeof(sp)); | 799 | scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp)); |
| 815 | } | 800 | } |
| 816 | 801 | ||
| 817 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 802 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
| @@ -1986,8 +1971,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 1986 | arr[4] = 0x0; | 1971 | arr[4] = 0x0; |
| 1987 | arr[5] = 0x80; | 1972 | arr[5] = 0x80; |
| 1988 | arr[1] = scsicmd->cmnd[2]; | 1973 | arr[1] = scsicmd->cmnd[2]; |
| 1989 | aac_internal_transfer(scsicmd, &inq_data, 0, | 1974 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
| 1990 | sizeof(inq_data)); | 1975 | sizeof(inq_data)); |
| 1991 | scsicmd->result = DID_OK << 16 | | 1976 | scsicmd->result = DID_OK << 16 | |
| 1992 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1977 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
| 1993 | } else if (scsicmd->cmnd[2] == 0x80) { | 1978 | } else if (scsicmd->cmnd[2] == 0x80) { |
| @@ -1995,8 +1980,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 1995 | arr[3] = setinqserial(dev, &arr[4], | 1980 | arr[3] = setinqserial(dev, &arr[4], |
| 1996 | scmd_id(scsicmd)); | 1981 | scmd_id(scsicmd)); |
| 1997 | arr[1] = scsicmd->cmnd[2]; | 1982 | arr[1] = scsicmd->cmnd[2]; |
| 1998 | aac_internal_transfer(scsicmd, &inq_data, 0, | 1983 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
| 1999 | sizeof(inq_data)); | 1984 | sizeof(inq_data)); |
| 2000 | return aac_get_container_serial(scsicmd); | 1985 | return aac_get_container_serial(scsicmd); |
| 2001 | } else { | 1986 | } else { |
| 2002 | /* vpd page not implemented */ | 1987 | /* vpd page not implemented */ |
| @@ -2027,7 +2012,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2027 | if (cid == host->this_id) { | 2012 | if (cid == host->this_id) { |
| 2028 | setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types)); | 2013 | setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types)); |
| 2029 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ | 2014 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ |
| 2030 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | 2015 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
| 2016 | sizeof(inq_data)); | ||
| 2031 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2017 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
| 2032 | scsicmd->scsi_done(scsicmd); | 2018 | scsicmd->scsi_done(scsicmd); |
| 2033 | return 0; | 2019 | return 0; |
| @@ -2036,7 +2022,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2036 | return -1; | 2022 | return -1; |
| 2037 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); | 2023 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); |
| 2038 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ | 2024 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ |
| 2039 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | 2025 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data)); |
| 2040 | return aac_get_container_name(scsicmd); | 2026 | return aac_get_container_name(scsicmd); |
| 2041 | } | 2027 | } |
| 2042 | case SERVICE_ACTION_IN: | 2028 | case SERVICE_ACTION_IN: |
| @@ -2047,6 +2033,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2047 | { | 2033 | { |
| 2048 | u64 capacity; | 2034 | u64 capacity; |
| 2049 | char cp[13]; | 2035 | char cp[13]; |
| 2036 | unsigned int alloc_len; | ||
| 2050 | 2037 | ||
| 2051 | dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); | 2038 | dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); |
| 2052 | capacity = fsa_dev_ptr[cid].size - 1; | 2039 | capacity = fsa_dev_ptr[cid].size - 1; |
| @@ -2063,18 +2050,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2063 | cp[10] = 2; | 2050 | cp[10] = 2; |
| 2064 | cp[11] = 0; | 2051 | cp[11] = 0; |
| 2065 | cp[12] = 0; | 2052 | cp[12] = 0; |
| 2066 | aac_internal_transfer(scsicmd, cp, 0, | ||
| 2067 | min_t(size_t, scsicmd->cmnd[13], sizeof(cp))); | ||
| 2068 | if (sizeof(cp) < scsicmd->cmnd[13]) { | ||
| 2069 | unsigned int len, offset = sizeof(cp); | ||
| 2070 | 2053 | ||
| 2071 | memset(cp, 0, offset); | 2054 | alloc_len = ((scsicmd->cmnd[10] << 24) |
| 2072 | do { | 2055 | + (scsicmd->cmnd[11] << 16) |
| 2073 | len = min_t(size_t, scsicmd->cmnd[13] - offset, | 2056 | + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]); |
| 2074 | sizeof(cp)); | 2057 | |
| 2075 | aac_internal_transfer(scsicmd, cp, offset, len); | 2058 | alloc_len = min_t(size_t, alloc_len, sizeof(cp)); |
| 2076 | } while ((offset += len) < scsicmd->cmnd[13]); | 2059 | scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len); |
| 2077 | } | 2060 | if (alloc_len < scsi_bufflen(scsicmd)) |
| 2061 | scsi_set_resid(scsicmd, | ||
| 2062 | scsi_bufflen(scsicmd) - alloc_len); | ||
| 2078 | 2063 | ||
| 2079 | /* Do not cache partition table for arrays */ | 2064 | /* Do not cache partition table for arrays */ |
| 2080 | scsicmd->device->removable = 1; | 2065 | scsicmd->device->removable = 1; |
| @@ -2104,7 +2089,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2104 | cp[5] = 0; | 2089 | cp[5] = 0; |
| 2105 | cp[6] = 2; | 2090 | cp[6] = 2; |
| 2106 | cp[7] = 0; | 2091 | cp[7] = 0; |
| 2107 | aac_internal_transfer(scsicmd, cp, 0, sizeof(cp)); | 2092 | scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); |
| 2108 | /* Do not cache partition table for arrays */ | 2093 | /* Do not cache partition table for arrays */ |
| 2109 | scsicmd->device->removable = 1; | 2094 | scsicmd->device->removable = 1; |
| 2110 | 2095 | ||
| @@ -2139,7 +2124,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2139 | if (mode_buf_length > scsicmd->cmnd[4]) | 2124 | if (mode_buf_length > scsicmd->cmnd[4]) |
| 2140 | mode_buf_length = scsicmd->cmnd[4]; | 2125 | mode_buf_length = scsicmd->cmnd[4]; |
| 2141 | } | 2126 | } |
| 2142 | aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length); | 2127 | scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length); |
| 2143 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2128 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
| 2144 | scsicmd->scsi_done(scsicmd); | 2129 | scsicmd->scsi_done(scsicmd); |
| 2145 | 2130 | ||
| @@ -2174,7 +2159,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
| 2174 | if (mode_buf_length > scsicmd->cmnd[8]) | 2159 | if (mode_buf_length > scsicmd->cmnd[8]) |
| 2175 | mode_buf_length = scsicmd->cmnd[8]; | 2160 | mode_buf_length = scsicmd->cmnd[8]; |
| 2176 | } | 2161 | } |
| 2177 | aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length); | 2162 | scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length); |
| 2178 | 2163 | ||
| 2179 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2164 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
| 2180 | scsicmd->scsi_done(scsicmd); | 2165 | scsicmd->scsi_done(scsicmd); |
