aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ipr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r--drivers/scsi/ipr.c104
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 **/
2365static int ipr_map_ucode_buffer(struct ipr_cmnd *ipr_cmd, 2361static 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 **/
2396static 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;
2497out:
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
2492static struct class_device_attribute ipr_update_fw_attr = { 2503static 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,