aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2009-04-21 17:42:13 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-04-27 11:54:04 -0400
commit99bb214b1b652c475bb3d79cede47ecb76b758fa (patch)
treee9e540c07496b8388c03ea8bf279a71089353200 /drivers
parent8901cbb45e2a6657adf0e6eea4276ef452dee011 (diff)
[SCSI] mpt2sas : release diagnotic buffers prior host reset
Diagnostic buffer support is already there in the driver. This support allows applications to pull ring buffers from controller firmware for debugging firmware related issues. What this patch does is sends reqeust to firmware to release the buffers prior to host reset. This will allow what ever debug info is there prior to reset to be dma'd to host memory. With out this fix, some of the debug data would been lost. Signed-off-by: Eric Moore <eric.moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-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 2dc38598c20..ba6ab170bdf 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 5bd7d4cfa81..4da11435533 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)