diff options
Diffstat (limited to 'drivers/message/fusion/mptctl.c')
| -rw-r--r-- | drivers/message/fusion/mptctl.c | 241 |
1 files changed, 200 insertions, 41 deletions
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index bdf709987982..9b64e07400da 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
| @@ -136,6 +136,12 @@ static void mptctl_free_tm_flags(MPT_ADAPTER *ioc); | |||
| 136 | */ | 136 | */ |
| 137 | static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); | 137 | static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); |
| 138 | 138 | ||
| 139 | /* | ||
| 140 | * Event Handler function | ||
| 141 | */ | ||
| 142 | static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | ||
| 143 | struct fasync_struct *async_queue=NULL; | ||
| 144 | |||
| 139 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 140 | /* | 146 | /* |
| 141 | * Scatter gather list (SGL) sizes and limits... | 147 | * Scatter gather list (SGL) sizes and limits... |
| @@ -385,18 +391,18 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) | |||
| 385 | } | 391 | } |
| 386 | 392 | ||
| 387 | /* Now wait for the command to complete */ | 393 | /* Now wait for the command to complete */ |
| 388 | ii = wait_event_interruptible_timeout(mptctl_wait, | 394 | ii = wait_event_timeout(mptctl_wait, |
| 389 | ioctl->wait_done == 1, | 395 | ioctl->wait_done == 1, |
| 390 | HZ*5 /* 5 second timeout */); | 396 | HZ*5 /* 5 second timeout */); |
| 391 | 397 | ||
| 392 | if(ii <=0 && (ioctl->wait_done != 1 )) { | 398 | if(ii <=0 && (ioctl->wait_done != 1 )) { |
| 399 | mpt_free_msg_frame(hd->ioc, mf); | ||
| 393 | ioctl->wait_done = 0; | 400 | ioctl->wait_done = 0; |
| 394 | retval = -1; /* return failure */ | 401 | retval = -1; /* return failure */ |
| 395 | } | 402 | } |
| 396 | 403 | ||
| 397 | mptctl_bus_reset_done: | 404 | mptctl_bus_reset_done: |
| 398 | 405 | ||
| 399 | mpt_free_msg_frame(hd->ioc, mf); | ||
| 400 | mptctl_free_tm_flags(ioctl->ioc); | 406 | mptctl_free_tm_flags(ioctl->ioc); |
| 401 | return retval; | 407 | return retval; |
| 402 | } | 408 | } |
| @@ -472,6 +478,69 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
| 472 | } | 478 | } |
| 473 | 479 | ||
| 474 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 480 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 481 | /* ASYNC Event Notification Support */ | ||
| 482 | static int | ||
| 483 | mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | ||
| 484 | { | ||
| 485 | u8 event; | ||
| 486 | |||
| 487 | event = le32_to_cpu(pEvReply->Event) & 0xFF; | ||
| 488 | |||
| 489 | dctlprintk(("%s() called\n", __FUNCTION__)); | ||
| 490 | if(async_queue == NULL) | ||
| 491 | return 1; | ||
| 492 | |||
| 493 | /* Raise SIGIO for persistent events. | ||
| 494 | * TODO - this define is not in MPI spec yet, | ||
| 495 | * but they plan to set it to 0x21 | ||
| 496 | */ | ||
| 497 | if (event == 0x21 ) { | ||
| 498 | ioc->aen_event_read_flag=1; | ||
| 499 | dctlprintk(("Raised SIGIO to application\n")); | ||
| 500 | devtprintk(("Raised SIGIO to application\n")); | ||
| 501 | kill_fasync(&async_queue, SIGIO, POLL_IN); | ||
| 502 | return 1; | ||
| 503 | } | ||
| 504 | |||
| 505 | /* This flag is set after SIGIO was raised, and | ||
| 506 | * remains set until the application has read | ||
| 507 | * the event log via ioctl=MPTEVENTREPORT | ||
| 508 | */ | ||
| 509 | if(ioc->aen_event_read_flag) | ||
| 510 | return 1; | ||
| 511 | |||
| 512 | /* Signal only for the events that are | ||
| 513 | * requested for by the application | ||
| 514 | */ | ||
| 515 | if (ioc->events && (ioc->eventTypes & ( 1 << event))) { | ||
| 516 | ioc->aen_event_read_flag=1; | ||
| 517 | dctlprintk(("Raised SIGIO to application\n")); | ||
| 518 | devtprintk(("Raised SIGIO to application\n")); | ||
| 519 | kill_fasync(&async_queue, SIGIO, POLL_IN); | ||
| 520 | } | ||
| 521 | return 1; | ||
| 522 | } | ||
| 523 | |||
| 524 | static int | ||
| 525 | mptctl_fasync(int fd, struct file *filep, int mode) | ||
| 526 | { | ||
| 527 | MPT_ADAPTER *ioc; | ||
| 528 | |||
| 529 | list_for_each_entry(ioc, &ioc_list, list) | ||
| 530 | ioc->aen_event_read_flag=0; | ||
| 531 | |||
| 532 | dctlprintk(("%s() called\n", __FUNCTION__)); | ||
| 533 | return fasync_helper(fd, filep, mode, &async_queue); | ||
| 534 | } | ||
| 535 | |||
| 536 | static int | ||
| 537 | mptctl_release(struct inode *inode, struct file *filep) | ||
| 538 | { | ||
| 539 | dctlprintk(("%s() called\n", __FUNCTION__)); | ||
| 540 | return fasync_helper(-1, filep, 0, &async_queue); | ||
| 541 | } | ||
| 542 | |||
| 543 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
| 475 | /* | 544 | /* |
| 476 | * MPT ioctl handler | 545 | * MPT ioctl handler |
| 477 | * cmd - specify the particular IOCTL command to be issued | 546 | * cmd - specify the particular IOCTL command to be issued |
| @@ -674,22 +743,23 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 674 | u16 iocstat; | 743 | u16 iocstat; |
| 675 | pFWDownloadReply_t ReplyMsg = NULL; | 744 | pFWDownloadReply_t ReplyMsg = NULL; |
| 676 | 745 | ||
| 677 | dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id)); | 746 | dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id)); |
| 678 | 747 | ||
| 679 | dctlprintk((KERN_INFO "DbG: kfwdl.bufp = %p\n", ufwbuf)); | 748 | dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf)); |
| 680 | dctlprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen)); | 749 | dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen)); |
| 681 | dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc)); | 750 | dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc)); |
| 682 | 751 | ||
| 683 | if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) { | 752 | if (mpt_verify_adapter(ioc, &iocp) < 0) { |
| 684 | dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n", | 753 | dctlprintk(("ioctl_fwdl - ioc%d not found!\n", |
| 685 | __FILE__, __LINE__, ioc)); | 754 | ioc)); |
| 686 | return -ENODEV; /* (-6) No such device or address */ | 755 | return -ENODEV; /* (-6) No such device or address */ |
| 687 | } | 756 | } else { |
| 688 | 757 | ||
| 689 | /* Valid device. Get a message frame and construct the FW download message. | 758 | /* Valid device. Get a message frame and construct the FW download message. |
| 690 | */ | 759 | */ |
| 691 | if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) | 760 | if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) |
| 692 | return -EAGAIN; | 761 | return -EAGAIN; |
| 762 | } | ||
| 693 | dlmsg = (FWDownload_t*) mf; | 763 | dlmsg = (FWDownload_t*) mf; |
| 694 | ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL; | 764 | ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL; |
| 695 | sgOut = (char *) (ptsge + 1); | 765 | sgOut = (char *) (ptsge + 1); |
| @@ -702,7 +772,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 702 | dlmsg->ChainOffset = 0; | 772 | dlmsg->ChainOffset = 0; |
| 703 | dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD; | 773 | dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD; |
| 704 | dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0; | 774 | dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0; |
| 705 | dlmsg->MsgFlags = 0; | 775 | if (iocp->facts.MsgVersion >= MPI_VERSION_01_05) |
| 776 | dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT; | ||
| 777 | else | ||
| 778 | dlmsg->MsgFlags = 0; | ||
| 779 | |||
| 706 | 780 | ||
| 707 | /* Set up the Transaction SGE. | 781 | /* Set up the Transaction SGE. |
| 708 | */ | 782 | */ |
| @@ -754,7 +828,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 754 | goto fwdl_out; | 828 | goto fwdl_out; |
| 755 | } | 829 | } |
| 756 | 830 | ||
| 757 | dctlprintk((KERN_INFO "DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags)); | 831 | dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags)); |
| 758 | 832 | ||
| 759 | /* | 833 | /* |
| 760 | * Parse SG list, copying sgl itself, | 834 | * Parse SG list, copying sgl itself, |
| @@ -803,11 +877,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) | |||
| 803 | /* | 877 | /* |
| 804 | * Finally, perform firmware download. | 878 | * Finally, perform firmware download. |
| 805 | */ | 879 | */ |
| 806 | iocp->ioctl->wait_done = 0; | 880 | ReplyMsg = NULL; |
| 807 | mpt_put_msg_frame(mptctl_id, iocp, mf); | 881 | mpt_put_msg_frame(mptctl_id, iocp, mf); |
| 808 | 882 | ||
| 809 | /* Now wait for the command to complete */ | 883 | /* Now wait for the command to complete */ |
| 810 | ret = wait_event_interruptible_timeout(mptctl_wait, | 884 | ret = wait_event_timeout(mptctl_wait, |
| 811 | iocp->ioctl->wait_done == 1, | 885 | iocp->ioctl->wait_done == 1, |
| 812 | HZ*60); | 886 | HZ*60); |
| 813 | 887 | ||
| @@ -1145,7 +1219,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) | |||
| 1145 | /* Fill in the data and return the structure to the calling | 1219 | /* Fill in the data and return the structure to the calling |
| 1146 | * program | 1220 | * program |
| 1147 | */ | 1221 | */ |
| 1148 | if (ioc->bus_type == FC) | 1222 | if (ioc->bus_type == SAS) |
| 1223 | karg->adapterType = MPT_IOCTL_INTERFACE_SAS; | ||
| 1224 | else if (ioc->bus_type == FC) | ||
| 1149 | karg->adapterType = MPT_IOCTL_INTERFACE_FC; | 1225 | karg->adapterType = MPT_IOCTL_INTERFACE_FC; |
| 1150 | else | 1226 | else |
| 1151 | karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; | 1227 | karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; |
| @@ -1170,12 +1246,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) | |||
| 1170 | karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); | 1246 | karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); |
| 1171 | karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); | 1247 | karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); |
| 1172 | } else if (cim_rev == 2) { | 1248 | } else if (cim_rev == 2) { |
| 1173 | /* Get the PCI bus, device, function and segment ID numbers | 1249 | /* Get the PCI bus, device, function and segment ID numbers |
| 1174 | for the IOC */ | 1250 | for the IOC */ |
| 1175 | karg->pciInfo.u.bits.busNumber = pdev->bus->number; | 1251 | karg->pciInfo.u.bits.busNumber = pdev->bus->number; |
| 1176 | karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); | 1252 | karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); |
| 1177 | karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); | 1253 | karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); |
| 1178 | karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); | ||
| 1179 | karg->pciInfo.segmentID = pci_domain_nr(pdev->bus); | 1254 | karg->pciInfo.segmentID = pci_domain_nr(pdev->bus); |
| 1180 | } | 1255 | } |
| 1181 | 1256 | ||
| @@ -1500,7 +1575,7 @@ mptctl_eventquery (unsigned long arg) | |||
| 1500 | return -ENODEV; | 1575 | return -ENODEV; |
| 1501 | } | 1576 | } |
| 1502 | 1577 | ||
| 1503 | karg.eventEntries = ioc->eventLogSize; | 1578 | karg.eventEntries = MPTCTL_EVENT_LOG_SIZE; |
| 1504 | karg.eventTypes = ioc->eventTypes; | 1579 | karg.eventTypes = ioc->eventTypes; |
| 1505 | 1580 | ||
| 1506 | /* Copy the data from kernel memory to user memory | 1581 | /* Copy the data from kernel memory to user memory |
| @@ -1550,7 +1625,6 @@ mptctl_eventenable (unsigned long arg) | |||
| 1550 | memset(ioc->events, 0, sz); | 1625 | memset(ioc->events, 0, sz); |
| 1551 | ioc->alloc_total += sz; | 1626 | ioc->alloc_total += sz; |
| 1552 | 1627 | ||
| 1553 | ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE; | ||
| 1554 | ioc->eventContext = 0; | 1628 | ioc->eventContext = 0; |
| 1555 | } | 1629 | } |
| 1556 | 1630 | ||
| @@ -1590,7 +1664,7 @@ mptctl_eventreport (unsigned long arg) | |||
| 1590 | maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS); | 1664 | maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS); |
| 1591 | 1665 | ||
| 1592 | 1666 | ||
| 1593 | max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents; | 1667 | max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents; |
| 1594 | 1668 | ||
| 1595 | /* If fewer than 1 event is requested, there must have | 1669 | /* If fewer than 1 event is requested, there must have |
| 1596 | * been some type of error. | 1670 | * been some type of error. |
| @@ -1598,6 +1672,9 @@ mptctl_eventreport (unsigned long arg) | |||
| 1598 | if ((max < 1) || !ioc->events) | 1672 | if ((max < 1) || !ioc->events) |
| 1599 | return -ENODATA; | 1673 | return -ENODATA; |
| 1600 | 1674 | ||
| 1675 | /* reset this flag so SIGIO can restart */ | ||
| 1676 | ioc->aen_event_read_flag=0; | ||
| 1677 | |||
| 1601 | /* Copy the data from kernel memory to user memory | 1678 | /* Copy the data from kernel memory to user memory |
| 1602 | */ | 1679 | */ |
| 1603 | numBytes = max * sizeof(MPT_IOCTL_EVENTS); | 1680 | numBytes = max * sizeof(MPT_IOCTL_EVENTS); |
| @@ -1817,6 +1894,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1817 | case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: | 1894 | case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: |
| 1818 | case MPI_FUNCTION_FW_DOWNLOAD: | 1895 | case MPI_FUNCTION_FW_DOWNLOAD: |
| 1819 | case MPI_FUNCTION_FC_PRIMITIVE_SEND: | 1896 | case MPI_FUNCTION_FC_PRIMITIVE_SEND: |
| 1897 | case MPI_FUNCTION_TOOLBOX: | ||
| 1898 | case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: | ||
| 1820 | break; | 1899 | break; |
| 1821 | 1900 | ||
| 1822 | case MPI_FUNCTION_SCSI_IO_REQUEST: | 1901 | case MPI_FUNCTION_SCSI_IO_REQUEST: |
| @@ -1837,7 +1916,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1837 | goto done_free_mem; | 1916 | goto done_free_mem; |
| 1838 | } | 1917 | } |
| 1839 | 1918 | ||
| 1840 | pScsiReq->MsgFlags = mpt_msg_flags(); | 1919 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; |
| 1920 | pScsiReq->MsgFlags |= mpt_msg_flags(); | ||
| 1921 | |||
| 1841 | 1922 | ||
| 1842 | /* verify that app has not requested | 1923 | /* verify that app has not requested |
| 1843 | * more sense data than driver | 1924 | * more sense data than driver |
| @@ -1888,6 +1969,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1888 | } | 1969 | } |
| 1889 | break; | 1970 | break; |
| 1890 | 1971 | ||
| 1972 | case MPI_FUNCTION_SMP_PASSTHROUGH: | ||
| 1973 | /* Check mf->PassthruFlags to determine if | ||
| 1974 | * transfer is ImmediateMode or not. | ||
| 1975 | * Immediate mode returns data in the ReplyFrame. | ||
| 1976 | * Else, we are sending request and response data | ||
| 1977 | * in two SGLs at the end of the mf. | ||
| 1978 | */ | ||
| 1979 | break; | ||
| 1980 | |||
| 1981 | case MPI_FUNCTION_SATA_PASSTHROUGH: | ||
| 1982 | if (!ioc->sh) { | ||
| 1983 | printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " | ||
| 1984 | "SCSI driver is not loaded. \n", | ||
| 1985 | __FILE__, __LINE__); | ||
| 1986 | rc = -EFAULT; | ||
| 1987 | goto done_free_mem; | ||
| 1988 | } | ||
| 1989 | break; | ||
| 1990 | |||
| 1891 | case MPI_FUNCTION_RAID_ACTION: | 1991 | case MPI_FUNCTION_RAID_ACTION: |
| 1892 | /* Just add a SGE | 1992 | /* Just add a SGE |
| 1893 | */ | 1993 | */ |
| @@ -1900,7 +2000,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 1900 | int scsidir = MPI_SCSIIO_CONTROL_READ; | 2000 | int scsidir = MPI_SCSIIO_CONTROL_READ; |
| 1901 | int dataSize; | 2001 | int dataSize; |
| 1902 | 2002 | ||
| 1903 | pScsiReq->MsgFlags = mpt_msg_flags(); | 2003 | pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; |
| 2004 | pScsiReq->MsgFlags |= mpt_msg_flags(); | ||
| 2005 | |||
| 1904 | 2006 | ||
| 1905 | /* verify that app has not requested | 2007 | /* verify that app has not requested |
| 1906 | * more sense data than driver | 2008 | * more sense data than driver |
| @@ -2130,7 +2232,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) | |||
| 2130 | 2232 | ||
| 2131 | /* Now wait for the command to complete */ | 2233 | /* Now wait for the command to complete */ |
| 2132 | timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; | 2234 | timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; |
| 2133 | timeout = wait_event_interruptible_timeout(mptctl_wait, | 2235 | timeout = wait_event_timeout(mptctl_wait, |
| 2134 | ioc->ioctl->wait_done == 1, | 2236 | ioc->ioctl->wait_done == 1, |
| 2135 | HZ*timeout); | 2237 | HZ*timeout); |
| 2136 | 2238 | ||
| @@ -2246,13 +2348,16 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2246 | hp_host_info_t __user *uarg = (void __user *) arg; | 2348 | hp_host_info_t __user *uarg = (void __user *) arg; |
| 2247 | MPT_ADAPTER *ioc; | 2349 | MPT_ADAPTER *ioc; |
| 2248 | struct pci_dev *pdev; | 2350 | struct pci_dev *pdev; |
| 2249 | char *pbuf; | 2351 | char *pbuf=NULL; |
| 2250 | dma_addr_t buf_dma; | 2352 | dma_addr_t buf_dma; |
| 2251 | hp_host_info_t karg; | 2353 | hp_host_info_t karg; |
| 2252 | CONFIGPARMS cfg; | 2354 | CONFIGPARMS cfg; |
| 2253 | ConfigPageHeader_t hdr; | 2355 | ConfigPageHeader_t hdr; |
| 2254 | int iocnum; | 2356 | int iocnum; |
| 2255 | int rc, cim_rev; | 2357 | int rc, cim_rev; |
| 2358 | ToolboxIstwiReadWriteRequest_t *IstwiRWRequest; | ||
| 2359 | MPT_FRAME_HDR *mf = NULL; | ||
| 2360 | MPIHeader_t *mpi_hdr; | ||
| 2256 | 2361 | ||
| 2257 | dctlprintk((": mptctl_hp_hostinfo called.\n")); | 2362 | dctlprintk((": mptctl_hp_hostinfo called.\n")); |
| 2258 | /* Reset long to int. Should affect IA64 and SPARC only | 2363 | /* Reset long to int. Should affect IA64 and SPARC only |
| @@ -2370,7 +2475,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2370 | 2475 | ||
| 2371 | karg.base_io_addr = pci_resource_start(pdev, 0); | 2476 | karg.base_io_addr = pci_resource_start(pdev, 0); |
| 2372 | 2477 | ||
| 2373 | if (ioc->bus_type == FC) | 2478 | if ((ioc->bus_type == SAS) || (ioc->bus_type == FC)) |
| 2374 | karg.bus_phys_width = HP_BUS_WIDTH_UNK; | 2479 | karg.bus_phys_width = HP_BUS_WIDTH_UNK; |
| 2375 | else | 2480 | else |
| 2376 | karg.bus_phys_width = HP_BUS_WIDTH_16; | 2481 | karg.bus_phys_width = HP_BUS_WIDTH_16; |
| @@ -2388,20 +2493,67 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) | |||
| 2388 | } | 2493 | } |
| 2389 | } | 2494 | } |
| 2390 | 2495 | ||
| 2391 | cfg.pageAddr = 0; | 2496 | /* |
| 2392 | cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; | 2497 | * Gather ISTWI(Industry Standard Two Wire Interface) Data |
| 2393 | cfg.dir = MPI_TB_ISTWI_FLAGS_READ; | 2498 | */ |
| 2394 | cfg.timeout = 10; | 2499 | if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { |
| 2500 | dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", | ||
| 2501 | ioc->name,__FUNCTION__)); | ||
| 2502 | goto out; | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf; | ||
| 2506 | mpi_hdr = (MPIHeader_t *) mf; | ||
| 2507 | memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t)); | ||
| 2508 | IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX; | ||
| 2509 | IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; | ||
| 2510 | IstwiRWRequest->MsgContext = mpi_hdr->MsgContext; | ||
| 2511 | IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ; | ||
| 2512 | IstwiRWRequest->NumAddressBytes = 0x01; | ||
| 2513 | IstwiRWRequest->DataLength = cpu_to_le16(0x04); | ||
| 2514 | if (pdev->devfn & 1) | ||
| 2515 | IstwiRWRequest->DeviceAddr = 0xB2; | ||
| 2516 | else | ||
| 2517 | IstwiRWRequest->DeviceAddr = 0xB0; | ||
| 2518 | |||
| 2395 | pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); | 2519 | pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); |
| 2396 | if (pbuf) { | 2520 | if (!pbuf) |
| 2397 | cfg.physAddr = buf_dma; | 2521 | goto out; |
| 2398 | if ((mpt_toolbox(ioc, &cfg)) == 0) { | 2522 | mpt_add_sge((char *)&IstwiRWRequest->SGL, |
| 2399 | karg.rsvd = *(u32 *)pbuf; | 2523 | (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); |
| 2400 | } | 2524 | |
| 2401 | pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); | 2525 | ioc->ioctl->wait_done = 0; |
| 2402 | pbuf = NULL; | 2526 | mpt_put_msg_frame(mptctl_id, ioc, mf); |
| 2527 | |||
| 2528 | rc = wait_event_timeout(mptctl_wait, | ||
| 2529 | ioc->ioctl->wait_done == 1, | ||
| 2530 | HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); | ||
| 2531 | |||
| 2532 | if(rc <=0 && (ioc->ioctl->wait_done != 1 )) { | ||
| 2533 | /* | ||
| 2534 | * Now we need to reset the board | ||
| 2535 | */ | ||
| 2536 | mpt_free_msg_frame(ioc, mf); | ||
| 2537 | mptctl_timeout_expired(ioc->ioctl); | ||
| 2538 | goto out; | ||
| 2403 | } | 2539 | } |
| 2404 | 2540 | ||
| 2541 | /* | ||
| 2542 | *ISTWI Data Definition | ||
| 2543 | * pbuf[0] = FW_VERSION = 0x4 | ||
| 2544 | * pbuf[1] = Bay Count = 6 or 4 or 2, depending on | ||
| 2545 | * the config, you should be seeing one out of these three values | ||
| 2546 | * pbuf[2] = Drive Installed Map = bit pattern depend on which | ||
| 2547 | * bays have drives in them | ||
| 2548 | * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3) | ||
| 2549 | */ | ||
| 2550 | if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) | ||
| 2551 | karg.rsvd = *(u32 *)pbuf; | ||
| 2552 | |||
| 2553 | out: | ||
| 2554 | if (pbuf) | ||
| 2555 | pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); | ||
| 2556 | |||
| 2405 | /* Copy the data from kernel memory to user memory | 2557 | /* Copy the data from kernel memory to user memory |
| 2406 | */ | 2558 | */ |
| 2407 | if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) { | 2559 | if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) { |
| @@ -2459,7 +2611,7 @@ mptctl_hp_targetinfo(unsigned long arg) | |||
| 2459 | 2611 | ||
| 2460 | /* There is nothing to do for FCP parts. | 2612 | /* There is nothing to do for FCP parts. |
| 2461 | */ | 2613 | */ |
| 2462 | if (ioc->bus_type == FC) | 2614 | if ((ioc->bus_type == SAS) || (ioc->bus_type == FC)) |
| 2463 | return 0; | 2615 | return 0; |
| 2464 | 2616 | ||
| 2465 | if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) | 2617 | if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) |
| @@ -2569,6 +2721,8 @@ mptctl_hp_targetinfo(unsigned long arg) | |||
| 2569 | static struct file_operations mptctl_fops = { | 2721 | static struct file_operations mptctl_fops = { |
| 2570 | .owner = THIS_MODULE, | 2722 | .owner = THIS_MODULE, |
| 2571 | .llseek = no_llseek, | 2723 | .llseek = no_llseek, |
| 2724 | .release = mptctl_release, | ||
| 2725 | .fasync = mptctl_fasync, | ||
| 2572 | .unlocked_ioctl = mptctl_ioctl, | 2726 | .unlocked_ioctl = mptctl_ioctl, |
| 2573 | #ifdef CONFIG_COMPAT | 2727 | #ifdef CONFIG_COMPAT |
| 2574 | .compat_ioctl = compat_mpctl_ioctl, | 2728 | .compat_ioctl = compat_mpctl_ioctl, |
| @@ -2813,6 +2967,11 @@ static int __init mptctl_init(void) | |||
| 2813 | /* FIXME! */ | 2967 | /* FIXME! */ |
| 2814 | } | 2968 | } |
| 2815 | 2969 | ||
| 2970 | if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { | ||
| 2971 | devtprintk((KERN_INFO MYNAM | ||
| 2972 | ": Registered for IOC event notifications\n")); | ||
| 2973 | } | ||
| 2974 | |||
| 2816 | return 0; | 2975 | return 0; |
| 2817 | 2976 | ||
| 2818 | out_fail: | 2977 | out_fail: |
