aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-02-15 16:58:42 -0500
committerDan Williams <dan.j.williams@intel.com>2012-05-17 15:27:12 -0400
commitabec912d71c44bbd642ce12ad98aab76f5a53163 (patch)
treed8967b23a5a4ea8302b43d4db5e0cd09d21d34d3 /drivers
parentae904d15cf344bcb426f63982016f6bacc45825b (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/isci/host.c313
-rw-r--r--drivers/scsi/isci/host.h71
-rw-r--r--drivers/scsi/isci/init.c199
-rw-r--r--drivers/scsi/isci/probe_roms.c12
-rw-r--r--drivers/scsi/isci/probe_roms.h2
-rw-r--r--drivers/scsi/isci/request.c4
-rw-r--r--drivers/scsi/isci/unsolicited_frame_control.c30
-rw-r--r--drivers/scsi/isci/unsolicited_frame_control.h6
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 */
1077static void isci_host_completion_routine(unsigned long data) 1077void 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
1320static 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
1343static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm) 1320static 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
1651static 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
1700static void controller_timeout(unsigned long data) 1628static 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
1838static 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
1859static u8 max_spin_up(struct isci_host *ihost) 1763static 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
2375static enum sci_status sci_user_parameters_set(struct isci_host *ihost, 2279static 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
2428static 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
2332static 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 */
2482int isci_host_init(struct isci_host *ihost) 2375int 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
455struct isci_request *sci_request_by_tag(struct isci_host *ihost, 459struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag);
456 u16 io_tag); 460void sci_controller_power_control_queue_insert(struct isci_host *ihost,
457 461 struct isci_phy *iphy);
458void sci_controller_power_control_queue_insert( 462void 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); 464void sci_controller_link_up(struct isci_host *ihost, struct isci_port *iport,
461 465 struct isci_phy *iphy);
462void sci_controller_power_control_queue_remove( 466void 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); 468void sci_controller_remote_device_stopped(struct isci_host *ihost,
465 469 struct isci_remote_device *idev);
466void sci_controller_link_up(
467 struct isci_host *ihost,
468 struct isci_port *iport,
469 struct isci_phy *iphy);
470
471void sci_controller_link_down(
472 struct isci_host *ihost,
473 struct isci_port *iport,
474 struct isci_phy *iphy);
475
476void sci_controller_remote_device_stopped(
477 struct isci_host *ihost,
478 struct isci_remote_device *idev);
479
480void sci_controller_copy_task_context(
481 struct isci_host *ihost,
482 struct isci_request *ireq);
483
484void sci_controller_register_setup(struct isci_host *ihost);
485 470
486enum sci_status sci_controller_continue_io(struct isci_request *ireq); 471enum sci_status sci_controller_continue_io(struct isci_request *ireq);
487int isci_host_scan_finished(struct Scsi_Host *, unsigned long); 472int 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);
491void isci_tci_free(struct isci_host *ihost, u16 tci); 476void isci_tci_free(struct isci_host *ihost, u16 tci);
492 477
493int isci_host_init(struct isci_host *); 478int isci_host_init(struct isci_host *);
494 479void isci_host_completion_routine(unsigned long data);
495void isci_host_init_controller_names( 480void isci_host_deinit(struct isci_host *);
496 struct isci_host *isci_host, 481void sci_controller_disable_interrupts(struct isci_host *ihost);
497 unsigned int controller_idx);
498
499void isci_host_deinit(
500 struct isci_host *);
501
502void isci_host_port_link_up(
503 struct isci_host *,
504 struct isci_port *,
505 struct isci_phy *);
506int isci_host_dev_found(struct domain_device *);
507
508void isci_host_remote_device_start_complete(
509 struct isci_host *,
510 struct isci_remote_device *,
511 enum sci_status);
512
513void sci_controller_disable_interrupts(
514 struct isci_host *ihost);
515 482
516enum sci_status sci_controller_start_io( 483enum 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
400static 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
423static 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
462static 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
400static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) 511static 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
115enum 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
127struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw) 115struct 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
157struct isci_orom; 157struct isci_orom;
158struct isci_orom *isci_request_oprom(struct pci_dev *pdev); 158struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
159enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
160 struct isci_orom *orom, int scu_index);
161struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw); 159struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw);
162struct isci_orom *isci_get_efi_var(struct pci_dev *pdev); 160struct 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
60int sci_unsolicited_frame_control_construct(struct isci_host *ihost) 60void 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
142enum sci_status sci_unsolicited_frame_control_get_header(struct sci_unsolicited_frame_control *uf_control, 128enum 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
260struct isci_host; 264struct isci_host;
261 265
262int sci_unsolicited_frame_control_construct(struct isci_host *ihost); 266void sci_unsolicited_frame_control_construct(struct isci_host *ihost);
263 267
264enum sci_status sci_unsolicited_frame_control_get_header( 268enum sci_status sci_unsolicited_frame_control_get_header(
265 struct sci_unsolicited_frame_control *uf_control, 269 struct sci_unsolicited_frame_control *uf_control,