diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/isci/host.c | 313 | ||||
-rw-r--r-- | drivers/scsi/isci/host.h | 71 | ||||
-rw-r--r-- | drivers/scsi/isci/init.c | 199 | ||||
-rw-r--r-- | drivers/scsi/isci/probe_roms.c | 12 | ||||
-rw-r--r-- | drivers/scsi/isci/probe_roms.h | 2 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 4 | ||||
-rw-r--r-- | drivers/scsi/isci/unsolicited_frame_control.c | 30 | ||||
-rw-r--r-- | drivers/scsi/isci/unsolicited_frame_control.h | 6 |
8 files changed, 277 insertions, 360 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index bbec1982d07f..0fe372f93289 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
@@ -1074,7 +1074,7 @@ static void sci_controller_completion_handler(struct isci_host *ihost) | |||
1074 | * @data: This parameter specifies the ISCI host object | 1074 | * @data: This parameter specifies the ISCI host object |
1075 | * | 1075 | * |
1076 | */ | 1076 | */ |
1077 | static void isci_host_completion_routine(unsigned long data) | 1077 | void isci_host_completion_routine(unsigned long data) |
1078 | { | 1078 | { |
1079 | struct isci_host *ihost = (struct isci_host *)data; | 1079 | struct isci_host *ihost = (struct isci_host *)data; |
1080 | struct list_head completed_request_list; | 1080 | struct list_head completed_request_list; |
@@ -1317,29 +1317,6 @@ static void __iomem *smu_base(struct isci_host *isci_host) | |||
1317 | return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; | 1317 | return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; |
1318 | } | 1318 | } |
1319 | 1319 | ||
1320 | static void isci_user_parameters_get(struct sci_user_parameters *u) | ||
1321 | { | ||
1322 | int i; | ||
1323 | |||
1324 | for (i = 0; i < SCI_MAX_PHYS; i++) { | ||
1325 | struct sci_phy_user_params *u_phy = &u->phys[i]; | ||
1326 | |||
1327 | u_phy->max_speed_generation = phy_gen; | ||
1328 | |||
1329 | /* we are not exporting these for now */ | ||
1330 | u_phy->align_insertion_frequency = 0x7f; | ||
1331 | u_phy->in_connection_align_insertion_frequency = 0xff; | ||
1332 | u_phy->notify_enable_spin_up_insertion_frequency = 0x33; | ||
1333 | } | ||
1334 | |||
1335 | u->stp_inactivity_timeout = stp_inactive_to; | ||
1336 | u->ssp_inactivity_timeout = ssp_inactive_to; | ||
1337 | u->stp_max_occupancy_timeout = stp_max_occ_to; | ||
1338 | u->ssp_max_occupancy_timeout = ssp_max_occ_to; | ||
1339 | u->no_outbound_task_timeout = no_outbound_task_to; | ||
1340 | u->max_concurr_spinup = max_concurr_spinup; | ||
1341 | } | ||
1342 | |||
1343 | static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm) | 1320 | static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm) |
1344 | { | 1321 | { |
1345 | struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); | 1322 | struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); |
@@ -1648,55 +1625,6 @@ static const struct sci_base_state sci_controller_state_table[] = { | |||
1648 | [SCIC_FAILED] = {} | 1625 | [SCIC_FAILED] = {} |
1649 | }; | 1626 | }; |
1650 | 1627 | ||
1651 | static void sci_controller_set_default_config_parameters(struct isci_host *ihost) | ||
1652 | { | ||
1653 | /* these defaults are overridden by the platform / firmware */ | ||
1654 | u16 index; | ||
1655 | |||
1656 | /* Default to APC mode. */ | ||
1657 | ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; | ||
1658 | |||
1659 | /* Default to APC mode. */ | ||
1660 | ihost->oem_parameters.controller.max_concurr_spin_up = 1; | ||
1661 | |||
1662 | /* Default to no SSC operation. */ | ||
1663 | ihost->oem_parameters.controller.do_enable_ssc = false; | ||
1664 | |||
1665 | /* Default to short cables on all phys. */ | ||
1666 | ihost->oem_parameters.controller.cable_selection_mask = 0; | ||
1667 | |||
1668 | /* Initialize all of the port parameter information to narrow ports. */ | ||
1669 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
1670 | ihost->oem_parameters.ports[index].phy_mask = 0; | ||
1671 | } | ||
1672 | |||
1673 | /* Initialize all of the phy parameter information. */ | ||
1674 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
1675 | /* Default to 3G (i.e. Gen 2). */ | ||
1676 | ihost->user_parameters.phys[index].max_speed_generation = | ||
1677 | SCIC_SDS_PARM_GEN2_SPEED; | ||
1678 | |||
1679 | /* the frequencies cannot be 0 */ | ||
1680 | ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f; | ||
1681 | ihost->user_parameters.phys[index].in_connection_align_insertion_frequency = 0xff; | ||
1682 | ihost->user_parameters.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; | ||
1683 | |||
1684 | /* | ||
1685 | * Previous Vitesse based expanders had a arbitration issue that | ||
1686 | * is worked around by having the upper 32-bits of SAS address | ||
1687 | * with a value greater then the Vitesse company identifier. | ||
1688 | * Hence, usage of 0x5FCFFFFF. */ | ||
1689 | ihost->oem_parameters.phys[index].sas_address.low = 0x1 + ihost->id; | ||
1690 | ihost->oem_parameters.phys[index].sas_address.high = 0x5FCFFFFF; | ||
1691 | } | ||
1692 | |||
1693 | ihost->user_parameters.stp_inactivity_timeout = 5; | ||
1694 | ihost->user_parameters.ssp_inactivity_timeout = 5; | ||
1695 | ihost->user_parameters.stp_max_occupancy_timeout = 5; | ||
1696 | ihost->user_parameters.ssp_max_occupancy_timeout = 20; | ||
1697 | ihost->user_parameters.no_outbound_task_timeout = 2; | ||
1698 | } | ||
1699 | |||
1700 | static void controller_timeout(unsigned long data) | 1628 | static void controller_timeout(unsigned long data) |
1701 | { | 1629 | { |
1702 | struct sci_timer *tmr = (struct sci_timer *)data; | 1630 | struct sci_timer *tmr = (struct sci_timer *)data; |
@@ -1753,9 +1681,6 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost, | |||
1753 | 1681 | ||
1754 | sci_init_timer(&ihost->timer, controller_timeout); | 1682 | sci_init_timer(&ihost->timer, controller_timeout); |
1755 | 1683 | ||
1756 | /* Initialize the User and OEM parameters to default values. */ | ||
1757 | sci_controller_set_default_config_parameters(ihost); | ||
1758 | |||
1759 | return sci_controller_reset(ihost); | 1684 | return sci_controller_reset(ihost); |
1760 | } | 1685 | } |
1761 | 1686 | ||
@@ -1835,27 +1760,6 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version) | |||
1835 | return 0; | 1760 | return 0; |
1836 | } | 1761 | } |
1837 | 1762 | ||
1838 | static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) | ||
1839 | { | ||
1840 | u32 state = ihost->sm.current_state_id; | ||
1841 | struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); | ||
1842 | |||
1843 | if (state == SCIC_RESET || | ||
1844 | state == SCIC_INITIALIZING || | ||
1845 | state == SCIC_INITIALIZED) { | ||
1846 | u8 oem_version = pci_info->orom ? pci_info->orom->hdr.version : | ||
1847 | ISCI_ROM_VER_1_0; | ||
1848 | |||
1849 | if (sci_oem_parameters_validate(&ihost->oem_parameters, | ||
1850 | oem_version)) | ||
1851 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
1852 | |||
1853 | return SCI_SUCCESS; | ||
1854 | } | ||
1855 | |||
1856 | return SCI_FAILURE_INVALID_STATE; | ||
1857 | } | ||
1858 | |||
1859 | static u8 max_spin_up(struct isci_host *ihost) | 1763 | static u8 max_spin_up(struct isci_host *ihost) |
1860 | { | 1764 | { |
1861 | if (ihost->user_parameters.max_concurr_spinup) | 1765 | if (ihost->user_parameters.max_concurr_spinup) |
@@ -2372,96 +2276,77 @@ static enum sci_status sci_controller_initialize(struct isci_host *ihost) | |||
2372 | return result; | 2276 | return result; |
2373 | } | 2277 | } |
2374 | 2278 | ||
2375 | static enum sci_status sci_user_parameters_set(struct isci_host *ihost, | 2279 | static int sci_controller_dma_alloc(struct isci_host *ihost) |
2376 | struct sci_user_parameters *sci_parms) | ||
2377 | { | ||
2378 | u32 state = ihost->sm.current_state_id; | ||
2379 | |||
2380 | if (state == SCIC_RESET || | ||
2381 | state == SCIC_INITIALIZING || | ||
2382 | state == SCIC_INITIALIZED) { | ||
2383 | u16 index; | ||
2384 | |||
2385 | /* | ||
2386 | * Validate the user parameters. If they are not legal, then | ||
2387 | * return a failure. | ||
2388 | */ | ||
2389 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
2390 | struct sci_phy_user_params *user_phy; | ||
2391 | |||
2392 | user_phy = &sci_parms->phys[index]; | ||
2393 | |||
2394 | if (!((user_phy->max_speed_generation <= | ||
2395 | SCIC_SDS_PARM_MAX_SPEED) && | ||
2396 | (user_phy->max_speed_generation > | ||
2397 | SCIC_SDS_PARM_NO_SPEED))) | ||
2398 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2399 | |||
2400 | if (user_phy->in_connection_align_insertion_frequency < | ||
2401 | 3) | ||
2402 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2403 | |||
2404 | if ((user_phy->in_connection_align_insertion_frequency < | ||
2405 | 3) || | ||
2406 | (user_phy->align_insertion_frequency == 0) || | ||
2407 | (user_phy-> | ||
2408 | notify_enable_spin_up_insertion_frequency == | ||
2409 | 0)) | ||
2410 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2411 | } | ||
2412 | |||
2413 | if ((sci_parms->stp_inactivity_timeout == 0) || | ||
2414 | (sci_parms->ssp_inactivity_timeout == 0) || | ||
2415 | (sci_parms->stp_max_occupancy_timeout == 0) || | ||
2416 | (sci_parms->ssp_max_occupancy_timeout == 0) || | ||
2417 | (sci_parms->no_outbound_task_timeout == 0)) | ||
2418 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2419 | |||
2420 | memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms)); | ||
2421 | |||
2422 | return SCI_SUCCESS; | ||
2423 | } | ||
2424 | |||
2425 | return SCI_FAILURE_INVALID_STATE; | ||
2426 | } | ||
2427 | |||
2428 | static int sci_controller_mem_init(struct isci_host *ihost) | ||
2429 | { | 2280 | { |
2430 | struct device *dev = &ihost->pdev->dev; | 2281 | struct device *dev = &ihost->pdev->dev; |
2431 | dma_addr_t dma; | ||
2432 | size_t size; | 2282 | size_t size; |
2433 | int err; | 2283 | int i; |
2284 | |||
2285 | /* detect re-initialization */ | ||
2286 | if (ihost->completion_queue) | ||
2287 | return 0; | ||
2434 | 2288 | ||
2435 | size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32); | 2289 | size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32); |
2436 | ihost->completion_queue = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); | 2290 | ihost->completion_queue = dmam_alloc_coherent(dev, size, &ihost->cq_dma, |
2291 | GFP_KERNEL); | ||
2437 | if (!ihost->completion_queue) | 2292 | if (!ihost->completion_queue) |
2438 | return -ENOMEM; | 2293 | return -ENOMEM; |
2439 | 2294 | ||
2440 | writel(lower_32_bits(dma), &ihost->smu_registers->completion_queue_lower); | ||
2441 | writel(upper_32_bits(dma), &ihost->smu_registers->completion_queue_upper); | ||
2442 | |||
2443 | size = ihost->remote_node_entries * sizeof(union scu_remote_node_context); | 2295 | size = ihost->remote_node_entries * sizeof(union scu_remote_node_context); |
2444 | ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma, | 2296 | ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &ihost->rnc_dma, |
2445 | GFP_KERNEL); | 2297 | GFP_KERNEL); |
2298 | |||
2446 | if (!ihost->remote_node_context_table) | 2299 | if (!ihost->remote_node_context_table) |
2447 | return -ENOMEM; | 2300 | return -ENOMEM; |
2448 | 2301 | ||
2449 | writel(lower_32_bits(dma), &ihost->smu_registers->remote_node_context_lower); | ||
2450 | writel(upper_32_bits(dma), &ihost->smu_registers->remote_node_context_upper); | ||
2451 | |||
2452 | size = ihost->task_context_entries * sizeof(struct scu_task_context), | 2302 | size = ihost->task_context_entries * sizeof(struct scu_task_context), |
2453 | ihost->task_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); | 2303 | ihost->task_context_table = dmam_alloc_coherent(dev, size, &ihost->tc_dma, |
2304 | GFP_KERNEL); | ||
2454 | if (!ihost->task_context_table) | 2305 | if (!ihost->task_context_table) |
2455 | return -ENOMEM; | 2306 | return -ENOMEM; |
2456 | 2307 | ||
2457 | ihost->task_context_dma = dma; | 2308 | size = SCI_UFI_TOTAL_SIZE; |
2458 | writel(lower_32_bits(dma), &ihost->smu_registers->host_task_table_lower); | 2309 | ihost->ufi_buf = dmam_alloc_coherent(dev, size, &ihost->ufi_dma, GFP_KERNEL); |
2459 | writel(upper_32_bits(dma), &ihost->smu_registers->host_task_table_upper); | 2310 | if (!ihost->ufi_buf) |
2311 | return -ENOMEM; | ||
2312 | |||
2313 | for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { | ||
2314 | struct isci_request *ireq; | ||
2315 | dma_addr_t dma; | ||
2316 | |||
2317 | ireq = dmam_alloc_coherent(dev, sizeof(*ireq), &dma, GFP_KERNEL); | ||
2318 | if (!ireq) | ||
2319 | return -ENOMEM; | ||
2320 | |||
2321 | ireq->tc = &ihost->task_context_table[i]; | ||
2322 | ireq->owning_controller = ihost; | ||
2323 | spin_lock_init(&ireq->state_lock); | ||
2324 | ireq->request_daddr = dma; | ||
2325 | ireq->isci_host = ihost; | ||
2326 | ihost->reqs[i] = ireq; | ||
2327 | } | ||
2328 | |||
2329 | return 0; | ||
2330 | } | ||
2331 | |||
2332 | static int sci_controller_mem_init(struct isci_host *ihost) | ||
2333 | { | ||
2334 | int err = sci_controller_dma_alloc(ihost); | ||
2460 | 2335 | ||
2461 | err = sci_unsolicited_frame_control_construct(ihost); | ||
2462 | if (err) | 2336 | if (err) |
2463 | return err; | 2337 | return err; |
2464 | 2338 | ||
2339 | writel(lower_32_bits(ihost->cq_dma), &ihost->smu_registers->completion_queue_lower); | ||
2340 | writel(upper_32_bits(ihost->cq_dma), &ihost->smu_registers->completion_queue_upper); | ||
2341 | |||
2342 | writel(lower_32_bits(ihost->rnc_dma), &ihost->smu_registers->remote_node_context_lower); | ||
2343 | writel(upper_32_bits(ihost->rnc_dma), &ihost->smu_registers->remote_node_context_upper); | ||
2344 | |||
2345 | writel(lower_32_bits(ihost->tc_dma), &ihost->smu_registers->host_task_table_lower); | ||
2346 | writel(upper_32_bits(ihost->tc_dma), &ihost->smu_registers->host_task_table_upper); | ||
2347 | |||
2348 | sci_unsolicited_frame_control_construct(ihost); | ||
2349 | |||
2465 | /* | 2350 | /* |
2466 | * Inform the silicon as to the location of the UF headers and | 2351 | * Inform the silicon as to the location of the UF headers and |
2467 | * address table. | 2352 | * address table. |
@@ -2479,19 +2364,20 @@ static int sci_controller_mem_init(struct isci_host *ihost) | |||
2479 | return 0; | 2364 | return 0; |
2480 | } | 2365 | } |
2481 | 2366 | ||
2367 | /** | ||
2368 | * isci_host_init - (re-)initialize hardware and internal (private) state | ||
2369 | * @ihost: host to init | ||
2370 | * | ||
2371 | * Any public facing objects (like asd_sas_port, and asd_sas_phys), or | ||
2372 | * one-time initialization objects like locks and waitqueues, are | ||
2373 | * not touched (they are initialized in isci_host_alloc) | ||
2374 | */ | ||
2482 | int isci_host_init(struct isci_host *ihost) | 2375 | int isci_host_init(struct isci_host *ihost) |
2483 | { | 2376 | { |
2484 | int err = 0, i; | 2377 | int i, err; |
2485 | enum sci_status status; | 2378 | enum sci_status status; |
2486 | struct sci_user_parameters sci_user_params; | ||
2487 | struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); | ||
2488 | |||
2489 | spin_lock_init(&ihost->scic_lock); | ||
2490 | init_waitqueue_head(&ihost->eventq); | ||
2491 | |||
2492 | status = sci_controller_construct(ihost, scu_base(ihost), | ||
2493 | smu_base(ihost)); | ||
2494 | 2379 | ||
2380 | status = sci_controller_construct(ihost, scu_base(ihost), smu_base(ihost)); | ||
2495 | if (status != SCI_SUCCESS) { | 2381 | if (status != SCI_SUCCESS) { |
2496 | dev_err(&ihost->pdev->dev, | 2382 | dev_err(&ihost->pdev->dev, |
2497 | "%s: sci_controller_construct failed - status = %x\n", | 2383 | "%s: sci_controller_construct failed - status = %x\n", |
@@ -2500,48 +2386,6 @@ int isci_host_init(struct isci_host *ihost) | |||
2500 | return -ENODEV; | 2386 | return -ENODEV; |
2501 | } | 2387 | } |
2502 | 2388 | ||
2503 | ihost->sas_ha.dev = &ihost->pdev->dev; | ||
2504 | ihost->sas_ha.lldd_ha = ihost; | ||
2505 | |||
2506 | /* | ||
2507 | * grab initial values stored in the controller object for OEM and USER | ||
2508 | * parameters | ||
2509 | */ | ||
2510 | isci_user_parameters_get(&sci_user_params); | ||
2511 | status = sci_user_parameters_set(ihost, &sci_user_params); | ||
2512 | if (status != SCI_SUCCESS) { | ||
2513 | dev_warn(&ihost->pdev->dev, | ||
2514 | "%s: sci_user_parameters_set failed\n", | ||
2515 | __func__); | ||
2516 | return -ENODEV; | ||
2517 | } | ||
2518 | |||
2519 | /* grab any OEM parameters specified in orom */ | ||
2520 | if (pci_info->orom) { | ||
2521 | status = isci_parse_oem_parameters(&ihost->oem_parameters, | ||
2522 | pci_info->orom, | ||
2523 | ihost->id); | ||
2524 | if (status != SCI_SUCCESS) { | ||
2525 | dev_warn(&ihost->pdev->dev, | ||
2526 | "parsing firmware oem parameters failed\n"); | ||
2527 | return -EINVAL; | ||
2528 | } | ||
2529 | } | ||
2530 | |||
2531 | status = sci_oem_parameters_set(ihost); | ||
2532 | if (status != SCI_SUCCESS) { | ||
2533 | dev_warn(&ihost->pdev->dev, | ||
2534 | "%s: sci_oem_parameters_set failed\n", | ||
2535 | __func__); | ||
2536 | return -ENODEV; | ||
2537 | } | ||
2538 | |||
2539 | tasklet_init(&ihost->completion_tasklet, | ||
2540 | isci_host_completion_routine, (unsigned long)ihost); | ||
2541 | |||
2542 | INIT_LIST_HEAD(&ihost->requests_to_complete); | ||
2543 | INIT_LIST_HEAD(&ihost->requests_to_errorback); | ||
2544 | |||
2545 | spin_lock_irq(&ihost->scic_lock); | 2389 | spin_lock_irq(&ihost->scic_lock); |
2546 | status = sci_controller_initialize(ihost); | 2390 | status = sci_controller_initialize(ihost); |
2547 | spin_unlock_irq(&ihost->scic_lock); | 2391 | spin_unlock_irq(&ihost->scic_lock); |
@@ -2557,47 +2401,12 @@ int isci_host_init(struct isci_host *ihost) | |||
2557 | if (err) | 2401 | if (err) |
2558 | return err; | 2402 | return err; |
2559 | 2403 | ||
2560 | for (i = 0; i < SCI_MAX_PORTS; i++) { | ||
2561 | struct isci_port *iport = &ihost->ports[i]; | ||
2562 | |||
2563 | INIT_LIST_HEAD(&iport->remote_dev_list); | ||
2564 | iport->isci_host = ihost; | ||
2565 | } | ||
2566 | |||
2567 | for (i = 0; i < SCI_MAX_PHYS; i++) | ||
2568 | isci_phy_init(&ihost->phys[i], ihost, i); | ||
2569 | |||
2570 | /* enable sgpio */ | 2404 | /* enable sgpio */ |
2571 | writel(1, &ihost->scu_registers->peg0.sgpio.interface_control); | 2405 | writel(1, &ihost->scu_registers->peg0.sgpio.interface_control); |
2572 | for (i = 0; i < isci_gpio_count(ihost); i++) | 2406 | for (i = 0; i < isci_gpio_count(ihost); i++) |
2573 | writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]); | 2407 | writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]); |
2574 | writel(0, &ihost->scu_registers->peg0.sgpio.vendor_specific_code); | 2408 | writel(0, &ihost->scu_registers->peg0.sgpio.vendor_specific_code); |
2575 | 2409 | ||
2576 | for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { | ||
2577 | struct isci_remote_device *idev = &ihost->devices[i]; | ||
2578 | |||
2579 | INIT_LIST_HEAD(&idev->reqs_in_process); | ||
2580 | INIT_LIST_HEAD(&idev->node); | ||
2581 | } | ||
2582 | |||
2583 | for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { | ||
2584 | struct isci_request *ireq; | ||
2585 | dma_addr_t dma; | ||
2586 | |||
2587 | ireq = dmam_alloc_coherent(&ihost->pdev->dev, | ||
2588 | sizeof(struct isci_request), &dma, | ||
2589 | GFP_KERNEL); | ||
2590 | if (!ireq) | ||
2591 | return -ENOMEM; | ||
2592 | |||
2593 | ireq->tc = &ihost->task_context_table[i]; | ||
2594 | ireq->owning_controller = ihost; | ||
2595 | spin_lock_init(&ireq->state_lock); | ||
2596 | ireq->request_daddr = dma; | ||
2597 | ireq->isci_host = ihost; | ||
2598 | ihost->reqs[i] = ireq; | ||
2599 | } | ||
2600 | |||
2601 | return 0; | 2410 | return 0; |
2602 | } | 2411 | } |
2603 | 2412 | ||
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 81485b4a1a51..4695162f406e 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h | |||
@@ -158,13 +158,17 @@ struct isci_host { | |||
158 | struct sci_power_control power_control; | 158 | struct sci_power_control power_control; |
159 | u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; | 159 | u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; |
160 | struct scu_task_context *task_context_table; | 160 | struct scu_task_context *task_context_table; |
161 | dma_addr_t task_context_dma; | 161 | dma_addr_t tc_dma; |
162 | union scu_remote_node_context *remote_node_context_table; | 162 | union scu_remote_node_context *remote_node_context_table; |
163 | dma_addr_t rnc_dma; | ||
163 | u32 *completion_queue; | 164 | u32 *completion_queue; |
165 | dma_addr_t cq_dma; | ||
164 | u32 completion_queue_get; | 166 | u32 completion_queue_get; |
165 | u32 logical_port_entries; | 167 | u32 logical_port_entries; |
166 | u32 remote_node_entries; | 168 | u32 remote_node_entries; |
167 | u32 task_context_entries; | 169 | u32 task_context_entries; |
170 | void *ufi_buf; | ||
171 | dma_addr_t ufi_dma; | ||
168 | struct sci_unsolicited_frame_control uf_control; | 172 | struct sci_unsolicited_frame_control uf_control; |
169 | 173 | ||
170 | /* phy startup */ | 174 | /* phy startup */ |
@@ -452,36 +456,17 @@ void sci_controller_free_remote_node_context( | |||
452 | struct isci_remote_device *idev, | 456 | struct isci_remote_device *idev, |
453 | u16 node_id); | 457 | u16 node_id); |
454 | 458 | ||
455 | struct isci_request *sci_request_by_tag(struct isci_host *ihost, | 459 | struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag); |
456 | u16 io_tag); | 460 | void sci_controller_power_control_queue_insert(struct isci_host *ihost, |
457 | 461 | struct isci_phy *iphy); | |
458 | void sci_controller_power_control_queue_insert( | 462 | void sci_controller_power_control_queue_remove(struct isci_host *ihost, |
459 | struct isci_host *ihost, | 463 | struct isci_phy *iphy); |
460 | struct isci_phy *iphy); | 464 | void sci_controller_link_up(struct isci_host *ihost, struct isci_port *iport, |
461 | 465 | struct isci_phy *iphy); | |
462 | void sci_controller_power_control_queue_remove( | 466 | void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport, |
463 | struct isci_host *ihost, | 467 | struct isci_phy *iphy); |
464 | struct isci_phy *iphy); | 468 | void sci_controller_remote_device_stopped(struct isci_host *ihost, |
465 | 469 | struct isci_remote_device *idev); | |
466 | void sci_controller_link_up( | ||
467 | struct isci_host *ihost, | ||
468 | struct isci_port *iport, | ||
469 | struct isci_phy *iphy); | ||
470 | |||
471 | void sci_controller_link_down( | ||
472 | struct isci_host *ihost, | ||
473 | struct isci_port *iport, | ||
474 | struct isci_phy *iphy); | ||
475 | |||
476 | void sci_controller_remote_device_stopped( | ||
477 | struct isci_host *ihost, | ||
478 | struct isci_remote_device *idev); | ||
479 | |||
480 | void sci_controller_copy_task_context( | ||
481 | struct isci_host *ihost, | ||
482 | struct isci_request *ireq); | ||
483 | |||
484 | void sci_controller_register_setup(struct isci_host *ihost); | ||
485 | 470 | ||
486 | enum sci_status sci_controller_continue_io(struct isci_request *ireq); | 471 | enum sci_status sci_controller_continue_io(struct isci_request *ireq); |
487 | int isci_host_scan_finished(struct Scsi_Host *, unsigned long); | 472 | int isci_host_scan_finished(struct Scsi_Host *, unsigned long); |
@@ -491,27 +476,9 @@ enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag); | |||
491 | void isci_tci_free(struct isci_host *ihost, u16 tci); | 476 | void isci_tci_free(struct isci_host *ihost, u16 tci); |
492 | 477 | ||
493 | int isci_host_init(struct isci_host *); | 478 | int isci_host_init(struct isci_host *); |
494 | 479 | void isci_host_completion_routine(unsigned long data); | |
495 | void isci_host_init_controller_names( | 480 | void isci_host_deinit(struct isci_host *); |
496 | struct isci_host *isci_host, | 481 | void sci_controller_disable_interrupts(struct isci_host *ihost); |
497 | unsigned int controller_idx); | ||
498 | |||
499 | void isci_host_deinit( | ||
500 | struct isci_host *); | ||
501 | |||
502 | void isci_host_port_link_up( | ||
503 | struct isci_host *, | ||
504 | struct isci_port *, | ||
505 | struct isci_phy *); | ||
506 | int isci_host_dev_found(struct domain_device *); | ||
507 | |||
508 | void isci_host_remote_device_start_complete( | ||
509 | struct isci_host *, | ||
510 | struct isci_remote_device *, | ||
511 | enum sci_status); | ||
512 | |||
513 | void sci_controller_disable_interrupts( | ||
514 | struct isci_host *ihost); | ||
515 | 482 | ||
516 | enum sci_status sci_controller_start_io( | 483 | enum sci_status sci_controller_start_io( |
517 | struct isci_host *ihost, | 484 | struct isci_host *ihost, |
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 5137db5a5d85..eda43851cc98 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c | |||
@@ -397,38 +397,203 @@ static int isci_setup_interrupts(struct pci_dev *pdev) | |||
397 | return err; | 397 | return err; |
398 | } | 398 | } |
399 | 399 | ||
400 | static void isci_user_parameters_get(struct sci_user_parameters *u) | ||
401 | { | ||
402 | int i; | ||
403 | |||
404 | for (i = 0; i < SCI_MAX_PHYS; i++) { | ||
405 | struct sci_phy_user_params *u_phy = &u->phys[i]; | ||
406 | |||
407 | u_phy->max_speed_generation = phy_gen; | ||
408 | |||
409 | /* we are not exporting these for now */ | ||
410 | u_phy->align_insertion_frequency = 0x7f; | ||
411 | u_phy->in_connection_align_insertion_frequency = 0xff; | ||
412 | u_phy->notify_enable_spin_up_insertion_frequency = 0x33; | ||
413 | } | ||
414 | |||
415 | u->stp_inactivity_timeout = stp_inactive_to; | ||
416 | u->ssp_inactivity_timeout = ssp_inactive_to; | ||
417 | u->stp_max_occupancy_timeout = stp_max_occ_to; | ||
418 | u->ssp_max_occupancy_timeout = ssp_max_occ_to; | ||
419 | u->no_outbound_task_timeout = no_outbound_task_to; | ||
420 | u->max_concurr_spinup = max_concurr_spinup; | ||
421 | } | ||
422 | |||
423 | static enum sci_status sci_user_parameters_set(struct isci_host *ihost, | ||
424 | struct sci_user_parameters *sci_parms) | ||
425 | { | ||
426 | u16 index; | ||
427 | |||
428 | /* | ||
429 | * Validate the user parameters. If they are not legal, then | ||
430 | * return a failure. | ||
431 | */ | ||
432 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
433 | struct sci_phy_user_params *u; | ||
434 | |||
435 | u = &sci_parms->phys[index]; | ||
436 | |||
437 | if (!((u->max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED) && | ||
438 | (u->max_speed_generation > SCIC_SDS_PARM_NO_SPEED))) | ||
439 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
440 | |||
441 | if (u->in_connection_align_insertion_frequency < 3) | ||
442 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
443 | |||
444 | if ((u->in_connection_align_insertion_frequency < 3) || | ||
445 | (u->align_insertion_frequency == 0) || | ||
446 | (u->notify_enable_spin_up_insertion_frequency == 0)) | ||
447 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
448 | } | ||
449 | |||
450 | if ((sci_parms->stp_inactivity_timeout == 0) || | ||
451 | (sci_parms->ssp_inactivity_timeout == 0) || | ||
452 | (sci_parms->stp_max_occupancy_timeout == 0) || | ||
453 | (sci_parms->ssp_max_occupancy_timeout == 0) || | ||
454 | (sci_parms->no_outbound_task_timeout == 0)) | ||
455 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
456 | |||
457 | memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms)); | ||
458 | |||
459 | return SCI_SUCCESS; | ||
460 | } | ||
461 | |||
462 | static void sci_oem_defaults(struct isci_host *ihost) | ||
463 | { | ||
464 | /* these defaults are overridden by the platform / firmware */ | ||
465 | struct sci_user_parameters *user = &ihost->user_parameters; | ||
466 | struct sci_oem_params *oem = &ihost->oem_parameters; | ||
467 | int i; | ||
468 | |||
469 | /* Default to APC mode. */ | ||
470 | oem->controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; | ||
471 | |||
472 | /* Default to APC mode. */ | ||
473 | oem->controller.max_concurr_spin_up = 1; | ||
474 | |||
475 | /* Default to no SSC operation. */ | ||
476 | oem->controller.do_enable_ssc = false; | ||
477 | |||
478 | /* Default to short cables on all phys. */ | ||
479 | oem->controller.cable_selection_mask = 0; | ||
480 | |||
481 | /* Initialize all of the port parameter information to narrow ports. */ | ||
482 | for (i = 0; i < SCI_MAX_PORTS; i++) | ||
483 | oem->ports[i].phy_mask = 0; | ||
484 | |||
485 | /* Initialize all of the phy parameter information. */ | ||
486 | for (i = 0; i < SCI_MAX_PHYS; i++) { | ||
487 | /* Default to 3G (i.e. Gen 2). */ | ||
488 | user->phys[i].max_speed_generation = SCIC_SDS_PARM_GEN2_SPEED; | ||
489 | |||
490 | /* the frequencies cannot be 0 */ | ||
491 | user->phys[i].align_insertion_frequency = 0x7f; | ||
492 | user->phys[i].in_connection_align_insertion_frequency = 0xff; | ||
493 | user->phys[i].notify_enable_spin_up_insertion_frequency = 0x33; | ||
494 | |||
495 | /* Previous Vitesse based expanders had a arbitration issue that | ||
496 | * is worked around by having the upper 32-bits of SAS address | ||
497 | * with a value greater then the Vitesse company identifier. | ||
498 | * Hence, usage of 0x5FCFFFFF. | ||
499 | */ | ||
500 | oem->phys[i].sas_address.low = 0x1 + ihost->id; | ||
501 | oem->phys[i].sas_address.high = 0x5FCFFFFF; | ||
502 | } | ||
503 | |||
504 | user->stp_inactivity_timeout = 5; | ||
505 | user->ssp_inactivity_timeout = 5; | ||
506 | user->stp_max_occupancy_timeout = 5; | ||
507 | user->ssp_max_occupancy_timeout = 20; | ||
508 | user->no_outbound_task_timeout = 2; | ||
509 | } | ||
510 | |||
400 | static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) | 511 | static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) |
401 | { | 512 | { |
402 | struct isci_host *isci_host; | 513 | struct isci_orom *orom = to_pci_info(pdev)->orom; |
514 | struct sci_user_parameters sci_user_params; | ||
515 | u8 oem_version = ISCI_ROM_VER_1_0; | ||
516 | struct isci_host *ihost; | ||
403 | struct Scsi_Host *shost; | 517 | struct Scsi_Host *shost; |
404 | int err; | 518 | int err, i; |
405 | 519 | ||
406 | isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); | 520 | ihost = devm_kzalloc(&pdev->dev, sizeof(*ihost), GFP_KERNEL); |
407 | if (!isci_host) | 521 | if (!ihost) |
522 | return NULL; | ||
523 | |||
524 | ihost->pdev = pdev; | ||
525 | ihost->id = id; | ||
526 | spin_lock_init(&ihost->scic_lock); | ||
527 | init_waitqueue_head(&ihost->eventq); | ||
528 | ihost->sas_ha.dev = &ihost->pdev->dev; | ||
529 | ihost->sas_ha.lldd_ha = ihost; | ||
530 | tasklet_init(&ihost->completion_tasklet, | ||
531 | isci_host_completion_routine, (unsigned long)ihost); | ||
532 | |||
533 | /* validate module parameters */ | ||
534 | /* TODO: kill struct sci_user_parameters and reference directly */ | ||
535 | sci_oem_defaults(ihost); | ||
536 | isci_user_parameters_get(&sci_user_params); | ||
537 | if (sci_user_parameters_set(ihost, &sci_user_params)) { | ||
538 | dev_warn(&pdev->dev, | ||
539 | "%s: sci_user_parameters_set failed\n", __func__); | ||
540 | return NULL; | ||
541 | } | ||
542 | |||
543 | /* sanity check platform (or 'firmware') oem parameters */ | ||
544 | if (orom) { | ||
545 | if (id < 0 || id >= SCI_MAX_CONTROLLERS || id > orom->hdr.num_elements) { | ||
546 | dev_warn(&pdev->dev, "parsing firmware oem parameters failed\n"); | ||
547 | return NULL; | ||
548 | } | ||
549 | ihost->oem_parameters = orom->ctrl[id]; | ||
550 | oem_version = orom->hdr.version; | ||
551 | } | ||
552 | |||
553 | /* validate oem parameters (platform, firmware, or built-in defaults) */ | ||
554 | if (sci_oem_parameters_validate(&ihost->oem_parameters, oem_version)) { | ||
555 | dev_warn(&pdev->dev, "oem parameter validation failed\n"); | ||
408 | return NULL; | 556 | return NULL; |
557 | } | ||
558 | |||
559 | INIT_LIST_HEAD(&ihost->requests_to_complete); | ||
560 | INIT_LIST_HEAD(&ihost->requests_to_errorback); | ||
561 | for (i = 0; i < SCI_MAX_PORTS; i++) { | ||
562 | struct isci_port *iport = &ihost->ports[i]; | ||
563 | |||
564 | INIT_LIST_HEAD(&iport->remote_dev_list); | ||
565 | iport->isci_host = ihost; | ||
566 | } | ||
409 | 567 | ||
410 | isci_host->pdev = pdev; | 568 | for (i = 0; i < SCI_MAX_PHYS; i++) |
411 | isci_host->id = id; | 569 | isci_phy_init(&ihost->phys[i], ihost, i); |
570 | |||
571 | for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { | ||
572 | struct isci_remote_device *idev = &ihost->devices[i]; | ||
573 | |||
574 | INIT_LIST_HEAD(&idev->reqs_in_process); | ||
575 | INIT_LIST_HEAD(&idev->node); | ||
576 | } | ||
412 | 577 | ||
413 | shost = scsi_host_alloc(&isci_sht, sizeof(void *)); | 578 | shost = scsi_host_alloc(&isci_sht, sizeof(void *)); |
414 | if (!shost) | 579 | if (!shost) |
415 | return NULL; | 580 | return NULL; |
416 | isci_host->shost = shost; | 581 | ihost->shost = shost; |
417 | 582 | ||
418 | dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: " | 583 | dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: " |
419 | "{%s, %s, %s, %s}\n", | 584 | "{%s, %s, %s, %s}\n", |
420 | (is_cable_select_overridden() ? "* " : ""), isci_host->id, | 585 | (is_cable_select_overridden() ? "* " : ""), ihost->id, |
421 | lookup_cable_names(decode_cable_selection(isci_host, 3)), | 586 | lookup_cable_names(decode_cable_selection(ihost, 3)), |
422 | lookup_cable_names(decode_cable_selection(isci_host, 2)), | 587 | lookup_cable_names(decode_cable_selection(ihost, 2)), |
423 | lookup_cable_names(decode_cable_selection(isci_host, 1)), | 588 | lookup_cable_names(decode_cable_selection(ihost, 1)), |
424 | lookup_cable_names(decode_cable_selection(isci_host, 0))); | 589 | lookup_cable_names(decode_cable_selection(ihost, 0))); |
425 | 590 | ||
426 | err = isci_host_init(isci_host); | 591 | err = isci_host_init(ihost); |
427 | if (err) | 592 | if (err) |
428 | goto err_shost; | 593 | goto err_shost; |
429 | 594 | ||
430 | SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha; | 595 | SHOST_TO_SAS_HA(shost) = &ihost->sas_ha; |
431 | isci_host->sas_ha.core.shost = shost; | 596 | ihost->sas_ha.core.shost = shost; |
432 | shost->transportt = isci_transport_template; | 597 | shost->transportt = isci_transport_template; |
433 | 598 | ||
434 | shost->max_id = ~0; | 599 | shost->max_id = ~0; |
@@ -439,11 +604,11 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) | |||
439 | if (err) | 604 | if (err) |
440 | goto err_shost; | 605 | goto err_shost; |
441 | 606 | ||
442 | err = isci_register_sas_ha(isci_host); | 607 | err = isci_register_sas_ha(ihost); |
443 | if (err) | 608 | if (err) |
444 | goto err_shost_remove; | 609 | goto err_shost_remove; |
445 | 610 | ||
446 | return isci_host; | 611 | return ihost; |
447 | 612 | ||
448 | err_shost_remove: | 613 | err_shost_remove: |
449 | scsi_remove_host(shost); | 614 | scsi_remove_host(shost); |
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 9b8117b9d756..4d95654c3fd4 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c | |||
@@ -112,18 +112,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) | |||
112 | return rom; | 112 | return rom; |
113 | } | 113 | } |
114 | 114 | ||
115 | enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem, | ||
116 | struct isci_orom *orom, int scu_index) | ||
117 | { | ||
118 | /* check for valid inputs */ | ||
119 | if (scu_index < 0 || scu_index >= SCI_MAX_CONTROLLERS || | ||
120 | scu_index > orom->hdr.num_elements || !oem) | ||
121 | return -EINVAL; | ||
122 | |||
123 | *oem = orom->ctrl[scu_index]; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw) | 115 | struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw) |
128 | { | 116 | { |
129 | struct isci_orom *orom = NULL, *data; | 117 | struct isci_orom *orom = NULL, *data; |
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index bb0e9d4d97c9..e08b578241f8 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h | |||
@@ -156,8 +156,6 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version); | |||
156 | 156 | ||
157 | struct isci_orom; | 157 | struct isci_orom; |
158 | struct isci_orom *isci_request_oprom(struct pci_dev *pdev); | 158 | struct isci_orom *isci_request_oprom(struct pci_dev *pdev); |
159 | enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem, | ||
160 | struct isci_orom *orom, int scu_index); | ||
161 | struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); | 159 | struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); |
162 | struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); | 160 | struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); |
163 | 161 | ||
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 835ede848871..dcd26eadf867 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -92,11 +92,11 @@ static dma_addr_t to_sgl_element_pair_dma(struct isci_host *ihost, | |||
92 | if (idx == 0) { | 92 | if (idx == 0) { |
93 | offset = (void *) &ireq->tc->sgl_pair_ab - | 93 | offset = (void *) &ireq->tc->sgl_pair_ab - |
94 | (void *) &ihost->task_context_table[0]; | 94 | (void *) &ihost->task_context_table[0]; |
95 | return ihost->task_context_dma + offset; | 95 | return ihost->tc_dma + offset; |
96 | } else if (idx == 1) { | 96 | } else if (idx == 1) { |
97 | offset = (void *) &ireq->tc->sgl_pair_cd - | 97 | offset = (void *) &ireq->tc->sgl_pair_cd - |
98 | (void *) &ihost->task_context_table[0]; | 98 | (void *) &ihost->task_context_table[0]; |
99 | return ihost->task_context_dma + offset; | 99 | return ihost->tc_dma + offset; |
100 | } | 100 | } |
101 | 101 | ||
102 | return sci_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]); | 102 | return sci_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]); |
diff --git a/drivers/scsi/isci/unsolicited_frame_control.c b/drivers/scsi/isci/unsolicited_frame_control.c index 16f88ab939c8..04a6d0d59a22 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.c +++ b/drivers/scsi/isci/unsolicited_frame_control.c | |||
@@ -57,31 +57,19 @@ | |||
57 | #include "unsolicited_frame_control.h" | 57 | #include "unsolicited_frame_control.h" |
58 | #include "registers.h" | 58 | #include "registers.h" |
59 | 59 | ||
60 | int sci_unsolicited_frame_control_construct(struct isci_host *ihost) | 60 | void sci_unsolicited_frame_control_construct(struct isci_host *ihost) |
61 | { | 61 | { |
62 | struct sci_unsolicited_frame_control *uf_control = &ihost->uf_control; | 62 | struct sci_unsolicited_frame_control *uf_control = &ihost->uf_control; |
63 | struct sci_unsolicited_frame *uf; | 63 | struct sci_unsolicited_frame *uf; |
64 | u32 buf_len, header_len, i; | 64 | dma_addr_t dma = ihost->ufi_dma; |
65 | dma_addr_t dma; | 65 | void *virt = ihost->ufi_buf; |
66 | size_t size; | 66 | int i; |
67 | void *virt; | ||
68 | |||
69 | /* | ||
70 | * Prepare all of the memory sizes for the UF headers, UF address | ||
71 | * table, and UF buffers themselves. | ||
72 | */ | ||
73 | buf_len = SCU_MAX_UNSOLICITED_FRAMES * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; | ||
74 | header_len = SCU_MAX_UNSOLICITED_FRAMES * sizeof(struct scu_unsolicited_frame_header); | ||
75 | size = buf_len + header_len + SCU_MAX_UNSOLICITED_FRAMES * sizeof(uf_control->address_table.array[0]); | ||
76 | 67 | ||
77 | /* | 68 | /* |
78 | * The Unsolicited Frame buffers are set at the start of the UF | 69 | * The Unsolicited Frame buffers are set at the start of the UF |
79 | * memory descriptor entry. The headers and address table will be | 70 | * memory descriptor entry. The headers and address table will be |
80 | * placed after the buffers. | 71 | * placed after the buffers. |
81 | */ | 72 | */ |
82 | virt = dmam_alloc_coherent(&ihost->pdev->dev, size, &dma, GFP_KERNEL); | ||
83 | if (!virt) | ||
84 | return -ENOMEM; | ||
85 | 73 | ||
86 | /* | 74 | /* |
87 | * Program the location of the UF header table into the SCU. | 75 | * Program the location of the UF header table into the SCU. |
@@ -93,8 +81,8 @@ int sci_unsolicited_frame_control_construct(struct isci_host *ihost) | |||
93 | * headers, since we program the UF address table pointers to | 81 | * headers, since we program the UF address table pointers to |
94 | * NULL. | 82 | * NULL. |
95 | */ | 83 | */ |
96 | uf_control->headers.physical_address = dma + buf_len; | 84 | uf_control->headers.physical_address = dma + SCI_UFI_BUF_SIZE; |
97 | uf_control->headers.array = virt + buf_len; | 85 | uf_control->headers.array = virt + SCI_UFI_BUF_SIZE; |
98 | 86 | ||
99 | /* | 87 | /* |
100 | * Program the location of the UF address table into the SCU. | 88 | * Program the location of the UF address table into the SCU. |
@@ -103,8 +91,8 @@ int sci_unsolicited_frame_control_construct(struct isci_host *ihost) | |||
103 | * byte boundary already due to above programming headers being on a | 91 | * byte boundary already due to above programming headers being on a |
104 | * 64-bit boundary and headers are on a 64-bytes in size. | 92 | * 64-bit boundary and headers are on a 64-bytes in size. |
105 | */ | 93 | */ |
106 | uf_control->address_table.physical_address = dma + buf_len + header_len; | 94 | uf_control->address_table.physical_address = dma + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE; |
107 | uf_control->address_table.array = virt + buf_len + header_len; | 95 | uf_control->address_table.array = virt + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE; |
108 | uf_control->get = 0; | 96 | uf_control->get = 0; |
109 | 97 | ||
110 | /* | 98 | /* |
@@ -135,8 +123,6 @@ int sci_unsolicited_frame_control_construct(struct isci_host *ihost) | |||
135 | virt += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; | 123 | virt += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; |
136 | dma += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; | 124 | dma += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; |
137 | } | 125 | } |
138 | |||
139 | return 0; | ||
140 | } | 126 | } |
141 | 127 | ||
142 | enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control, | 128 | enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control, |
diff --git a/drivers/scsi/isci/unsolicited_frame_control.h b/drivers/scsi/isci/unsolicited_frame_control.h index 75d896686f5a..1bc551ec611f 100644 --- a/drivers/scsi/isci/unsolicited_frame_control.h +++ b/drivers/scsi/isci/unsolicited_frame_control.h | |||
@@ -257,9 +257,13 @@ struct sci_unsolicited_frame_control { | |||
257 | 257 | ||
258 | }; | 258 | }; |
259 | 259 | ||
260 | #define SCI_UFI_BUF_SIZE (SCU_MAX_UNSOLICITED_FRAMES * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) | ||
261 | #define SCI_UFI_HDR_SIZE (SCU_MAX_UNSOLICITED_FRAMES * sizeof(struct scu_unsolicited_frame_header)) | ||
262 | #define SCI_UFI_TOTAL_SIZE (SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE + SCU_MAX_UNSOLICITED_FRAMES * sizeof(u64)) | ||
263 | |||
260 | struct isci_host; | 264 | struct isci_host; |
261 | 265 | ||
262 | int sci_unsolicited_frame_control_construct(struct isci_host *ihost); | 266 | void sci_unsolicited_frame_control_construct(struct isci_host *ihost); |
263 | 267 | ||
264 | enum sci_status sci_unsolicited_frame_control_get_header( | 268 | enum sci_status sci_unsolicited_frame_control_get_header( |
265 | struct sci_unsolicited_frame_control *uf_control, | 269 | struct sci_unsolicited_frame_control *uf_control, |