aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAsai Thambi S P <asamymuthupa@micron.com>2012-04-09 02:35:38 -0400
committerJens Axboe <axboe@kernel.dk>2012-04-09 02:35:38 -0400
commitf65872177d838a33e90cbae25625b9bec05134ca (patch)
treee4cc29b3395f8c989b5821f132b2fdb91e9931a7
parentdad40f16ff683a10f4f2bea55a0b9fd86d3db58e (diff)
mtip32xx: Add new sysfs entry 'status'
* Add support for detecting the following device status - write protect - over temp (thermal shutdown) * Add new sysfs entry 'status', possible values - online, write_protect, thermal_shutdown * Add new file 'sysfs-block-rssd' to document ABI (Reported-by: Greg Kroah-Hartman) Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--Documentation/ABI/testing/sysfs-block-rssd18
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c323
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h19
3 files changed, 331 insertions, 29 deletions
diff --git a/Documentation/ABI/testing/sysfs-block-rssd b/Documentation/ABI/testing/sysfs-block-rssd
new file mode 100644
index 000000000000..d535757799fe
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-block-rssd
@@ -0,0 +1,18 @@
1What: /sys/block/rssd*/registers
2Date: March 2012
3KernelVersion: 3.3
4Contact: Asai Thambi S P <asamymuthupa@micron.com>
5Description: This is a read-only file. Dumps below driver information and
6 hardware registers.
7 - S ACTive
8 - Command Issue
9 - Allocated
10 - Completed
11 - PORT IRQ STAT
12 - HOST IRQ STAT
13
14What: /sys/block/rssd*/status
15Date: April 2012
16KernelVersion: 3.4
17Contact: Asai Thambi S P <asamymuthupa@micron.com>
18Description: This is a read-only file. Indicates the status of the device.
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index aaa82453ae74..79fdb063f9c0 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -725,6 +725,10 @@ static void print_tags(struct driver_data *dd,
725 dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count); 725 dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count);
726} 726}
727 727
728static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
729 dma_addr_t buffer_dma, unsigned int sectors);
730static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
731 struct smart_attr *attrib);
728/* 732/*
729 * Handle an error. 733 * Handle an error.
730 * 734 *
@@ -735,12 +739,15 @@ static void print_tags(struct driver_data *dd,
735 */ 739 */
736static void mtip_handle_tfe(struct driver_data *dd) 740static void mtip_handle_tfe(struct driver_data *dd)
737{ 741{
738 int group, tag, bit, reissue; 742 int group, tag, bit, reissue, rv;
739 struct mtip_port *port; 743 struct mtip_port *port;
740 struct mtip_cmd *command; 744 struct mtip_cmd *cmd;
741 u32 completed; 745 u32 completed;
742 struct host_to_dev_fis *fis; 746 struct host_to_dev_fis *fis;
743 unsigned long tagaccum[SLOTBITS_IN_LONGS]; 747 unsigned long tagaccum[SLOTBITS_IN_LONGS];
748 unsigned char *buf;
749 char *fail_reason = NULL;
750 int fail_all_ncq_write = 0, fail_all_ncq_cmds = 0;
744 751
745 dev_warn(&dd->pdev->dev, "Taskfile error\n"); 752 dev_warn(&dd->pdev->dev, "Taskfile error\n");
746 753
@@ -772,13 +779,13 @@ static void mtip_handle_tfe(struct driver_data *dd)
772 if (tag == MTIP_TAG_INTERNAL) 779 if (tag == MTIP_TAG_INTERNAL)
773 continue; 780 continue;
774 781
775 command = &port->commands[tag]; 782 cmd = &port->commands[tag];
776 if (likely(command->comp_func)) { 783 if (likely(cmd->comp_func)) {
777 set_bit(tag, tagaccum); 784 set_bit(tag, tagaccum);
778 atomic_set(&port->commands[tag].active, 0); 785 atomic_set(&cmd->active, 0);
779 command->comp_func(port, 786 cmd->comp_func(port,
780 tag, 787 tag,
781 command->comp_data, 788 cmd->comp_data,
782 0); 789 0);
783 } else { 790 } else {
784 dev_err(&port->dd->pdev->dev, 791 dev_err(&port->dd->pdev->dev,
@@ -798,6 +805,38 @@ static void mtip_handle_tfe(struct driver_data *dd)
798 mdelay(20); 805 mdelay(20);
799 mtip_restart_port(port); 806 mtip_restart_port(port);
800 807
808 /* Trying to determine the cause of the error */
809 rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
810 dd->port->log_buf,
811 dd->port->log_buf_dma, 1);
812 if (rv) {
813 dev_warn(&dd->pdev->dev,
814 "Error in READ LOG EXT (10h) command\n");
815 /* non-critical error, don't fail the load */
816 } else {
817 buf = (unsigned char *)dd->port->log_buf;
818 if (buf[259] & 0x1) {
819 dev_info(&dd->pdev->dev,
820 "Write protect bit is set.\n");
821 set_bit(MTIP_DD_FLAG_WRITE_PROTECT_BIT, &dd->dd_flag);
822 fail_all_ncq_write = 1;
823 fail_reason = "write protect";
824 }
825 if (buf[288] == 0xF7) {
826 dev_info(&dd->pdev->dev,
827 "Exceeded Tmax, drive in thermal shutdown.\n");
828 set_bit(MTIP_DD_FLAG_OVER_TEMP_BIT, &dd->dd_flag);
829 fail_all_ncq_cmds = 1;
830 fail_reason = "thermal shutdown";
831 }
832 if (buf[288] == 0xBF) {
833 dev_info(&dd->pdev->dev,
834 "Drive indicates rebuild has failed.\n");
835 fail_all_ncq_cmds = 1;
836 fail_reason = "rebuild failed";
837 }
838 }
839
801 /* clear the tag accumulator */ 840 /* clear the tag accumulator */
802 memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); 841 memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
803 842
@@ -806,25 +845,44 @@ static void mtip_handle_tfe(struct driver_data *dd)
806 for (bit = 0; bit < 32; bit++) { 845 for (bit = 0; bit < 32; bit++) {
807 reissue = 1; 846 reissue = 1;
808 tag = (group << 5) + bit; 847 tag = (group << 5) + bit;
848 cmd = &port->commands[tag];
809 849
810 /* If the active bit is set re-issue the command */ 850 /* If the active bit is set re-issue the command */
811 if (atomic_read(&port->commands[tag].active) == 0) 851 if (atomic_read(&cmd->active) == 0)
812 continue; 852 continue;
813 853
814 fis = (struct host_to_dev_fis *) 854 fis = (struct host_to_dev_fis *)cmd->command;
815 port->commands[tag].command;
816 855
817 /* Should re-issue? */ 856 /* Should re-issue? */
818 if (tag == MTIP_TAG_INTERNAL || 857 if (tag == MTIP_TAG_INTERNAL ||
819 fis->command == ATA_CMD_SET_FEATURES) 858 fis->command == ATA_CMD_SET_FEATURES)
820 reissue = 0; 859 reissue = 0;
860 else {
861 if (fail_all_ncq_cmds ||
862 (fail_all_ncq_write &&
863 fis->command == ATA_CMD_FPDMA_WRITE)) {
864 dev_warn(&dd->pdev->dev,
865 " Fail: %s w/tag %d [%s].\n",
866 fis->command == ATA_CMD_FPDMA_WRITE ?
867 "write" : "read",
868 tag,
869 fail_reason != NULL ?
870 fail_reason : "unknown");
871 atomic_set(&cmd->active, 0);
872 if (cmd->comp_func) {
873 cmd->comp_func(port, tag,
874 cmd->comp_data,
875 -ENODATA);
876 }
877 continue;
878 }
879 }
821 880
822 /* 881 /*
823 * First check if this command has 882 * First check if this command has
824 * exceeded its retries. 883 * exceeded its retries.
825 */ 884 */
826 if (reissue && 885 if (reissue && (cmd->retries-- > 0)) {
827 (port->commands[tag].retries-- > 0)) {
828 886
829 set_bit(tag, tagaccum); 887 set_bit(tag, tagaccum);
830 888
@@ -837,13 +895,13 @@ static void mtip_handle_tfe(struct driver_data *dd)
837 /* Retire a command that will not be reissued */ 895 /* Retire a command that will not be reissued */
838 dev_warn(&port->dd->pdev->dev, 896 dev_warn(&port->dd->pdev->dev,
839 "retiring tag %d\n", tag); 897 "retiring tag %d\n", tag);
840 atomic_set(&port->commands[tag].active, 0); 898 atomic_set(&cmd->active, 0);
841 899
842 if (port->commands[tag].comp_func) 900 if (cmd->comp_func)
843 port->commands[tag].comp_func( 901 cmd->comp_func(
844 port, 902 port,
845 tag, 903 tag,
846 port->commands[tag].comp_data, 904 cmd->comp_data,
847 PORT_IRQ_TF_ERR); 905 PORT_IRQ_TF_ERR);
848 else 906 else
849 dev_warn(&port->dd->pdev->dev, 907 dev_warn(&port->dd->pdev->dev,
@@ -1374,6 +1432,7 @@ static int mtip_standby_immediate(struct mtip_port *port)
1374{ 1432{
1375 int rv; 1433 int rv;
1376 struct host_to_dev_fis fis; 1434 struct host_to_dev_fis fis;
1435 unsigned long start;
1377 1436
1378 /* Build the FIS. */ 1437 /* Build the FIS. */
1379 memset(&fis, 0, sizeof(struct host_to_dev_fis)); 1438 memset(&fis, 0, sizeof(struct host_to_dev_fis));
@@ -1381,15 +1440,150 @@ static int mtip_standby_immediate(struct mtip_port *port)
1381 fis.opts = 1 << 7; 1440 fis.opts = 1 << 7;
1382 fis.command = ATA_CMD_STANDBYNOW1; 1441 fis.command = ATA_CMD_STANDBYNOW1;
1383 1442
1384 /* Execute the command. Use a 15-second timeout for large drives. */ 1443 start = jiffies;
1385 rv = mtip_exec_internal_command(port, 1444 rv = mtip_exec_internal_command(port,
1386 &fis, 1445 &fis,
1387 5, 1446 5,
1388 0, 1447 0,
1389 0, 1448 0,
1390 0, 1449 0,
1391 GFP_KERNEL, 1450 GFP_ATOMIC,
1392 15000); 1451 15000);
1452 dbg_printk(MTIP_DRV_NAME "Time taken to complete standby cmd: %d ms\n",
1453 jiffies_to_msecs(jiffies - start));
1454 if (rv)
1455 dev_warn(&port->dd->pdev->dev,
1456 "STANDBY IMMEDIATE command failed.\n");
1457
1458 return rv;
1459}
1460
1461/*
1462 * Issue a READ LOG EXT command to the device.
1463 *
1464 * @port pointer to the port structure.
1465 * @page page number to fetch
1466 * @buffer pointer to buffer
1467 * @buffer_dma dma address corresponding to @buffer
1468 * @sectors page length to fetch, in sectors
1469 *
1470 * return value
1471 * @rv return value from mtip_exec_internal_command()
1472 */
1473static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
1474 dma_addr_t buffer_dma, unsigned int sectors)
1475{
1476 struct host_to_dev_fis fis;
1477
1478 memset(&fis, 0, sizeof(struct host_to_dev_fis));
1479 fis.type = 0x27;
1480 fis.opts = 1 << 7;
1481 fis.command = ATA_CMD_READ_LOG_EXT;
1482 fis.sect_count = sectors & 0xFF;
1483 fis.sect_cnt_ex = (sectors >> 8) & 0xFF;
1484 fis.lba_low = page;
1485 fis.lba_mid = 0;
1486 fis.device = ATA_DEVICE_OBS;
1487
1488 memset(buffer, 0, sectors * ATA_SECT_SIZE);
1489
1490 return mtip_exec_internal_command(port,
1491 &fis,
1492 5,
1493 buffer_dma,
1494 sectors * ATA_SECT_SIZE,
1495 0,
1496 GFP_ATOMIC,
1497 MTIP_INTERNAL_COMMAND_TIMEOUT_MS);
1498}
1499
1500/*
1501 * Issue a SMART READ DATA command to the device.
1502 *
1503 * @port pointer to the port structure.
1504 * @buffer pointer to buffer
1505 * @buffer_dma dma address corresponding to @buffer
1506 *
1507 * return value
1508 * @rv return value from mtip_exec_internal_command()
1509 */
1510static int mtip_get_smart_data(struct mtip_port *port, u8 *buffer,
1511 dma_addr_t buffer_dma)
1512{
1513 struct host_to_dev_fis fis;
1514
1515 memset(&fis, 0, sizeof(struct host_to_dev_fis));
1516 fis.type = 0x27;
1517 fis.opts = 1 << 7;
1518 fis.command = ATA_CMD_SMART;
1519 fis.features = 0xD0;
1520 fis.sect_count = 1;
1521 fis.lba_mid = 0x4F;
1522 fis.lba_hi = 0xC2;
1523 fis.device = ATA_DEVICE_OBS;
1524
1525 return mtip_exec_internal_command(port,
1526 &fis,
1527 5,
1528 buffer_dma,
1529 ATA_SECT_SIZE,
1530 0,
1531 GFP_ATOMIC,
1532 15000);
1533}
1534
1535/*
1536 * Get the value of a smart attribute
1537 *
1538 * @port pointer to the port structure
1539 * @id attribute number
1540 * @attrib pointer to return attrib information corresponding to @id
1541 *
1542 * return value
1543 * -EINVAL NULL buffer passed or unsupported attribute @id.
1544 * -EPERM Identify data not valid, SMART not supported or not enabled
1545 */
1546static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
1547 struct smart_attr *attrib)
1548{
1549 int rv, i;
1550 struct smart_attr *pattr;
1551
1552 if (!attrib)
1553 return -EINVAL;
1554
1555 if (!port->identify_valid) {
1556 dev_warn(&port->dd->pdev->dev, "IDENTIFY DATA not valid\n");
1557 return -EPERM;
1558 }
1559 if (!(port->identify[82] & 0x1)) {
1560 dev_warn(&port->dd->pdev->dev, "SMART not supported\n");
1561 return -EPERM;
1562 }
1563 if (!(port->identify[85] & 0x1)) {
1564 dev_warn(&port->dd->pdev->dev, "SMART not enabled\n");
1565 return -EPERM;
1566 }
1567
1568 memset(port->smart_buf, 0, ATA_SECT_SIZE);
1569 rv = mtip_get_smart_data(port, port->smart_buf, port->smart_buf_dma);
1570 if (rv) {
1571 dev_warn(&port->dd->pdev->dev, "Failed to ge SMART data\n");
1572 return rv;
1573 }
1574
1575 pattr = (struct smart_attr *)(port->smart_buf + 2);
1576 for (i = 0; i < 29; i++, pattr++)
1577 if (pattr->attr_id == id) {
1578 memcpy(attrib, pattr, sizeof(struct smart_attr));
1579 break;
1580 }
1581
1582 if (i == 29) {
1583 dev_warn(&port->dd->pdev->dev,
1584 "Query for invalid SMART attribute ID\n");
1585 rv = -EINVAL;
1586 }
1393 1587
1394 return rv; 1588 return rv;
1395} 1589}
@@ -2272,7 +2466,7 @@ static ssize_t mtip_hw_show_registers(struct device *dev,
2272 int size = 0; 2466 int size = 0;
2273 int n; 2467 int n;
2274 2468
2275 size += sprintf(&buf[size], "%s:\ns_active:\n", __func__); 2469 size += sprintf(&buf[size], "S ACTive:\n");
2276 2470
2277 for (n = 0; n < dd->slot_groups; n++) 2471 for (n = 0; n < dd->slot_groups; n++)
2278 size += sprintf(&buf[size], "0x%08x\n", 2472 size += sprintf(&buf[size], "0x%08x\n",
@@ -2296,20 +2490,39 @@ static ssize_t mtip_hw_show_registers(struct device *dev,
2296 group_allocated); 2490 group_allocated);
2297 } 2491 }
2298 2492
2299 size += sprintf(&buf[size], "completed:\n"); 2493 size += sprintf(&buf[size], "Completed:\n");
2300 2494
2301 for (n = 0; n < dd->slot_groups; n++) 2495 for (n = 0; n < dd->slot_groups; n++)
2302 size += sprintf(&buf[size], "0x%08x\n", 2496 size += sprintf(&buf[size], "0x%08x\n",
2303 readl(dd->port->completed[n])); 2497 readl(dd->port->completed[n]));
2304 2498
2305 size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n", 2499 size += sprintf(&buf[size], "PORT IRQ STAT : 0x%08x\n",
2306 readl(dd->port->mmio + PORT_IRQ_STAT)); 2500 readl(dd->port->mmio + PORT_IRQ_STAT));
2307 size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n", 2501 size += sprintf(&buf[size], "HOST IRQ STAT : 0x%08x\n",
2308 readl(dd->mmio + HOST_IRQ_STAT)); 2502 readl(dd->mmio + HOST_IRQ_STAT));
2309 2503
2310 return size; 2504 return size;
2311} 2505}
2506
2507static ssize_t mtip_hw_show_status(struct device *dev,
2508 struct device_attribute *attr,
2509 char *buf)
2510{
2511 struct driver_data *dd = dev_to_disk(dev)->private_data;
2512 int size = 0;
2513
2514 if (test_bit(MTIP_DD_FLAG_OVER_TEMP_BIT, &dd->dd_flag))
2515 size += sprintf(buf, "%s", "thermal_shutdown\n");
2516 else if (test_bit(MTIP_DD_FLAG_WRITE_PROTECT_BIT, &dd->dd_flag))
2517 size += sprintf(buf, "%s", "write_protect\n");
2518 else
2519 size += sprintf(buf, "%s", "online\n");
2520
2521 return size;
2522}
2523
2312static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL); 2524static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL);
2525static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
2313 2526
2314/* 2527/*
2315 * Create the sysfs related attributes. 2528 * Create the sysfs related attributes.
@@ -2328,7 +2541,10 @@ static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj)
2328 2541
2329 if (sysfs_create_file(kobj, &dev_attr_registers.attr)) 2542 if (sysfs_create_file(kobj, &dev_attr_registers.attr))
2330 dev_warn(&dd->pdev->dev, 2543 dev_warn(&dd->pdev->dev,
2331 "Error creating registers sysfs entry\n"); 2544 "Error creating 'registers' sysfs entry\n");
2545 if (sysfs_create_file(kobj, &dev_attr_status.attr))
2546 dev_warn(&dd->pdev->dev,
2547 "Error creating 'status' sysfs entry\n");
2332 return 0; 2548 return 0;
2333} 2549}
2334 2550
@@ -2348,6 +2564,7 @@ static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj)
2348 return -EINVAL; 2564 return -EINVAL;
2349 2565
2350 sysfs_remove_file(kobj, &dev_attr_registers.attr); 2566 sysfs_remove_file(kobj, &dev_attr_registers.attr);
2567 sysfs_remove_file(kobj, &dev_attr_status.attr);
2351 2568
2352 return 0; 2569 return 0;
2353} 2570}
@@ -2566,6 +2783,8 @@ static int mtip_hw_init(struct driver_data *dd)
2566 int rv; 2783 int rv;
2567 unsigned int num_command_slots; 2784 unsigned int num_command_slots;
2568 unsigned long timeout, timetaken; 2785 unsigned long timeout, timetaken;
2786 unsigned char *buf;
2787 struct smart_attr attr242;
2569 2788
2570 dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR]; 2789 dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
2571 2790
@@ -2600,7 +2819,7 @@ static int mtip_hw_init(struct driver_data *dd)
2600 /* Allocate memory for the command list. */ 2819 /* Allocate memory for the command list. */
2601 dd->port->command_list = 2820 dd->port->command_list =
2602 dmam_alloc_coherent(&dd->pdev->dev, 2821 dmam_alloc_coherent(&dd->pdev->dev,
2603 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), 2822 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
2604 &dd->port->command_list_dma, 2823 &dd->port->command_list_dma,
2605 GFP_KERNEL); 2824 GFP_KERNEL);
2606 if (!dd->port->command_list) { 2825 if (!dd->port->command_list) {
@@ -2613,7 +2832,7 @@ static int mtip_hw_init(struct driver_data *dd)
2613 /* Clear the memory we have allocated. */ 2832 /* Clear the memory we have allocated. */
2614 memset(dd->port->command_list, 2833 memset(dd->port->command_list,
2615 0, 2834 0,
2616 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2)); 2835 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4));
2617 2836
2618 /* Setup the addresse of the RX FIS. */ 2837 /* Setup the addresse of the RX FIS. */
2619 dd->port->rxfis = dd->port->command_list + HW_CMD_SLOT_SZ; 2838 dd->port->rxfis = dd->port->command_list + HW_CMD_SLOT_SZ;
@@ -2629,10 +2848,19 @@ static int mtip_hw_init(struct driver_data *dd)
2629 dd->port->identify_dma = dd->port->command_tbl_dma + 2848 dd->port->identify_dma = dd->port->command_tbl_dma +
2630 HW_CMD_TBL_AR_SZ; 2849 HW_CMD_TBL_AR_SZ;
2631 2850
2632 /* Setup the address of the sector buffer. */ 2851 /* Setup the address of the sector buffer - for some non-ncq cmds */
2633 dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE; 2852 dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE;
2634 dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE; 2853 dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE;
2635 2854
2855 /* Setup the address of the log buf - for read log command */
2856 dd->port->log_buf = (void *)dd->port->sector_buffer + ATA_SECT_SIZE;
2857 dd->port->log_buf_dma = dd->port->sector_buffer_dma + ATA_SECT_SIZE;
2858
2859 /* Setup the address of the smart buf - for smart read data command */
2860 dd->port->smart_buf = (void *)dd->port->log_buf + ATA_SECT_SIZE;
2861 dd->port->smart_buf_dma = dd->port->log_buf_dma + ATA_SECT_SIZE;
2862
2863
2636 /* Point the command headers at the command tables. */ 2864 /* Point the command headers at the command tables. */
2637 for (i = 0; i < num_command_slots; i++) { 2865 for (i = 0; i < num_command_slots; i++) {
2638 dd->port->commands[i].command_header = 2866 dd->port->commands[i].command_header =
@@ -2759,6 +2987,43 @@ static int mtip_hw_init(struct driver_data *dd)
2759 return MTIP_FTL_REBUILD_MAGIC; 2987 return MTIP_FTL_REBUILD_MAGIC;
2760 } 2988 }
2761 mtip_dump_identify(dd->port); 2989 mtip_dump_identify(dd->port);
2990
2991 /* check write protect, over temp and rebuild statuses */
2992 rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
2993 dd->port->log_buf,
2994 dd->port->log_buf_dma, 1);
2995 if (rv) {
2996 dev_warn(&dd->pdev->dev,
2997 "Error in READ LOG EXT (10h) command\n");
2998 /* non-critical error, don't fail the load */
2999 } else {
3000 buf = (unsigned char *)dd->port->log_buf;
3001 if (buf[259] & 0x1) {
3002 dev_info(&dd->pdev->dev,
3003 "Write protect bit is set.\n");
3004 set_bit(MTIP_DD_FLAG_WRITE_PROTECT_BIT, &dd->dd_flag);
3005 }
3006 if (buf[288] == 0xF7) {
3007 dev_info(&dd->pdev->dev,
3008 "Exceeded Tmax, drive in thermal shutdown.\n");
3009 set_bit(MTIP_DD_FLAG_OVER_TEMP_BIT, &dd->dd_flag);
3010 }
3011 if (buf[288] == 0xBF) {
3012 dev_info(&dd->pdev->dev,
3013 "Drive indicates rebuild has failed.\n");
3014 /* TODO */
3015 }
3016 }
3017
3018 /* get write protect progess */
3019 memset(&attr242, 0, sizeof(struct smart_attr));
3020 if (mtip_get_smart_attr(dd->port, 242, &attr242))
3021 dev_warn(&dd->pdev->dev,
3022 "Unable to check write protect progress\n");
3023 else
3024 dev_info(&dd->pdev->dev,
3025 "Write protect progress: %d%% (%d blocks)\n",
3026 attr242.cur, attr242.data);
2762 return rv; 3027 return rv;
2763 3028
2764out3: 3029out3:
@@ -2776,7 +3041,7 @@ out2:
2776 3041
2777 /* Free the command/command header memory. */ 3042 /* Free the command/command header memory. */
2778 dmam_free_coherent(&dd->pdev->dev, 3043 dmam_free_coherent(&dd->pdev->dev,
2779 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), 3044 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
2780 dd->port->command_list, 3045 dd->port->command_list,
2781 dd->port->command_list_dma); 3046 dd->port->command_list_dma);
2782out1: 3047out1:
@@ -2825,7 +3090,7 @@ static int mtip_hw_exit(struct driver_data *dd)
2825 3090
2826 /* Free the command/command header memory. */ 3091 /* Free the command/command header memory. */
2827 dmam_free_coherent(&dd->pdev->dev, 3092 dmam_free_coherent(&dd->pdev->dev,
2828 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), 3093 HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
2829 dd->port->command_list, 3094 dd->port->command_list,
2830 dd->port->command_list_dma); 3095 dd->port->command_list_dma);
2831 /* Free the memory allocated for the for structure. */ 3096 /* Free the memory allocated for the for structure. */
@@ -3378,7 +3643,7 @@ static int mtip_block_remove(struct driver_data *dd)
3378 kthread_stop(dd->mtip_svc_handler); 3643 kthread_stop(dd->mtip_svc_handler);
3379 } 3644 }
3380 3645
3381 /* Clean up the sysfs attributes managed by the protocol layer. */ 3646 /* Clean up the sysfs attributes, if created */
3382 if (test_bit(MTIP_DD_FLAG_INIT_DONE_BIT, &dd->dd_flag)) { 3647 if (test_bit(MTIP_DD_FLAG_INIT_DONE_BIT, &dd->dd_flag)) {
3383 kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); 3648 kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
3384 if (kobj) { 3649 if (kobj) {
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index f4e46cc81d55..ea5c7e7cb50d 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -127,6 +127,19 @@
127#define MTIP_DD_FLAG_CLEANUP_BIT 3 127#define MTIP_DD_FLAG_CLEANUP_BIT 3
128#define MTIP_DD_FLAG_INIT_DONE_BIT 4 128#define MTIP_DD_FLAG_INIT_DONE_BIT 4
129 129
130#define MTIP_DD_FLAG_WRITE_PROTECT_BIT 5
131#define MTIP_DD_FLAG_OVER_TEMP_BIT 6
132#define MTIP_DD_FLAG_REBUILD_FAILED_BIT 7
133
134__packed struct smart_attr{
135 u8 attr_id;
136 u16 flags;
137 u8 cur;
138 u8 worst;
139 u32 data;
140 u8 res[3];
141};
142
130/* Register Frame Information Structure (FIS), host to device. */ 143/* Register Frame Information Structure (FIS), host to device. */
131struct host_to_dev_fis { 144struct host_to_dev_fis {
132 /* 145 /*
@@ -351,6 +364,12 @@ struct mtip_port {
351 * when the command slot and all associated data structures 364 * when the command slot and all associated data structures
352 * are no longer needed. 365 * are no longer needed.
353 */ 366 */
367 u16 *log_buf;
368 dma_addr_t log_buf_dma;
369
370 u8 *smart_buf;
371 dma_addr_t smart_buf_dma;
372
354 unsigned long allocated[SLOTBITS_IN_LONGS]; 373 unsigned long allocated[SLOTBITS_IN_LONGS];
355 /* 374 /*
356 * used to queue commands when an internal command is in progress 375 * used to queue commands when an internal command is in progress