diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 88e6eebc315..b830d61684d 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * for access to MPT (Message Passing Technology) firmware. | 3 | * for access to MPT (Message Passing Technology) firmware. |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c |
6 | * Copyright (C) 2007-2009 LSI Corporation | 6 | * Copyright (C) 2007-2010 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/sort.h> | 58 | #include <linux/sort.h> |
59 | #include <linux/io.h> | 59 | #include <linux/io.h> |
60 | #include <linux/time.h> | 60 | #include <linux/time.h> |
61 | #include <linux/aer.h> | ||
61 | 62 | ||
62 | #include "mpt2sas_base.h" | 63 | #include "mpt2sas_base.h" |
63 | 64 | ||
@@ -285,6 +286,9 @@ _base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, | |||
285 | request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION) | 286 | request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION) |
286 | return; | 287 | return; |
287 | 288 | ||
289 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
290 | return; | ||
291 | |||
288 | switch (ioc_status) { | 292 | switch (ioc_status) { |
289 | 293 | ||
290 | /**************************************************************************** | 294 | /**************************************************************************** |
@@ -517,8 +521,18 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc, | |||
517 | desc = "IR Operation Status"; | 521 | desc = "IR Operation Status"; |
518 | break; | 522 | break; |
519 | case MPI2_EVENT_SAS_DISCOVERY: | 523 | case MPI2_EVENT_SAS_DISCOVERY: |
520 | desc = "Discovery"; | 524 | { |
521 | break; | 525 | Mpi2EventDataSasDiscovery_t *event_data = |
526 | (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData; | ||
527 | printk(MPT2SAS_INFO_FMT "Discovery: (%s)", ioc->name, | ||
528 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? | ||
529 | "start" : "stop"); | ||
530 | if (event_data->DiscoveryStatus) | ||
531 | printk("discovery_status(0x%08x)", | ||
532 | le32_to_cpu(event_data->DiscoveryStatus)); | ||
533 | printk("\n"); | ||
534 | return; | ||
535 | } | ||
522 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: | 536 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: |
523 | desc = "SAS Broadcast Primitive"; | 537 | desc = "SAS Broadcast Primitive"; |
524 | break; | 538 | break; |
@@ -1243,6 +1257,9 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1243 | goto out_fail; | 1257 | goto out_fail; |
1244 | } | 1258 | } |
1245 | 1259 | ||
1260 | /* AER (Advanced Error Reporting) hooks */ | ||
1261 | pci_enable_pcie_error_reporting(pdev); | ||
1262 | |||
1246 | pci_set_master(pdev); | 1263 | pci_set_master(pdev); |
1247 | 1264 | ||
1248 | if (_base_config_dma_addressing(ioc, pdev) != 0) { | 1265 | if (_base_config_dma_addressing(ioc, pdev) != 0) { |
@@ -1253,7 +1270,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1253 | } | 1270 | } |
1254 | 1271 | ||
1255 | for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) { | 1272 | for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) { |
1256 | if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) { | 1273 | if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { |
1257 | if (pio_sz) | 1274 | if (pio_sz) |
1258 | continue; | 1275 | continue; |
1259 | pio_chip = (u64)pci_resource_start(pdev, i); | 1276 | pio_chip = (u64)pci_resource_start(pdev, i); |
@@ -1261,15 +1278,18 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1261 | } else { | 1278 | } else { |
1262 | if (memap_sz) | 1279 | if (memap_sz) |
1263 | continue; | 1280 | continue; |
1264 | ioc->chip_phys = pci_resource_start(pdev, i); | 1281 | /* verify memory resource is valid before using */ |
1265 | chip_phys = (u64)ioc->chip_phys; | 1282 | if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { |
1266 | memap_sz = pci_resource_len(pdev, i); | 1283 | ioc->chip_phys = pci_resource_start(pdev, i); |
1267 | ioc->chip = ioremap(ioc->chip_phys, memap_sz); | 1284 | chip_phys = (u64)ioc->chip_phys; |
1268 | if (ioc->chip == NULL) { | 1285 | memap_sz = pci_resource_len(pdev, i); |
1269 | printk(MPT2SAS_ERR_FMT "unable to map adapter " | 1286 | ioc->chip = ioremap(ioc->chip_phys, memap_sz); |
1270 | "memory!\n", ioc->name); | 1287 | if (ioc->chip == NULL) { |
1271 | r = -EINVAL; | 1288 | printk(MPT2SAS_ERR_FMT "unable to map " |
1272 | goto out_fail; | 1289 | "adapter memory!\n", ioc->name); |
1290 | r = -EINVAL; | ||
1291 | goto out_fail; | ||
1292 | } | ||
1273 | } | 1293 | } |
1274 | } | 1294 | } |
1275 | } | 1295 | } |
@@ -1295,6 +1315,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1295 | ioc->chip_phys = 0; | 1315 | ioc->chip_phys = 0; |
1296 | ioc->pci_irq = -1; | 1316 | ioc->pci_irq = -1; |
1297 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 1317 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
1318 | pci_disable_pcie_error_reporting(pdev); | ||
1298 | pci_disable_device(pdev); | 1319 | pci_disable_device(pdev); |
1299 | return r; | 1320 | return r; |
1300 | } | 1321 | } |
@@ -1898,7 +1919,10 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) | |||
1898 | ioc->config_page, ioc->config_page_dma); | 1919 | ioc->config_page, ioc->config_page_dma); |
1899 | } | 1920 | } |
1900 | 1921 | ||
1901 | kfree(ioc->scsi_lookup); | 1922 | if (ioc->scsi_lookup) { |
1923 | free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages); | ||
1924 | ioc->scsi_lookup = NULL; | ||
1925 | } | ||
1902 | kfree(ioc->hpr_lookup); | 1926 | kfree(ioc->hpr_lookup); |
1903 | kfree(ioc->internal_lookup); | 1927 | kfree(ioc->internal_lookup); |
1904 | } | 1928 | } |
@@ -2110,11 +2134,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
2110 | ioc->name, (unsigned long long) ioc->request_dma)); | 2134 | ioc->name, (unsigned long long) ioc->request_dma)); |
2111 | total_sz += sz; | 2135 | total_sz += sz; |
2112 | 2136 | ||
2113 | ioc->scsi_lookup = kcalloc(ioc->scsiio_depth, | 2137 | sz = ioc->scsiio_depth * sizeof(struct request_tracker); |
2114 | sizeof(struct request_tracker), GFP_KERNEL); | 2138 | ioc->scsi_lookup_pages = get_order(sz); |
2139 | ioc->scsi_lookup = (struct request_tracker *)__get_free_pages( | ||
2140 | GFP_KERNEL, ioc->scsi_lookup_pages); | ||
2115 | if (!ioc->scsi_lookup) { | 2141 | if (!ioc->scsi_lookup) { |
2116 | printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n", | 2142 | printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, " |
2117 | ioc->name); | 2143 | "sz(%d)\n", ioc->name, (int)sz); |
2118 | goto out; | 2144 | goto out; |
2119 | } | 2145 | } |
2120 | 2146 | ||
@@ -3006,8 +3032,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3006 | * since epoch ~ midnight January 1, 1970. | 3032 | * since epoch ~ midnight January 1, 1970. |
3007 | */ | 3033 | */ |
3008 | do_gettimeofday(¤t_time); | 3034 | do_gettimeofday(¤t_time); |
3009 | mpi_request.TimeStamp = (current_time.tv_sec * 1000) + | 3035 | mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 + |
3010 | (current_time.tv_usec >> 3); | 3036 | (current_time.tv_usec / 1000)); |
3011 | 3037 | ||
3012 | if (ioc->logging_level & MPT_DEBUG_INIT) { | 3038 | if (ioc->logging_level & MPT_DEBUG_INIT) { |
3013 | u32 *mfp; | 3039 | u32 *mfp; |
@@ -3179,7 +3205,7 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3179 | mpi_request->VP_ID = 0; | 3205 | mpi_request->VP_ID = 0; |
3180 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 3206 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
3181 | mpi_request->EventMasks[i] = | 3207 | mpi_request->EventMasks[i] = |
3182 | le32_to_cpu(ioc->event_masks[i]); | 3208 | cpu_to_le32(ioc->event_masks[i]); |
3183 | mpt2sas_base_put_smid_default(ioc, smid); | 3209 | mpt2sas_base_put_smid_default(ioc, smid); |
3184 | init_completion(&ioc->base_cmds.done); | 3210 | init_completion(&ioc->base_cmds.done); |
3185 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); | 3211 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); |
@@ -3516,7 +3542,9 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
3516 | __func__)); | 3542 | __func__)); |
3517 | 3543 | ||
3518 | _base_mask_interrupts(ioc); | 3544 | _base_mask_interrupts(ioc); |
3545 | ioc->shost_recovery = 1; | ||
3519 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 3546 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
3547 | ioc->shost_recovery = 0; | ||
3520 | if (ioc->pci_irq) { | 3548 | if (ioc->pci_irq) { |
3521 | synchronize_irq(pdev->irq); | 3549 | synchronize_irq(pdev->irq); |
3522 | free_irq(ioc->pci_irq, ioc); | 3550 | free_irq(ioc->pci_irq, ioc); |
@@ -3527,6 +3555,7 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
3527 | ioc->pci_irq = -1; | 3555 | ioc->pci_irq = -1; |
3528 | ioc->chip_phys = 0; | 3556 | ioc->chip_phys = 0; |
3529 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 3557 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
3558 | pci_disable_pcie_error_reporting(pdev); | ||
3530 | pci_disable_device(pdev); | 3559 | pci_disable_device(pdev); |
3531 | return; | 3560 | return; |
3532 | } | 3561 | } |
@@ -3560,8 +3589,10 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3560 | 3589 | ||
3561 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, | 3590 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, |
3562 | sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); | 3591 | sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); |
3563 | if (!ioc->pfacts) | 3592 | if (!ioc->pfacts) { |
3593 | r = -ENOMEM; | ||
3564 | goto out_free_resources; | 3594 | goto out_free_resources; |
3595 | } | ||
3565 | 3596 | ||
3566 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | 3597 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { |
3567 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | 3598 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); |
@@ -3607,6 +3638,15 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3607 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | 3638 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; |
3608 | mutex_init(&ioc->ctl_cmds.mutex); | 3639 | mutex_init(&ioc->ctl_cmds.mutex); |
3609 | 3640 | ||
3641 | if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || | ||
3642 | !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || | ||
3643 | !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) { | ||
3644 | r = -ENOMEM; | ||
3645 | goto out_free_resources; | ||
3646 | } | ||
3647 | |||
3648 | init_completion(&ioc->shost_recovery_done); | ||
3649 | |||
3610 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 3650 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
3611 | ioc->event_masks[i] = -1; | 3651 | ioc->event_masks[i] = -1; |
3612 | 3652 | ||
@@ -3639,6 +3679,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3639 | pci_set_drvdata(ioc->pdev, NULL); | 3679 | pci_set_drvdata(ioc->pdev, NULL); |
3640 | kfree(ioc->tm_cmds.reply); | 3680 | kfree(ioc->tm_cmds.reply); |
3641 | kfree(ioc->transport_cmds.reply); | 3681 | kfree(ioc->transport_cmds.reply); |
3682 | kfree(ioc->scsih_cmds.reply); | ||
3642 | kfree(ioc->config_cmds.reply); | 3683 | kfree(ioc->config_cmds.reply); |
3643 | kfree(ioc->base_cmds.reply); | 3684 | kfree(ioc->base_cmds.reply); |
3644 | kfree(ioc->ctl_cmds.reply); | 3685 | kfree(ioc->ctl_cmds.reply); |
@@ -3646,6 +3687,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3646 | ioc->ctl_cmds.reply = NULL; | 3687 | ioc->ctl_cmds.reply = NULL; |
3647 | ioc->base_cmds.reply = NULL; | 3688 | ioc->base_cmds.reply = NULL; |
3648 | ioc->tm_cmds.reply = NULL; | 3689 | ioc->tm_cmds.reply = NULL; |
3690 | ioc->scsih_cmds.reply = NULL; | ||
3649 | ioc->transport_cmds.reply = NULL; | 3691 | ioc->transport_cmds.reply = NULL; |
3650 | ioc->config_cmds.reply = NULL; | 3692 | ioc->config_cmds.reply = NULL; |
3651 | ioc->pfacts = NULL; | 3693 | ioc->pfacts = NULL; |
@@ -3675,6 +3717,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | |||
3675 | kfree(ioc->base_cmds.reply); | 3717 | kfree(ioc->base_cmds.reply); |
3676 | kfree(ioc->tm_cmds.reply); | 3718 | kfree(ioc->tm_cmds.reply); |
3677 | kfree(ioc->transport_cmds.reply); | 3719 | kfree(ioc->transport_cmds.reply); |
3720 | kfree(ioc->scsih_cmds.reply); | ||
3678 | kfree(ioc->config_cmds.reply); | 3721 | kfree(ioc->config_cmds.reply); |
3679 | } | 3722 | } |
3680 | 3723 | ||
@@ -3811,9 +3854,8 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3811 | 3854 | ||
3812 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3855 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); |
3813 | ioc->shost_recovery = 0; | 3856 | ioc->shost_recovery = 0; |
3857 | complete(&ioc->shost_recovery_done); | ||
3814 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 3858 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
3815 | 3859 | ||
3816 | if (!r) | ||
3817 | _base_reset_handler(ioc, MPT2_IOC_RUNNING); | ||
3818 | return r; | 3860 | return r; |
3819 | } | 3861 | } |