aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c206
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.h5
2 files changed, 141 insertions, 70 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 2dc38598c207..ba6ab170bdf0 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -64,6 +64,9 @@
64static struct fasync_struct *async_queue; 64static struct fasync_struct *async_queue;
65static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); 65static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
66 66
67static 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)
378void 381void
379mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) 382mpt2sas_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}
@@ -1553,81 +1579,38 @@ _ctl_diag_query(void __user *arg)
1553} 1579}
1554 1580
1555/** 1581/**
1556 * _ctl_diag_release - request to send Diag Release Message to firmware 1582 * _ctl_send_release - Diag Release Message
1557 * @arg - user space buffer containing ioctl content 1583 * @ioc: per adapter object
1558 * @state - NON_BLOCKING or BLOCKING 1584 * @buffer_type - specifies either TRACE or SNAPSHOT
1585 * @issue_reset - specifies whether host reset is required.
1559 * 1586 *
1560 * This allows ownership of the specified buffer to returned to the driver,
1561 * allowing an application to read the buffer without fear that firmware is
1562 * overwritting information in the buffer.
1563 */ 1587 */
1564static long 1588static int
1565_ctl_diag_release(void __user *arg, enum block_state state) 1589_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
1566{ 1590{
1567 struct mpt2_diag_release karg;
1568 struct MPT2SAS_ADAPTER *ioc;
1569 void *request_data;
1570 int rc;
1571 Mpi2DiagReleaseRequest_t *mpi_request; 1591 Mpi2DiagReleaseRequest_t *mpi_request;
1572 Mpi2DiagReleaseReply_t *mpi_reply; 1592 Mpi2DiagReleaseReply_t *mpi_reply;
1573 u8 buffer_type;
1574 unsigned long timeleft;
1575 u16 smid; 1593 u16 smid;
1576 u16 ioc_status; 1594 u16 ioc_status;
1577 u8 issue_reset = 0; 1595 u32 ioc_state;
1578 1596 int rc;
1579 if (copy_from_user(&karg, arg, sizeof(karg))) { 1597 unsigned long timeleft;
1580 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1581 __FILE__, __LINE__, __func__);
1582 return -EFAULT;
1583 }
1584 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1585 return -ENODEV;
1586 1598
1587 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, 1599 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1588 __func__)); 1600 __func__));
1589 1601
1590 buffer_type = karg.unique_id & 0x000000ff; 1602 rc = 0;
1591 if (!_ctl_diag_capability(ioc, buffer_type)) { 1603 *issue_reset = 0;
1592 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1593 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1594 return -EPERM;
1595 }
1596
1597 if ((ioc->diag_buffer_status[buffer_type] &
1598 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1599 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1600 "registered\n", ioc->name, __func__, buffer_type);
1601 return -EINVAL;
1602 }
1603
1604 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1605 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1606 "registered\n", ioc->name, __func__, karg.unique_id);
1607 return -EINVAL;
1608 }
1609
1610 if (ioc->diag_buffer_status[buffer_type] &
1611 MPT2_DIAG_BUFFER_IS_RELEASED) {
1612 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
1613 "is already released\n", ioc->name, __func__,
1614 buffer_type);
1615 return 0;
1616 }
1617
1618 request_data = ioc->diag_buffer[buffer_type];
1619 1604
1620 if (!request_data) { 1605 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1621 printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " 1606 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1622 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); 1607 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
1623 return -ENOMEM; 1608 "skipping due to FAULT state\n", ioc->name,
1609 __func__));
1610 rc = -EAGAIN;
1611 goto out;
1624 } 1612 }
1625 1613
1626 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1627 return -EAGAIN;
1628 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
1629 return -ERESTARTSYS;
1630
1631 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { 1614 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
1632 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", 1615 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
1633 ioc->name, __func__); 1616 ioc->name, __func__);
@@ -1643,7 +1626,6 @@ _ctl_diag_release(void __user *arg, enum block_state state)
1643 goto out; 1626 goto out;
1644 } 1627 }
1645 1628
1646 rc = 0;
1647 ioc->ctl_cmds.status = MPT2_CMD_PENDING; 1629 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
1648 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); 1630 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1649 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); 1631 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
@@ -1662,8 +1644,9 @@ _ctl_diag_release(void __user *arg, enum block_state state)
1662 _debug_dump_mf(mpi_request, 1644 _debug_dump_mf(mpi_request,
1663 sizeof(Mpi2DiagReleaseRequest_t)/4); 1645 sizeof(Mpi2DiagReleaseRequest_t)/4);
1664 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) 1646 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
1665 issue_reset = 1; 1647 *issue_reset = 1;
1666 goto issue_host_reset; 1648 rc = -EFAULT;
1649 goto out;
1667 } 1650 }
1668 1651
1669 /* process the completed Reply Message Frame */ 1652 /* process the completed Reply Message Frame */
@@ -1689,14 +1672,101 @@ _ctl_diag_release(void __user *arg, enum block_state state)
1689 rc = -EFAULT; 1672 rc = -EFAULT;
1690 } 1673 }
1691 1674
1692 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 */
1689static 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
1693 if (issue_reset) 1766 if (issue_reset)
1694 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, 1767 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1695 FORCE_BIG_HAMMER); 1768 FORCE_BIG_HAMMER);
1696 1769
1697 out:
1698
1699 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
1700 mutex_unlock(&ioc->ctl_cmds.mutex); 1770 mutex_unlock(&ioc->ctl_cmds.mutex);
1701 return rc; 1771 return rc;
1702} 1772}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
index 5bd7d4cfa819..4da11435533f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
@@ -295,8 +295,9 @@ struct mpt2_ioctl_btdh_mapping {
295 295
296 296
297/* status bits for ioc->diag_buffer_status */ 297/* status bits for ioc->diag_buffer_status */
298#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01) 298#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
299#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02) 299#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
300#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04)
300 301
301/* application flags for mpt2_diag_register, mpt2_diag_query */ 302/* application flags for mpt2_diag_register, mpt2_diag_query */
302#define MPT2_APP_FLAGS_APP_OWNED (0x0001) 303#define MPT2_APP_FLAGS_APP_OWNED (0x0001)