diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index ad13ae11e2e6..72b588d65562 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -2351,31 +2351,24 @@ static int ipr_copy_ucode_buffer(struct ipr_sglist *sglist, | |||
2351 | } | 2351 | } |
2352 | 2352 | ||
2353 | /** | 2353 | /** |
2354 | * ipr_map_ucode_buffer - Map a microcode download buffer | 2354 | * ipr_build_ucode_ioadl - Build a microcode download IOADL |
2355 | * @ipr_cmd: ipr command struct | 2355 | * @ipr_cmd: ipr command struct |
2356 | * @sglist: scatter/gather list | 2356 | * @sglist: scatter/gather list |
2357 | * @len: total length of download buffer | ||
2358 | * | 2357 | * |
2359 | * Maps a microcode download scatter/gather list for DMA and | 2358 | * Builds a microcode download IOA data list (IOADL). |
2360 | * builds the IOADL. | ||
2361 | * | 2359 | * |
2362 | * Return value: | ||
2363 | * 0 on success / -EIO on failure | ||
2364 | **/ | 2360 | **/ |
2365 | static int ipr_map_ucode_buffer(struct ipr_cmnd *ipr_cmd, | 2361 | static void ipr_build_ucode_ioadl(struct ipr_cmnd *ipr_cmd, |
2366 | struct ipr_sglist *sglist, int len) | 2362 | struct ipr_sglist *sglist) |
2367 | { | 2363 | { |
2368 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
2369 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | 2364 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; |
2370 | struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; | 2365 | struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; |
2371 | struct scatterlist *scatterlist = sglist->scatterlist; | 2366 | struct scatterlist *scatterlist = sglist->scatterlist; |
2372 | int i; | 2367 | int i; |
2373 | 2368 | ||
2374 | ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev, scatterlist, | 2369 | ipr_cmd->dma_use_sg = sglist->num_dma_sg; |
2375 | sglist->num_sg, DMA_TO_DEVICE); | ||
2376 | |||
2377 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; | 2370 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; |
2378 | ioarcb->write_data_transfer_length = cpu_to_be32(len); | 2371 | ioarcb->write_data_transfer_length = cpu_to_be32(sglist->buffer_len); |
2379 | ioarcb->write_ioadl_len = | 2372 | ioarcb->write_ioadl_len = |
2380 | cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); | 2373 | cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); |
2381 | 2374 | ||
@@ -2386,15 +2379,52 @@ static int ipr_map_ucode_buffer(struct ipr_cmnd *ipr_cmd, | |||
2386 | cpu_to_be32(sg_dma_address(&scatterlist[i])); | 2379 | cpu_to_be32(sg_dma_address(&scatterlist[i])); |
2387 | } | 2380 | } |
2388 | 2381 | ||
2389 | if (likely(ipr_cmd->dma_use_sg)) { | 2382 | ioadl[i-1].flags_and_data_len |= |
2390 | ioadl[i-1].flags_and_data_len |= | 2383 | cpu_to_be32(IPR_IOADL_FLAGS_LAST); |
2391 | cpu_to_be32(IPR_IOADL_FLAGS_LAST); | 2384 | } |
2385 | |||
2386 | /** | ||
2387 | * ipr_update_ioa_ucode - Update IOA's microcode | ||
2388 | * @ioa_cfg: ioa config struct | ||
2389 | * @sglist: scatter/gather list | ||
2390 | * | ||
2391 | * Initiate an adapter reset to update the IOA's microcode | ||
2392 | * | ||
2393 | * Return value: | ||
2394 | * 0 on success / -EIO on failure | ||
2395 | **/ | ||
2396 | static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg, | ||
2397 | struct ipr_sglist *sglist) | ||
2398 | { | ||
2399 | unsigned long lock_flags; | ||
2400 | |||
2401 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
2402 | |||
2403 | if (ioa_cfg->ucode_sglist) { | ||
2404 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2405 | dev_err(&ioa_cfg->pdev->dev, | ||
2406 | "Microcode download already in progress\n"); | ||
2407 | return -EIO; | ||
2392 | } | 2408 | } |
2393 | else { | 2409 | |
2394 | dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n"); | 2410 | sglist->num_dma_sg = pci_map_sg(ioa_cfg->pdev, sglist->scatterlist, |
2411 | sglist->num_sg, DMA_TO_DEVICE); | ||
2412 | |||
2413 | if (!sglist->num_dma_sg) { | ||
2414 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2415 | dev_err(&ioa_cfg->pdev->dev, | ||
2416 | "Failed to map microcode download buffer!\n"); | ||
2395 | return -EIO; | 2417 | return -EIO; |
2396 | } | 2418 | } |
2397 | 2419 | ||
2420 | ioa_cfg->ucode_sglist = sglist; | ||
2421 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NORMAL); | ||
2422 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2423 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | ||
2424 | |||
2425 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
2426 | ioa_cfg->ucode_sglist = NULL; | ||
2427 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2398 | return 0; | 2428 | return 0; |
2399 | } | 2429 | } |
2400 | 2430 | ||
@@ -2417,7 +2447,6 @@ static ssize_t ipr_store_update_fw(struct class_device *class_dev, | |||
2417 | struct ipr_ucode_image_header *image_hdr; | 2447 | struct ipr_ucode_image_header *image_hdr; |
2418 | const struct firmware *fw_entry; | 2448 | const struct firmware *fw_entry; |
2419 | struct ipr_sglist *sglist; | 2449 | struct ipr_sglist *sglist; |
2420 | unsigned long lock_flags; | ||
2421 | char fname[100]; | 2450 | char fname[100]; |
2422 | char *src; | 2451 | char *src; |
2423 | int len, result, dnld_size; | 2452 | int len, result, dnld_size; |
@@ -2458,35 +2487,17 @@ static ssize_t ipr_store_update_fw(struct class_device *class_dev, | |||
2458 | if (result) { | 2487 | if (result) { |
2459 | dev_err(&ioa_cfg->pdev->dev, | 2488 | dev_err(&ioa_cfg->pdev->dev, |
2460 | "Microcode buffer copy to DMA buffer failed\n"); | 2489 | "Microcode buffer copy to DMA buffer failed\n"); |
2461 | ipr_free_ucode_buffer(sglist); | 2490 | goto out; |
2462 | release_firmware(fw_entry); | ||
2463 | return result; | ||
2464 | } | ||
2465 | |||
2466 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
2467 | |||
2468 | if (ioa_cfg->ucode_sglist) { | ||
2469 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2470 | dev_err(&ioa_cfg->pdev->dev, | ||
2471 | "Microcode download already in progress\n"); | ||
2472 | ipr_free_ucode_buffer(sglist); | ||
2473 | release_firmware(fw_entry); | ||
2474 | return -EIO; | ||
2475 | } | 2491 | } |
2476 | 2492 | ||
2477 | ioa_cfg->ucode_sglist = sglist; | 2493 | result = ipr_update_ioa_ucode(ioa_cfg, sglist); |
2478 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NORMAL); | ||
2479 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2480 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | ||
2481 | |||
2482 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
2483 | ioa_cfg->ucode_sglist = NULL; | ||
2484 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
2485 | 2494 | ||
2495 | if (!result) | ||
2496 | result = count; | ||
2497 | out: | ||
2486 | ipr_free_ucode_buffer(sglist); | 2498 | ipr_free_ucode_buffer(sglist); |
2487 | release_firmware(fw_entry); | 2499 | release_firmware(fw_entry); |
2488 | 2500 | return result; | |
2489 | return count; | ||
2490 | } | 2501 | } |
2491 | 2502 | ||
2492 | static struct class_device_attribute ipr_update_fw_attr = { | 2503 | static struct class_device_attribute ipr_update_fw_attr = { |
@@ -5291,12 +5302,7 @@ static int ipr_reset_ucode_download(struct ipr_cmnd *ipr_cmd) | |||
5291 | ipr_cmd->ioarcb.cmd_pkt.cdb[7] = (sglist->buffer_len & 0x00ff00) >> 8; | 5302 | ipr_cmd->ioarcb.cmd_pkt.cdb[7] = (sglist->buffer_len & 0x00ff00) >> 8; |
5292 | ipr_cmd->ioarcb.cmd_pkt.cdb[8] = sglist->buffer_len & 0x0000ff; | 5303 | ipr_cmd->ioarcb.cmd_pkt.cdb[8] = sglist->buffer_len & 0x0000ff; |
5293 | 5304 | ||
5294 | if (ipr_map_ucode_buffer(ipr_cmd, sglist, sglist->buffer_len)) { | 5305 | ipr_build_ucode_ioadl(ipr_cmd, sglist); |
5295 | dev_err(&ioa_cfg->pdev->dev, | ||
5296 | "Failed to map microcode download buffer\n"); | ||
5297 | return IPR_RC_JOB_CONTINUE; | ||
5298 | } | ||
5299 | |||
5300 | ipr_cmd->job_step = ipr_reset_ucode_download_done; | 5306 | ipr_cmd->job_step = ipr_reset_ucode_download_done; |
5301 | 5307 | ||
5302 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, | 5308 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, |