Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

isci: refactor initialization for S3/S4

Based on an original implementation by Ed Nadolski and Artur Wojcik

In preparation for S3/S4 support refactor initialization so that
driver-load and resume-from-suspend can share the common init path of
isci_host_init(). Organize the initialization into objects that are
self-contained to the driver (initialized by isci_host_init) versus
those that have some upward registration (initialized at allocation time
asd_sas_phy, asd_sas_port, dma allocations). The largest change is
moving the the validation of the oem and module parameters from
isci_host_init() to isci_host_alloc().

The S3/S4 approach being taken is that libsas will be tasked with
remembering the state of the domain and the lldd is free to be
forgetful. In the case of isci we'll just re-init using a subset of the
normal driver load path.

[clean up some unused / mis-indented function definitions in host.h]

Signed-off-by: Ed Nadolski <edmund.nadolski@intel.com>
Signed-off-by: Artur Wojcik <artur.wojcik@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+278 -361
+62 -253
drivers/scsi/isci/host.c
··· 1074 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 1079 struct isci_host *ihost = (struct isci_host *)data; 1080 1080 struct list_head completed_request_list; ··· 1315 1315 int id = isci_host->id; 1316 1316 1317 1317 return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; 1318 - } 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 1318 } 1342 1319 1343 1320 static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm) ··· 1625 1648 [SCIC_FAILED] = {} 1626 1649 }; 1627 1650 1628 - static void sci_controller_set_default_config_parameters(struct isci_host *ihost) 1629 - { 1630 - /* these defaults are overridden by the platform / firmware */ 1631 - u16 index; 1632 - 1633 - /* Default to APC mode. */ 1634 - ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; 1635 - 1636 - /* Default to APC mode. */ 1637 - ihost->oem_parameters.controller.max_concurr_spin_up = 1; 1638 - 1639 - /* Default to no SSC operation. */ 1640 - ihost->oem_parameters.controller.do_enable_ssc = false; 1641 - 1642 - /* Default to short cables on all phys. */ 1643 - ihost->oem_parameters.controller.cable_selection_mask = 0; 1644 - 1645 - /* Initialize all of the port parameter information to narrow ports. */ 1646 - for (index = 0; index < SCI_MAX_PORTS; index++) { 1647 - ihost->oem_parameters.ports[index].phy_mask = 0; 1648 - } 1649 - 1650 - /* Initialize all of the phy parameter information. */ 1651 - for (index = 0; index < SCI_MAX_PHYS; index++) { 1652 - /* Default to 3G (i.e. Gen 2). */ 1653 - ihost->user_parameters.phys[index].max_speed_generation = 1654 - SCIC_SDS_PARM_GEN2_SPEED; 1655 - 1656 - /* the frequencies cannot be 0 */ 1657 - ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f; 1658 - ihost->user_parameters.phys[index].in_connection_align_insertion_frequency = 0xff; 1659 - ihost->user_parameters.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; 1660 - 1661 - /* 1662 - * Previous Vitesse based expanders had a arbitration issue that 1663 - * is worked around by having the upper 32-bits of SAS address 1664 - * with a value greater then the Vitesse company identifier. 1665 - * Hence, usage of 0x5FCFFFFF. */ 1666 - ihost->oem_parameters.phys[index].sas_address.low = 0x1 + ihost->id; 1667 - ihost->oem_parameters.phys[index].sas_address.high = 0x5FCFFFFF; 1668 - } 1669 - 1670 - ihost->user_parameters.stp_inactivity_timeout = 5; 1671 - ihost->user_parameters.ssp_inactivity_timeout = 5; 1672 - ihost->user_parameters.stp_max_occupancy_timeout = 5; 1673 - ihost->user_parameters.ssp_max_occupancy_timeout = 20; 1674 - ihost->user_parameters.no_outbound_task_timeout = 2; 1675 - } 1676 - 1677 1651 static void controller_timeout(unsigned long data) 1678 1652 { 1679 1653 struct sci_timer *tmr = (struct sci_timer *)data; ··· 1680 1752 ihost->invalid_phy_mask = 0; 1681 1753 1682 1754 sci_init_timer(&ihost->timer, controller_timeout); 1683 - 1684 - /* Initialize the User and OEM parameters to default values. */ 1685 - sci_controller_set_default_config_parameters(ihost); 1686 1755 1687 1756 return sci_controller_reset(ihost); 1688 1757 } ··· 1758 1833 } 1759 1834 1760 1835 return 0; 1761 - } 1762 - 1763 - static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) 1764 - { 1765 - u32 state = ihost->sm.current_state_id; 1766 - struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); 1767 - 1768 - if (state == SCIC_RESET || 1769 - state == SCIC_INITIALIZING || 1770 - state == SCIC_INITIALIZED) { 1771 - u8 oem_version = pci_info->orom ? pci_info->orom->hdr.version : 1772 - ISCI_ROM_VER_1_0; 1773 - 1774 - if (sci_oem_parameters_validate(&ihost->oem_parameters, 1775 - oem_version)) 1776 - return SCI_FAILURE_INVALID_PARAMETER_VALUE; 1777 - 1778 - return SCI_SUCCESS; 1779 - } 1780 - 1781 - return SCI_FAILURE_INVALID_STATE; 1782 1836 } 1783 1837 1784 1838 static u8 max_spin_up(struct isci_host *ihost) ··· 2276 2372 return result; 2277 2373 } 2278 2374 2279 - static enum sci_status sci_user_parameters_set(struct isci_host *ihost, 2280 - struct sci_user_parameters *sci_parms) 2375 + static int sci_controller_dma_alloc(struct isci_host *ihost) 2281 2376 { 2282 - u32 state = ihost->sm.current_state_id; 2377 + struct device *dev = &ihost->pdev->dev; 2378 + size_t size; 2379 + int i; 2283 2380 2284 - if (state == SCIC_RESET || 2285 - state == SCIC_INITIALIZING || 2286 - state == SCIC_INITIALIZED) { 2287 - u16 index; 2381 + /* detect re-initialization */ 2382 + if (ihost->completion_queue) 2383 + return 0; 2288 2384 2289 - /* 2290 - * Validate the user parameters. If they are not legal, then 2291 - * return a failure. 2292 - */ 2293 - for (index = 0; index < SCI_MAX_PHYS; index++) { 2294 - struct sci_phy_user_params *user_phy; 2385 + size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32); 2386 + ihost->completion_queue = dmam_alloc_coherent(dev, size, &ihost->cq_dma, 2387 + GFP_KERNEL); 2388 + if (!ihost->completion_queue) 2389 + return -ENOMEM; 2295 2390 2296 - user_phy = &sci_parms->phys[index]; 2391 + size = ihost->remote_node_entries * sizeof(union scu_remote_node_context); 2392 + ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &ihost->rnc_dma, 2393 + GFP_KERNEL); 2297 2394 2298 - if (!((user_phy->max_speed_generation <= 2299 - SCIC_SDS_PARM_MAX_SPEED) && 2300 - (user_phy->max_speed_generation > 2301 - SCIC_SDS_PARM_NO_SPEED))) 2302 - return SCI_FAILURE_INVALID_PARAMETER_VALUE; 2395 + if (!ihost->remote_node_context_table) 2396 + return -ENOMEM; 2303 2397 2304 - if (user_phy->in_connection_align_insertion_frequency < 2305 - 3) 2306 - return SCI_FAILURE_INVALID_PARAMETER_VALUE; 2398 + size = ihost->task_context_entries * sizeof(struct scu_task_context), 2399 + ihost->task_context_table = dmam_alloc_coherent(dev, size, &ihost->tc_dma, 2400 + GFP_KERNEL); 2401 + if (!ihost->task_context_table) 2402 + return -ENOMEM; 2307 2403 2308 - if ((user_phy->in_connection_align_insertion_frequency < 2309 - 3) || 2310 - (user_phy->align_insertion_frequency == 0) || 2311 - (user_phy-> 2312 - notify_enable_spin_up_insertion_frequency == 2313 - 0)) 2314 - return SCI_FAILURE_INVALID_PARAMETER_VALUE; 2315 - } 2404 + size = SCI_UFI_TOTAL_SIZE; 2405 + ihost->ufi_buf = dmam_alloc_coherent(dev, size, &ihost->ufi_dma, GFP_KERNEL); 2406 + if (!ihost->ufi_buf) 2407 + return -ENOMEM; 2316 2408 2317 - if ((sci_parms->stp_inactivity_timeout == 0) || 2318 - (sci_parms->ssp_inactivity_timeout == 0) || 2319 - (sci_parms->stp_max_occupancy_timeout == 0) || 2320 - (sci_parms->ssp_max_occupancy_timeout == 0) || 2321 - (sci_parms->no_outbound_task_timeout == 0)) 2322 - return SCI_FAILURE_INVALID_PARAMETER_VALUE; 2409 + for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { 2410 + struct isci_request *ireq; 2411 + dma_addr_t dma; 2323 2412 2324 - memcpy(&ihost->user_parameters, sci_parms, sizeof(*sci_parms)); 2413 + ireq = dmam_alloc_coherent(dev, sizeof(*ireq), &dma, GFP_KERNEL); 2414 + if (!ireq) 2415 + return -ENOMEM; 2325 2416 2326 - return SCI_SUCCESS; 2417 + ireq->tc = &ihost->task_context_table[i]; 2418 + ireq->owning_controller = ihost; 2419 + spin_lock_init(&ireq->state_lock); 2420 + ireq->request_daddr = dma; 2421 + ireq->isci_host = ihost; 2422 + ihost->reqs[i] = ireq; 2327 2423 } 2328 2424 2329 - return SCI_FAILURE_INVALID_STATE; 2425 + return 0; 2330 2426 } 2331 2427 2332 2428 static int sci_controller_mem_init(struct isci_host *ihost) 2333 2429 { 2334 - struct device *dev = &ihost->pdev->dev; 2335 - dma_addr_t dma; 2336 - size_t size; 2337 - int err; 2430 + int err = sci_controller_dma_alloc(ihost); 2338 2431 2339 - size = SCU_MAX_COMPLETION_QUEUE_ENTRIES * sizeof(u32); 2340 - ihost->completion_queue = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); 2341 - if (!ihost->completion_queue) 2342 - return -ENOMEM; 2343 - 2344 - writel(lower_32_bits(dma), &ihost->smu_registers->completion_queue_lower); 2345 - writel(upper_32_bits(dma), &ihost->smu_registers->completion_queue_upper); 2346 - 2347 - size = ihost->remote_node_entries * sizeof(union scu_remote_node_context); 2348 - ihost->remote_node_context_table = dmam_alloc_coherent(dev, size, &dma, 2349 - GFP_KERNEL); 2350 - if (!ihost->remote_node_context_table) 2351 - return -ENOMEM; 2352 - 2353 - writel(lower_32_bits(dma), &ihost->smu_registers->remote_node_context_lower); 2354 - writel(upper_32_bits(dma), &ihost->smu_registers->remote_node_context_upper); 2355 - 2356 - size = ihost->task_context_entries * sizeof(struct scu_task_context), 2357 - ihost->task_context_table = dmam_alloc_coherent(dev, size, &dma, GFP_KERNEL); 2358 - if (!ihost->task_context_table) 2359 - return -ENOMEM; 2360 - 2361 - ihost->task_context_dma = dma; 2362 - writel(lower_32_bits(dma), &ihost->smu_registers->host_task_table_lower); 2363 - writel(upper_32_bits(dma), &ihost->smu_registers->host_task_table_upper); 2364 - 2365 - err = sci_unsolicited_frame_control_construct(ihost); 2366 2432 if (err) 2367 2433 return err; 2434 + 2435 + writel(lower_32_bits(ihost->cq_dma), &ihost->smu_registers->completion_queue_lower); 2436 + writel(upper_32_bits(ihost->cq_dma), &ihost->smu_registers->completion_queue_upper); 2437 + 2438 + writel(lower_32_bits(ihost->rnc_dma), &ihost->smu_registers->remote_node_context_lower); 2439 + writel(upper_32_bits(ihost->rnc_dma), &ihost->smu_registers->remote_node_context_upper); 2440 + 2441 + writel(lower_32_bits(ihost->tc_dma), &ihost->smu_registers->host_task_table_lower); 2442 + writel(upper_32_bits(ihost->tc_dma), &ihost->smu_registers->host_task_table_upper); 2443 + 2444 + sci_unsolicited_frame_control_construct(ihost); 2368 2445 2369 2446 /* 2370 2447 * Inform the silicon as to the location of the UF headers and ··· 2364 2479 return 0; 2365 2480 } 2366 2481 2482 + /** 2483 + * isci_host_init - (re-)initialize hardware and internal (private) state 2484 + * @ihost: host to init 2485 + * 2486 + * Any public facing objects (like asd_sas_port, and asd_sas_phys), or 2487 + * one-time initialization objects like locks and waitqueues, are 2488 + * not touched (they are initialized in isci_host_alloc) 2489 + */ 2367 2490 int isci_host_init(struct isci_host *ihost) 2368 2491 { 2369 - int err = 0, i; 2492 + int i, err; 2370 2493 enum sci_status status; 2371 - struct sci_user_parameters sci_user_params; 2372 - struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); 2373 2494 2374 - spin_lock_init(&ihost->scic_lock); 2375 - init_waitqueue_head(&ihost->eventq); 2376 - 2377 - status = sci_controller_construct(ihost, scu_base(ihost), 2378 - smu_base(ihost)); 2379 - 2495 + status = sci_controller_construct(ihost, scu_base(ihost), smu_base(ihost)); 2380 2496 if (status != SCI_SUCCESS) { 2381 2497 dev_err(&ihost->pdev->dev, 2382 2498 "%s: sci_controller_construct failed - status = %x\n", ··· 2385 2499 status); 2386 2500 return -ENODEV; 2387 2501 } 2388 - 2389 - ihost->sas_ha.dev = &ihost->pdev->dev; 2390 - ihost->sas_ha.lldd_ha = ihost; 2391 - 2392 - /* 2393 - * grab initial values stored in the controller object for OEM and USER 2394 - * parameters 2395 - */ 2396 - isci_user_parameters_get(&sci_user_params); 2397 - status = sci_user_parameters_set(ihost, &sci_user_params); 2398 - if (status != SCI_SUCCESS) { 2399 - dev_warn(&ihost->pdev->dev, 2400 - "%s: sci_user_parameters_set failed\n", 2401 - __func__); 2402 - return -ENODEV; 2403 - } 2404 - 2405 - /* grab any OEM parameters specified in orom */ 2406 - if (pci_info->orom) { 2407 - status = isci_parse_oem_parameters(&ihost->oem_parameters, 2408 - pci_info->orom, 2409 - ihost->id); 2410 - if (status != SCI_SUCCESS) { 2411 - dev_warn(&ihost->pdev->dev, 2412 - "parsing firmware oem parameters failed\n"); 2413 - return -EINVAL; 2414 - } 2415 - } 2416 - 2417 - status = sci_oem_parameters_set(ihost); 2418 - if (status != SCI_SUCCESS) { 2419 - dev_warn(&ihost->pdev->dev, 2420 - "%s: sci_oem_parameters_set failed\n", 2421 - __func__); 2422 - return -ENODEV; 2423 - } 2424 - 2425 - tasklet_init(&ihost->completion_tasklet, 2426 - isci_host_completion_routine, (unsigned long)ihost); 2427 - 2428 - INIT_LIST_HEAD(&ihost->requests_to_complete); 2429 - INIT_LIST_HEAD(&ihost->requests_to_errorback); 2430 2502 2431 2503 spin_lock_irq(&ihost->scic_lock); 2432 2504 status = sci_controller_initialize(ihost); ··· 2401 2557 if (err) 2402 2558 return err; 2403 2559 2404 - for (i = 0; i < SCI_MAX_PORTS; i++) { 2405 - struct isci_port *iport = &ihost->ports[i]; 2406 - 2407 - INIT_LIST_HEAD(&iport->remote_dev_list); 2408 - iport->isci_host = ihost; 2409 - } 2410 - 2411 - for (i = 0; i < SCI_MAX_PHYS; i++) 2412 - isci_phy_init(&ihost->phys[i], ihost, i); 2413 - 2414 2560 /* enable sgpio */ 2415 2561 writel(1, &ihost->scu_registers->peg0.sgpio.interface_control); 2416 2562 for (i = 0; i < isci_gpio_count(ihost); i++) 2417 2563 writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]); 2418 2564 writel(0, &ihost->scu_registers->peg0.sgpio.vendor_specific_code); 2419 - 2420 - for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { 2421 - struct isci_remote_device *idev = &ihost->devices[i]; 2422 - 2423 - INIT_LIST_HEAD(&idev->reqs_in_process); 2424 - INIT_LIST_HEAD(&idev->node); 2425 - } 2426 - 2427 - for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { 2428 - struct isci_request *ireq; 2429 - dma_addr_t dma; 2430 - 2431 - ireq = dmam_alloc_coherent(&ihost->pdev->dev, 2432 - sizeof(struct isci_request), &dma, 2433 - GFP_KERNEL); 2434 - if (!ireq) 2435 - return -ENOMEM; 2436 - 2437 - ireq->tc = &ihost->task_context_table[i]; 2438 - ireq->owning_controller = ihost; 2439 - spin_lock_init(&ireq->state_lock); 2440 - ireq->request_daddr = dma; 2441 - ireq->isci_host = ihost; 2442 - ihost->reqs[i] = ireq; 2443 - } 2444 2565 2445 2566 return 0; 2446 2567 }
+19 -52
drivers/scsi/isci/host.h
··· 158 158 struct sci_power_control power_control; 159 159 u8 io_request_sequence[SCI_MAX_IO_REQUESTS]; 160 160 struct scu_task_context *task_context_table; 161 - dma_addr_t task_context_dma; 161 + dma_addr_t tc_dma; 162 162 union scu_remote_node_context *remote_node_context_table; 163 + dma_addr_t rnc_dma; 163 164 u32 *completion_queue; 165 + dma_addr_t cq_dma; 164 166 u32 completion_queue_get; 165 167 u32 logical_port_entries; 166 168 u32 remote_node_entries; 167 169 u32 task_context_entries; 170 + void *ufi_buf; 171 + dma_addr_t ufi_dma; 168 172 struct sci_unsolicited_frame_control uf_control; 169 173 170 174 /* phy startup */ ··· 456 452 struct isci_remote_device *idev, 457 453 u16 node_id); 458 454 459 - struct isci_request *sci_request_by_tag(struct isci_host *ihost, 460 - u16 io_tag); 461 - 462 - void sci_controller_power_control_queue_insert( 463 - struct isci_host *ihost, 464 - struct isci_phy *iphy); 465 - 466 - void sci_controller_power_control_queue_remove( 467 - struct isci_host *ihost, 468 - struct isci_phy *iphy); 469 - 470 - void sci_controller_link_up( 471 - struct isci_host *ihost, 472 - struct isci_port *iport, 473 - struct isci_phy *iphy); 474 - 475 - void sci_controller_link_down( 476 - struct isci_host *ihost, 477 - struct isci_port *iport, 478 - struct isci_phy *iphy); 479 - 480 - void sci_controller_remote_device_stopped( 481 - struct isci_host *ihost, 482 - struct isci_remote_device *idev); 483 - 484 - void sci_controller_copy_task_context( 485 - struct isci_host *ihost, 486 - struct isci_request *ireq); 487 - 488 - void sci_controller_register_setup(struct isci_host *ihost); 455 + struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag); 456 + void sci_controller_power_control_queue_insert(struct isci_host *ihost, 457 + struct isci_phy *iphy); 458 + void sci_controller_power_control_queue_remove(struct isci_host *ihost, 459 + struct isci_phy *iphy); 460 + void sci_controller_link_up(struct isci_host *ihost, struct isci_port *iport, 461 + struct isci_phy *iphy); 462 + void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport, 463 + struct isci_phy *iphy); 464 + void sci_controller_remote_device_stopped(struct isci_host *ihost, 465 + struct isci_remote_device *idev); 489 466 490 467 enum sci_status sci_controller_continue_io(struct isci_request *ireq); 491 468 int isci_host_scan_finished(struct Scsi_Host *, unsigned long); ··· 476 491 void isci_tci_free(struct isci_host *ihost, u16 tci); 477 492 478 493 int isci_host_init(struct isci_host *); 479 - 480 - void isci_host_init_controller_names( 481 - struct isci_host *isci_host, 482 - unsigned int controller_idx); 483 - 484 - void isci_host_deinit( 485 - struct isci_host *); 486 - 487 - void isci_host_port_link_up( 488 - struct isci_host *, 489 - struct isci_port *, 490 - struct isci_phy *); 491 - int isci_host_dev_found(struct domain_device *); 492 - 493 - void isci_host_remote_device_start_complete( 494 - struct isci_host *, 495 - struct isci_remote_device *, 496 - enum sci_status); 497 - 498 - void sci_controller_disable_interrupts( 499 - struct isci_host *ihost); 494 + void isci_host_completion_routine(unsigned long data); 495 + void isci_host_deinit(struct isci_host *); 496 + void sci_controller_disable_interrupts(struct isci_host *ihost); 500 497 501 498 enum sci_status sci_controller_start_io( 502 499 struct isci_host *ihost,
+182 -17
drivers/scsi/isci/init.c
··· 397 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 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 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); 407 - if (!isci_host) 520 + ihost = devm_kzalloc(&pdev->dev, sizeof(*ihost), GFP_KERNEL); 521 + if (!ihost) 408 522 return NULL; 409 523 410 - isci_host->pdev = pdev; 411 - isci_host->id = id; 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"); 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 + } 567 + 568 + for (i = 0; i < SCI_MAX_PHYS; i++) 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 578 shost = scsi_host_alloc(&isci_sht, sizeof(void *)); 414 579 if (!shost) 415 580 return NULL; 416 - isci_host->shost = shost; 581 + ihost->shost = shost; 417 582 418 583 dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: " 419 584 "{%s, %s, %s, %s}\n", 420 - (is_cable_select_overridden() ? "* " : ""), isci_host->id, 421 - lookup_cable_names(decode_cable_selection(isci_host, 3)), 422 - lookup_cable_names(decode_cable_selection(isci_host, 2)), 423 - lookup_cable_names(decode_cable_selection(isci_host, 1)), 424 - lookup_cable_names(decode_cable_selection(isci_host, 0))); 585 + (is_cable_select_overridden() ? "* " : ""), ihost->id, 586 + lookup_cable_names(decode_cable_selection(ihost, 3)), 587 + lookup_cable_names(decode_cable_selection(ihost, 2)), 588 + lookup_cable_names(decode_cable_selection(ihost, 1)), 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 592 if (err) 428 593 goto err_shost; 429 594 430 - SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha; 431 - isci_host->sas_ha.core.shost = shost; 595 + SHOST_TO_SAS_HA(shost) = &ihost->sas_ha; 596 + ihost->sas_ha.core.shost = shost; 432 597 shost->transportt = isci_transport_template; 433 598 434 599 shost->max_id = ~0; ··· 604 439 if (err) 605 440 goto err_shost; 606 441 607 - err = isci_register_sas_ha(isci_host); 442 + err = isci_register_sas_ha(ihost); 608 443 if (err) 609 444 goto err_shost_remove; 610 445 611 - return isci_host; 446 + return ihost; 612 447 613 448 err_shost_remove: 614 449 scsi_remove_host(shost);
-12
drivers/scsi/isci/probe_roms.c
··· 112 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 115 struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw) 128 116 { 129 117 struct isci_orom *orom = NULL, *data;
-2
drivers/scsi/isci/probe_roms.h
··· 156 156 157 157 struct isci_orom; 158 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 159 struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); 162 160 struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); 163 161
+2 -2
drivers/scsi/isci/request.c
··· 92 92 if (idx == 0) { 93 93 offset = (void *) &ireq->tc->sgl_pair_ab - 94 94 (void *) &ihost->task_context_table[0]; 95 - return ihost->task_context_dma + offset; 95 + return ihost->tc_dma + offset; 96 96 } else if (idx == 1) { 97 97 offset = (void *) &ireq->tc->sgl_pair_cd - 98 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 102 return sci_io_request_get_dma_addr(ireq, &ireq->sg_table[idx - 2]);
+8 -22
drivers/scsi/isci/unsolicited_frame_control.c
··· 57 57 #include "unsolicited_frame_control.h" 58 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 62 struct sci_unsolicited_frame_control *uf_control = &ihost->uf_control; 63 63 struct sci_unsolicited_frame *uf; 64 - u32 buf_len, header_len, i; 65 - dma_addr_t dma; 66 - size_t size; 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]); 64 + dma_addr_t dma = ihost->ufi_dma; 65 + void *virt = ihost->ufi_buf; 66 + int i; 76 67 77 68 /* 78 69 * The Unsolicited Frame buffers are set at the start of the UF 79 70 * memory descriptor entry. The headers and address table will be 80 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 75 * Program the location of the UF header table into the SCU. ··· 81 93 * headers, since we program the UF address table pointers to 82 94 * NULL. 83 95 */ 84 - uf_control->headers.physical_address = dma + buf_len; 85 - uf_control->headers.array = virt + buf_len; 96 + uf_control->headers.physical_address = dma + SCI_UFI_BUF_SIZE; 97 + uf_control->headers.array = virt + SCI_UFI_BUF_SIZE; 86 98 87 99 /* 88 100 * Program the location of the UF address table into the SCU. ··· 91 103 * byte boundary already due to above programming headers being on a 92 104 * 64-bit boundary and headers are on a 64-bytes in size. 93 105 */ 94 - uf_control->address_table.physical_address = dma + buf_len + header_len; 95 - uf_control->address_table.array = virt + buf_len + header_len; 106 + uf_control->address_table.physical_address = dma + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE; 107 + uf_control->address_table.array = virt + SCI_UFI_BUF_SIZE + SCI_UFI_HDR_SIZE; 96 108 uf_control->get = 0; 97 109 98 110 /* ··· 123 135 virt += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; 124 136 dma += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; 125 137 } 126 - 127 - return 0; 128 138 } 129 139 130 140 enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control,
+5 -1
drivers/scsi/isci/unsolicited_frame_control.h
··· 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 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 268 enum sci_status sci_unsolicited_frame_control_get_header( 265 269 struct sci_unsolicited_frame_control *uf_control,