diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_ctl.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_ctl.c | 216 |
1 files changed, 144 insertions, 72 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 2d4f85c9d7a1..ba6ab170bdf0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -64,6 +64,9 @@ | |||
64 | static struct fasync_struct *async_queue; | 64 | static struct fasync_struct *async_queue; |
65 | static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); | 65 | static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); |
66 | 66 | ||
67 | static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, | ||
68 | u8 *issue_reset); | ||
69 | |||
67 | /** | 70 | /** |
68 | * enum block_state - blocking state | 71 | * enum block_state - blocking state |
69 | * @NON_BLOCKING: non blocking | 72 | * @NON_BLOCKING: non blocking |
@@ -378,10 +381,22 @@ _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) | |||
378 | void | 381 | void |
379 | mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | 382 | mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) |
380 | { | 383 | { |
384 | int i; | ||
385 | u8 issue_reset; | ||
386 | |||
381 | switch (reset_phase) { | 387 | switch (reset_phase) { |
382 | case MPT2_IOC_PRE_RESET: | 388 | case MPT2_IOC_PRE_RESET: |
383 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 389 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
384 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); | 390 | "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); |
391 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | ||
392 | if (!(ioc->diag_buffer_status[i] & | ||
393 | MPT2_DIAG_BUFFER_IS_REGISTERED)) | ||
394 | continue; | ||
395 | if ((ioc->diag_buffer_status[i] & | ||
396 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
397 | continue; | ||
398 | _ctl_send_release(ioc, i, &issue_reset); | ||
399 | } | ||
385 | break; | 400 | break; |
386 | case MPT2_IOC_AFTER_RESET: | 401 | case MPT2_IOC_AFTER_RESET: |
387 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 402 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
@@ -395,6 +410,17 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
395 | case MPT2_IOC_DONE_RESET: | 410 | case MPT2_IOC_DONE_RESET: |
396 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 411 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
397 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | 412 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); |
413 | |||
414 | for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { | ||
415 | if (!(ioc->diag_buffer_status[i] & | ||
416 | MPT2_DIAG_BUFFER_IS_REGISTERED)) | ||
417 | continue; | ||
418 | if ((ioc->diag_buffer_status[i] & | ||
419 | MPT2_DIAG_BUFFER_IS_RELEASED)) | ||
420 | continue; | ||
421 | ioc->diag_buffer_status[i] |= | ||
422 | MPT2_DIAG_BUFFER_IS_DIAG_RESET; | ||
423 | } | ||
398 | break; | 424 | break; |
399 | } | 425 | } |
400 | } | 426 | } |
@@ -714,8 +740,10 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
714 | 740 | ||
715 | if (tm_request->TaskType == | 741 | if (tm_request->TaskType == |
716 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | 742 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { |
717 | if (_ctl_do_task_abort(ioc, &karg, tm_request)) | 743 | if (_ctl_do_task_abort(ioc, &karg, tm_request)) { |
744 | mpt2sas_base_free_smid(ioc, smid); | ||
718 | goto out; | 745 | goto out; |
746 | } | ||
719 | } | 747 | } |
720 | 748 | ||
721 | mutex_lock(&ioc->tm_cmds.mutex); | 749 | mutex_lock(&ioc->tm_cmds.mutex); |
@@ -915,9 +943,9 @@ _ctl_getiocinfo(void __user *arg) | |||
915 | karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); | 943 | karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); |
916 | karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); | 944 | karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); |
917 | karg.firmware_version = ioc->facts.FWVersion.Word; | 945 | karg.firmware_version = ioc->facts.FWVersion.Word; |
918 | strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION, | 946 | strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME); |
919 | MPT2_IOCTL_VERSION_LENGTH); | 947 | strcat(karg.driver_version, "-"); |
920 | karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0'; | 948 | strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION); |
921 | karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); | 949 | karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); |
922 | 950 | ||
923 | if (copy_to_user(arg, &karg, sizeof(karg))) { | 951 | if (copy_to_user(arg, &karg, sizeof(karg))) { |
@@ -1551,81 +1579,38 @@ _ctl_diag_query(void __user *arg) | |||
1551 | } | 1579 | } |
1552 | 1580 | ||
1553 | /** | 1581 | /** |
1554 | * _ctl_diag_release - request to send Diag Release Message to firmware | 1582 | * _ctl_send_release - Diag Release Message |
1555 | * @arg - user space buffer containing ioctl content | 1583 | * @ioc: per adapter object |
1556 | * @state - NON_BLOCKING or BLOCKING | 1584 | * @buffer_type - specifies either TRACE or SNAPSHOT |
1585 | * @issue_reset - specifies whether host reset is required. | ||
1557 | * | 1586 | * |
1558 | * This allows ownership of the specified buffer to returned to the driver, | ||
1559 | * allowing an application to read the buffer without fear that firmware is | ||
1560 | * overwritting information in the buffer. | ||
1561 | */ | 1587 | */ |
1562 | static long | 1588 | static int |
1563 | _ctl_diag_release(void __user *arg, enum block_state state) | 1589 | _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) |
1564 | { | 1590 | { |
1565 | struct mpt2_diag_release karg; | ||
1566 | struct MPT2SAS_ADAPTER *ioc; | ||
1567 | void *request_data; | ||
1568 | int rc; | ||
1569 | Mpi2DiagReleaseRequest_t *mpi_request; | 1591 | Mpi2DiagReleaseRequest_t *mpi_request; |
1570 | Mpi2DiagReleaseReply_t *mpi_reply; | 1592 | Mpi2DiagReleaseReply_t *mpi_reply; |
1571 | u8 buffer_type; | ||
1572 | unsigned long timeleft; | ||
1573 | u16 smid; | 1593 | u16 smid; |
1574 | u16 ioc_status; | 1594 | u16 ioc_status; |
1575 | u8 issue_reset = 0; | 1595 | u32 ioc_state; |
1576 | 1596 | int rc; | |
1577 | if (copy_from_user(&karg, arg, sizeof(karg))) { | 1597 | unsigned long timeleft; |
1578 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
1579 | __FILE__, __LINE__, __func__); | ||
1580 | return -EFAULT; | ||
1581 | } | ||
1582 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | ||
1583 | return -ENODEV; | ||
1584 | 1598 | ||
1585 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 1599 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
1586 | __func__)); | 1600 | __func__)); |
1587 | 1601 | ||
1588 | buffer_type = karg.unique_id & 0x000000ff; | 1602 | rc = 0; |
1589 | if (!_ctl_diag_capability(ioc, buffer_type)) { | 1603 | *issue_reset = 0; |
1590 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
1591 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
1592 | return -EPERM; | ||
1593 | } | ||
1594 | |||
1595 | if ((ioc->diag_buffer_status[buffer_type] & | ||
1596 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
1597 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " | ||
1598 | "registered\n", ioc->name, __func__, buffer_type); | ||
1599 | return -EINVAL; | ||
1600 | } | ||
1601 | |||
1602 | if (karg.unique_id != ioc->unique_id[buffer_type]) { | ||
1603 | printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " | ||
1604 | "registered\n", ioc->name, __func__, karg.unique_id); | ||
1605 | return -EINVAL; | ||
1606 | } | ||
1607 | |||
1608 | if (ioc->diag_buffer_status[buffer_type] & | ||
1609 | MPT2_DIAG_BUFFER_IS_RELEASED) { | ||
1610 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " | ||
1611 | "is already released\n", ioc->name, __func__, | ||
1612 | buffer_type); | ||
1613 | return 0; | ||
1614 | } | ||
1615 | |||
1616 | request_data = ioc->diag_buffer[buffer_type]; | ||
1617 | 1604 | ||
1618 | if (!request_data) { | 1605 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); |
1619 | printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " | 1606 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { |
1620 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | 1607 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
1621 | return -ENOMEM; | 1608 | "skipping due to FAULT state\n", ioc->name, |
1609 | __func__)); | ||
1610 | rc = -EAGAIN; | ||
1611 | goto out; | ||
1622 | } | 1612 | } |
1623 | 1613 | ||
1624 | if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) | ||
1625 | return -EAGAIN; | ||
1626 | else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) | ||
1627 | return -ERESTARTSYS; | ||
1628 | |||
1629 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { | 1614 | if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { |
1630 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", | 1615 | printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", |
1631 | ioc->name, __func__); | 1616 | ioc->name, __func__); |
@@ -1641,7 +1626,6 @@ _ctl_diag_release(void __user *arg, enum block_state state) | |||
1641 | goto out; | 1626 | goto out; |
1642 | } | 1627 | } |
1643 | 1628 | ||
1644 | rc = 0; | ||
1645 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; | 1629 | ioc->ctl_cmds.status = MPT2_CMD_PENDING; |
1646 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); | 1630 | memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); |
1647 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 1631 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
@@ -1660,8 +1644,9 @@ _ctl_diag_release(void __user *arg, enum block_state state) | |||
1660 | _debug_dump_mf(mpi_request, | 1644 | _debug_dump_mf(mpi_request, |
1661 | sizeof(Mpi2DiagReleaseRequest_t)/4); | 1645 | sizeof(Mpi2DiagReleaseRequest_t)/4); |
1662 | if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) | 1646 | if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) |
1663 | issue_reset = 1; | 1647 | *issue_reset = 1; |
1664 | goto issue_host_reset; | 1648 | rc = -EFAULT; |
1649 | goto out; | ||
1665 | } | 1650 | } |
1666 | 1651 | ||
1667 | /* process the completed Reply Message Frame */ | 1652 | /* process the completed Reply Message Frame */ |
@@ -1687,14 +1672,101 @@ _ctl_diag_release(void __user *arg, enum block_state state) | |||
1687 | rc = -EFAULT; | 1672 | rc = -EFAULT; |
1688 | } | 1673 | } |
1689 | 1674 | ||
1690 | issue_host_reset: | 1675 | out: |
1676 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
1677 | return rc; | ||
1678 | } | ||
1679 | |||
1680 | /** | ||
1681 | * _ctl_diag_release - request to send Diag Release Message to firmware | ||
1682 | * @arg - user space buffer containing ioctl content | ||
1683 | * @state - NON_BLOCKING or BLOCKING | ||
1684 | * | ||
1685 | * This allows ownership of the specified buffer to returned to the driver, | ||
1686 | * allowing an application to read the buffer without fear that firmware is | ||
1687 | * overwritting information in the buffer. | ||
1688 | */ | ||
1689 | static long | ||
1690 | _ctl_diag_release(void __user *arg, enum block_state state) | ||
1691 | { | ||
1692 | struct mpt2_diag_release karg; | ||
1693 | struct MPT2SAS_ADAPTER *ioc; | ||
1694 | void *request_data; | ||
1695 | int rc; | ||
1696 | u8 buffer_type; | ||
1697 | u8 issue_reset = 0; | ||
1698 | |||
1699 | if (copy_from_user(&karg, arg, sizeof(karg))) { | ||
1700 | printk(KERN_ERR "failure at %s:%d/%s()!\n", | ||
1701 | __FILE__, __LINE__, __func__); | ||
1702 | return -EFAULT; | ||
1703 | } | ||
1704 | if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) | ||
1705 | return -ENODEV; | ||
1706 | |||
1707 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | ||
1708 | __func__)); | ||
1709 | |||
1710 | buffer_type = karg.unique_id & 0x000000ff; | ||
1711 | if (!_ctl_diag_capability(ioc, buffer_type)) { | ||
1712 | printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " | ||
1713 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
1714 | return -EPERM; | ||
1715 | } | ||
1716 | |||
1717 | if ((ioc->diag_buffer_status[buffer_type] & | ||
1718 | MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { | ||
1719 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " | ||
1720 | "registered\n", ioc->name, __func__, buffer_type); | ||
1721 | return -EINVAL; | ||
1722 | } | ||
1723 | |||
1724 | if (karg.unique_id != ioc->unique_id[buffer_type]) { | ||
1725 | printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " | ||
1726 | "registered\n", ioc->name, __func__, karg.unique_id); | ||
1727 | return -EINVAL; | ||
1728 | } | ||
1729 | |||
1730 | if (ioc->diag_buffer_status[buffer_type] & | ||
1731 | MPT2_DIAG_BUFFER_IS_RELEASED) { | ||
1732 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " | ||
1733 | "is already released\n", ioc->name, __func__, | ||
1734 | buffer_type); | ||
1735 | return 0; | ||
1736 | } | ||
1737 | |||
1738 | request_data = ioc->diag_buffer[buffer_type]; | ||
1739 | |||
1740 | if (!request_data) { | ||
1741 | printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " | ||
1742 | "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); | ||
1743 | return -ENOMEM; | ||
1744 | } | ||
1745 | |||
1746 | /* buffers were released by due to host reset */ | ||
1747 | if ((ioc->diag_buffer_status[buffer_type] & | ||
1748 | MPT2_DIAG_BUFFER_IS_DIAG_RESET)) { | ||
1749 | ioc->diag_buffer_status[buffer_type] |= | ||
1750 | MPT2_DIAG_BUFFER_IS_RELEASED; | ||
1751 | ioc->diag_buffer_status[buffer_type] &= | ||
1752 | ~MPT2_DIAG_BUFFER_IS_DIAG_RESET; | ||
1753 | printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " | ||
1754 | "was released due to host reset\n", ioc->name, __func__, | ||
1755 | buffer_type); | ||
1756 | return 0; | ||
1757 | } | ||
1758 | |||
1759 | if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) | ||
1760 | return -EAGAIN; | ||
1761 | else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) | ||
1762 | return -ERESTARTSYS; | ||
1763 | |||
1764 | rc = _ctl_send_release(ioc, buffer_type, &issue_reset); | ||
1765 | |||
1691 | if (issue_reset) | 1766 | if (issue_reset) |
1692 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1767 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, |
1693 | FORCE_BIG_HAMMER); | 1768 | FORCE_BIG_HAMMER); |
1694 | 1769 | ||
1695 | out: | ||
1696 | |||
1697 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | ||
1698 | mutex_unlock(&ioc->ctl_cmds.mutex); | 1770 | mutex_unlock(&ioc->ctl_cmds.mutex); |
1699 | return rc; | 1771 | return rc; |
1700 | } | 1772 | } |