aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c212
1 files changed, 101 insertions, 111 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5abdce3ef70b..076dbcfa9471 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1398,6 +1398,106 @@ static int cciss_getluninfo(ctlr_info_t *h,
1398 return 0; 1398 return 0;
1399} 1399}
1400 1400
1401static int cciss_passthru(ctlr_info_t *h, void __user *argp)
1402{
1403 IOCTL_Command_struct iocommand;
1404 CommandList_struct *c;
1405 char *buff = NULL;
1406 u64bit temp64;
1407 DECLARE_COMPLETION_ONSTACK(wait);
1408
1409 if (!argp)
1410 return -EINVAL;
1411
1412 if (!capable(CAP_SYS_RAWIO))
1413 return -EPERM;
1414
1415 if (copy_from_user
1416 (&iocommand, argp, sizeof(IOCTL_Command_struct)))
1417 return -EFAULT;
1418 if ((iocommand.buf_size < 1) &&
1419 (iocommand.Request.Type.Direction != XFER_NONE)) {
1420 return -EINVAL;
1421 }
1422 if (iocommand.buf_size > 0) {
1423 buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
1424 if (buff == NULL)
1425 return -EFAULT;
1426 }
1427 if (iocommand.Request.Type.Direction == XFER_WRITE) {
1428 /* Copy the data into the buffer we created */
1429 if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
1430 kfree(buff);
1431 return -EFAULT;
1432 }
1433 } else {
1434 memset(buff, 0, iocommand.buf_size);
1435 }
1436 c = cmd_special_alloc(h);
1437 if (!c) {
1438 kfree(buff);
1439 return -ENOMEM;
1440 }
1441 /* Fill in the command type */
1442 c->cmd_type = CMD_IOCTL_PEND;
1443 /* Fill in Command Header */
1444 c->Header.ReplyQueue = 0; /* unused in simple mode */
1445 if (iocommand.buf_size > 0) { /* buffer to fill */
1446 c->Header.SGList = 1;
1447 c->Header.SGTotal = 1;
1448 } else { /* no buffers to fill */
1449 c->Header.SGList = 0;
1450 c->Header.SGTotal = 0;
1451 }
1452 c->Header.LUN = iocommand.LUN_info;
1453 /* use the kernel address the cmd block for tag */
1454 c->Header.Tag.lower = c->busaddr;
1455
1456 /* Fill in Request block */
1457 c->Request = iocommand.Request;
1458
1459 /* Fill in the scatter gather information */
1460 if (iocommand.buf_size > 0) {
1461 temp64.val = pci_map_single(h->pdev, buff,
1462 iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
1463 c->SG[0].Addr.lower = temp64.val32.lower;
1464 c->SG[0].Addr.upper = temp64.val32.upper;
1465 c->SG[0].Len = iocommand.buf_size;
1466 c->SG[0].Ext = 0; /* we are not chaining */
1467 }
1468 c->waiting = &wait;
1469
1470 enqueue_cmd_and_start_io(h, c);
1471 wait_for_completion(&wait);
1472
1473 /* unlock the buffers from DMA */
1474 temp64.val32.lower = c->SG[0].Addr.lower;
1475 temp64.val32.upper = c->SG[0].Addr.upper;
1476 pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
1477 PCI_DMA_BIDIRECTIONAL);
1478 check_ioctl_unit_attention(h, c);
1479
1480 /* Copy the error information out */
1481 iocommand.error_info = *(c->err_info);
1482 if (copy_to_user(argp, &iocommand, sizeof(IOCTL_Command_struct))) {
1483 kfree(buff);
1484 cmd_special_free(h, c);
1485 return -EFAULT;
1486 }
1487
1488 if (iocommand.Request.Type.Direction == XFER_READ) {
1489 /* Copy the data out of the buffer we created */
1490 if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
1491 kfree(buff);
1492 cmd_special_free(h, c);
1493 return -EFAULT;
1494 }
1495 }
1496 kfree(buff);
1497 cmd_special_free(h, c);
1498 return 0;
1499}
1500
1401static int cciss_ioctl(struct block_device *bdev, fmode_t mode, 1501static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1402 unsigned int cmd, unsigned long arg) 1502 unsigned int cmd, unsigned long arg)
1403{ 1503{
@@ -1433,117 +1533,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1433 case CCISS_GETLUNINFO: 1533 case CCISS_GETLUNINFO:
1434 return cciss_getluninfo(h, disk, argp); 1534 return cciss_getluninfo(h, disk, argp);
1435 case CCISS_PASSTHRU: 1535 case CCISS_PASSTHRU:
1436 { 1536 return cciss_passthru(h, argp);
1437 IOCTL_Command_struct iocommand;
1438 CommandList_struct *c;
1439 char *buff = NULL;
1440 u64bit temp64;
1441 DECLARE_COMPLETION_ONSTACK(wait);
1442
1443 if (!arg)
1444 return -EINVAL;
1445
1446 if (!capable(CAP_SYS_RAWIO))
1447 return -EPERM;
1448
1449 if (copy_from_user
1450 (&iocommand, argp, sizeof(IOCTL_Command_struct)))
1451 return -EFAULT;
1452 if ((iocommand.buf_size < 1) &&
1453 (iocommand.Request.Type.Direction != XFER_NONE)) {
1454 return -EINVAL;
1455 }
1456#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
1457 /* Check kmalloc limits */
1458 if (iocommand.buf_size > 128000)
1459 return -EINVAL;
1460#endif
1461 if (iocommand.buf_size > 0) {
1462 buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
1463 if (buff == NULL)
1464 return -EFAULT;
1465 }
1466 if (iocommand.Request.Type.Direction == XFER_WRITE) {
1467 /* Copy the data into the buffer we created */
1468 if (copy_from_user
1469 (buff, iocommand.buf, iocommand.buf_size)) {
1470 kfree(buff);
1471 return -EFAULT;
1472 }
1473 } else {
1474 memset(buff, 0, iocommand.buf_size);
1475 }
1476 c = cmd_special_alloc(h);
1477 if (!c) {
1478 kfree(buff);
1479 return -ENOMEM;
1480 }
1481 /* Fill in the command type */
1482 c->cmd_type = CMD_IOCTL_PEND;
1483 /* Fill in Command Header */
1484 c->Header.ReplyQueue = 0; /* unused in simple mode */
1485 if (iocommand.buf_size > 0) /* buffer to fill */
1486 {
1487 c->Header.SGList = 1;
1488 c->Header.SGTotal = 1;
1489 } else /* no buffers to fill */
1490 {
1491 c->Header.SGList = 0;
1492 c->Header.SGTotal = 0;
1493 }
1494 c->Header.LUN = iocommand.LUN_info;
1495 /* use the kernel address the cmd block for tag */
1496 c->Header.Tag.lower = c->busaddr;
1497
1498 /* Fill in Request block */
1499 c->Request = iocommand.Request;
1500
1501 /* Fill in the scatter gather information */
1502 if (iocommand.buf_size > 0) {
1503 temp64.val = pci_map_single(h->pdev, buff,
1504 iocommand.buf_size,
1505 PCI_DMA_BIDIRECTIONAL);
1506 c->SG[0].Addr.lower = temp64.val32.lower;
1507 c->SG[0].Addr.upper = temp64.val32.upper;
1508 c->SG[0].Len = iocommand.buf_size;
1509 c->SG[0].Ext = 0; /* we are not chaining */
1510 }
1511 c->waiting = &wait;
1512
1513 enqueue_cmd_and_start_io(h, c);
1514 wait_for_completion(&wait);
1515
1516 /* unlock the buffers from DMA */
1517 temp64.val32.lower = c->SG[0].Addr.lower;
1518 temp64.val32.upper = c->SG[0].Addr.upper;
1519 pci_unmap_single(h->pdev, (dma_addr_t) temp64.val,
1520 iocommand.buf_size,
1521 PCI_DMA_BIDIRECTIONAL);
1522
1523 check_ioctl_unit_attention(h, c);
1524
1525 /* Copy the error information out */
1526 iocommand.error_info = *(c->err_info);
1527 if (copy_to_user
1528 (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
1529 kfree(buff);
1530 cmd_special_free(h, c);
1531 return -EFAULT;
1532 }
1533
1534 if (iocommand.Request.Type.Direction == XFER_READ) {
1535 /* Copy the data out of the buffer we created */
1536 if (copy_to_user
1537 (iocommand.buf, buff, iocommand.buf_size)) {
1538 kfree(buff);
1539 cmd_special_free(h, c);
1540 return -EFAULT;
1541 }
1542 }
1543 kfree(buff);
1544 cmd_special_free(h, c);
1545 return 0;
1546 }
1547 case CCISS_BIG_PASSTHRU:{ 1537 case CCISS_BIG_PASSTHRU:{
1548 BIG_IOCTL_Command_struct *ioc; 1538 BIG_IOCTL_Command_struct *ioc;
1549 CommandList_struct *c; 1539 CommandList_struct *c;