diff options
| author | James Bottomley <James.Bottomley@steeleye.com> | 2005-06-28 10:18:21 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:34:11 -0400 |
| commit | c9d297c543f379a27a34082070ed03a8ef846fc2 (patch) | |
| tree | 4dcc96b31a31a6e7fbc82de31346f395fe78cb0b | |
| parent | f189c5cb8ddde0c01838f2b3bc7650e86c097a14 (diff) | |
[SCSI] fix 3ware raid emulated commands
The 3ware emulated commands all expect they are executing in the
use_sg == 0 case, which isn't true either in the block layer rework or
an SG_IO ioctl.
Fix this by adding the correct kmapping of the first element in the sg
list.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
| -rw-r--r-- | drivers/scsi/3w-xxxx.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 973c51fb0fe2..ae9e0203e9de 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c | |||
| @@ -1499,22 +1499,43 @@ static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id) | |||
| 1499 | return 0; | 1499 | return 0; |
| 1500 | } /* End tw_scsiop_inquiry() */ | 1500 | } /* End tw_scsiop_inquiry() */ |
| 1501 | 1501 | ||
| 1502 | static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, | ||
| 1503 | void *data, unsigned int len) | ||
| 1504 | { | ||
| 1505 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; | ||
| 1506 | void *buf; | ||
| 1507 | unsigned int transfer_len; | ||
| 1508 | |||
| 1509 | if (cmd->use_sg) { | ||
| 1510 | struct scatterlist *sg = | ||
| 1511 | (struct scatterlist *)cmd->request_buffer; | ||
| 1512 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
| 1513 | transfer_len = min(sg->length, len); | ||
| 1514 | } else { | ||
| 1515 | buf = cmd->request_buffer; | ||
| 1516 | transfer_len = min(cmd->request_bufflen, len); | ||
| 1517 | } | ||
| 1518 | |||
| 1519 | memcpy(buf, data, transfer_len); | ||
| 1520 | |||
| 1521 | if (cmd->use_sg) { | ||
| 1522 | struct scatterlist *sg; | ||
| 1523 | |||
| 1524 | sg = (struct scatterlist *)cmd->request_buffer; | ||
| 1525 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
| 1526 | } | ||
| 1527 | } | ||
| 1528 | |||
| 1502 | /* This function is called by the isr to complete an inquiry command */ | 1529 | /* This function is called by the isr to complete an inquiry command */ |
| 1503 | static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) | 1530 | static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) |
| 1504 | { | 1531 | { |
| 1505 | unsigned char *is_unit_present; | 1532 | unsigned char *is_unit_present; |
| 1506 | unsigned char *request_buffer; | 1533 | unsigned char request_buffer[36]; |
| 1507 | TW_Param *param; | 1534 | TW_Param *param; |
| 1508 | 1535 | ||
| 1509 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); | 1536 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); |
| 1510 | 1537 | ||
| 1511 | /* Fill request buffer */ | 1538 | memset(request_buffer, 0, sizeof(request_buffer)); |
| 1512 | if (tw_dev->srb[request_id]->request_buffer == NULL) { | ||
| 1513 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n"); | ||
| 1514 | return 1; | ||
| 1515 | } | ||
| 1516 | request_buffer = tw_dev->srb[request_id]->request_buffer; | ||
| 1517 | memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); | ||
| 1518 | request_buffer[0] = TYPE_DISK; /* Peripheral device type */ | 1539 | request_buffer[0] = TYPE_DISK; /* Peripheral device type */ |
| 1519 | request_buffer[1] = 0; /* Device type modifier */ | 1540 | request_buffer[1] = 0; /* Device type modifier */ |
| 1520 | request_buffer[2] = 0; /* No ansi/iso compliance */ | 1541 | request_buffer[2] = 0; /* No ansi/iso compliance */ |
| @@ -1522,6 +1543,8 @@ static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_i | |||
| 1522 | memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ | 1543 | memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ |
| 1523 | sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); | 1544 | sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); |
| 1524 | memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); | 1545 | memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); |
| 1546 | tw_transfer_internal(tw_dev, request_id, request_buffer, | ||
| 1547 | sizeof(request_buffer)); | ||
| 1525 | 1548 | ||
| 1526 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; | 1549 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; |
| 1527 | if (param == NULL) { | 1550 | if (param == NULL) { |
| @@ -1612,7 +1635,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques | |||
| 1612 | { | 1635 | { |
| 1613 | TW_Param *param; | 1636 | TW_Param *param; |
| 1614 | unsigned char *flags; | 1637 | unsigned char *flags; |
| 1615 | unsigned char *request_buffer; | 1638 | unsigned char request_buffer[8]; |
| 1616 | 1639 | ||
| 1617 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); | 1640 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); |
| 1618 | 1641 | ||
| @@ -1622,8 +1645,7 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques | |||
| 1622 | return 1; | 1645 | return 1; |
| 1623 | } | 1646 | } |
| 1624 | flags = (char *)&(param->data[0]); | 1647 | flags = (char *)&(param->data[0]); |
| 1625 | request_buffer = tw_dev->srb[request_id]->buffer; | 1648 | memset(request_buffer, 0, sizeof(request_buffer)); |
| 1626 | memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); | ||
| 1627 | 1649 | ||
| 1628 | request_buffer[0] = 0xf; /* mode data length */ | 1650 | request_buffer[0] = 0xf; /* mode data length */ |
| 1629 | request_buffer[1] = 0; /* default medium type */ | 1651 | request_buffer[1] = 0; /* default medium type */ |
| @@ -1635,6 +1657,8 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques | |||
| 1635 | request_buffer[6] = 0x4; /* WCE on */ | 1657 | request_buffer[6] = 0x4; /* WCE on */ |
| 1636 | else | 1658 | else |
| 1637 | request_buffer[6] = 0x0; /* WCE off */ | 1659 | request_buffer[6] = 0x0; /* WCE off */ |
| 1660 | tw_transfer_internal(tw_dev, request_id, request_buffer, | ||
| 1661 | sizeof(request_buffer)); | ||
| 1638 | 1662 | ||
| 1639 | return 0; | 1663 | return 0; |
| 1640 | } /* End tw_scsiop_mode_sense_complete() */ | 1664 | } /* End tw_scsiop_mode_sense_complete() */ |
| @@ -1701,17 +1725,12 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req | |||
| 1701 | { | 1725 | { |
| 1702 | unsigned char *param_data; | 1726 | unsigned char *param_data; |
| 1703 | u32 capacity; | 1727 | u32 capacity; |
| 1704 | char *buff; | 1728 | char buff[8]; |
| 1705 | TW_Param *param; | 1729 | TW_Param *param; |
| 1706 | 1730 | ||
| 1707 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); | 1731 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); |
| 1708 | 1732 | ||
| 1709 | buff = tw_dev->srb[request_id]->request_buffer; | 1733 | memset(buff, 0, sizeof(buff)); |
| 1710 | if (buff == NULL) { | ||
| 1711 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n"); | ||
| 1712 | return 1; | ||
| 1713 | } | ||
| 1714 | memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); | ||
| 1715 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; | 1734 | param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; |
| 1716 | if (param == NULL) { | 1735 | if (param == NULL) { |
| 1717 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n"); | 1736 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n"); |
| @@ -1739,6 +1758,8 @@ static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int req | |||
| 1739 | buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; | 1758 | buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; |
| 1740 | buff[7] = TW_BLOCK_SIZE & 0xff; | 1759 | buff[7] = TW_BLOCK_SIZE & 0xff; |
| 1741 | 1760 | ||
| 1761 | tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff)); | ||
| 1762 | |||
| 1742 | return 0; | 1763 | return 0; |
| 1743 | } /* End tw_scsiop_read_capacity_complete() */ | 1764 | } /* End tw_scsiop_read_capacity_complete() */ |
| 1744 | 1765 | ||
