aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_bsg.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-04-16 11:03:43 -0400
committerJames Bottomley <James.Bottomley@suse.de>2011-05-01 12:10:41 -0400
commitb6e3b9c606f271824bdeb6a40a080452eb086598 (patch)
tree9180f8036f9a729b40b2c8243e241c600d6afa12 /drivers/scsi/lpfc/lpfc_bsg.c
parentc31098cef5e091e22a02ff255f911e0ad71cc393 (diff)
[SCSI] lpfc 8.3.23: BSG additions and fixes
- Fixed the mixed declarations and codes which violate ISO C90 (declarations in subsections that assign at declaration) - Add BSG data transfer size protection in mailbox command pass-through path - Invoke BSG job_done while holding spinlock to fix deadlock - Added support for checking SLI_CONFIG subcommands - Fixed bug in BSG mailbox size check to non-embedded external buffer Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_bsg.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c59
1 files changed, 34 insertions, 25 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 77b2871d96b7..37e2a1272f86 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2426,6 +2426,7 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
2426{ 2426{
2427 struct bsg_job_data *dd_data; 2427 struct bsg_job_data *dd_data;
2428 struct fc_bsg_job *job; 2428 struct fc_bsg_job *job;
2429 struct lpfc_mbx_nembed_cmd *nembed_sge;
2429 uint32_t size; 2430 uint32_t size;
2430 unsigned long flags; 2431 unsigned long flags;
2431 uint8_t *to; 2432 uint8_t *to;
@@ -2469,9 +2470,8 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
2469 memcpy(to, from, size); 2470 memcpy(to, from, size);
2470 } else if ((phba->sli_rev == LPFC_SLI_REV4) && 2471 } else if ((phba->sli_rev == LPFC_SLI_REV4) &&
2471 (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) { 2472 (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
2472 struct lpfc_mbx_nembed_cmd *nembed_sge = 2473 nembed_sge = (struct lpfc_mbx_nembed_cmd *)
2473 (struct lpfc_mbx_nembed_cmd *) 2474 &pmboxq->u.mb.un.varWords[0];
2474 &pmboxq->u.mb.un.varWords[0];
2475 2475
2476 from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. 2476 from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
2477 virt; 2477 virt;
@@ -2496,16 +2496,18 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
2496 job->reply_payload.sg_cnt, 2496 job->reply_payload.sg_cnt,
2497 from, size); 2497 from, size);
2498 job->reply->result = 0; 2498 job->reply->result = 0;
2499 2499 /* need to hold the lock until we set job->dd_data to NULL
2500 * to hold off the timeout handler returning to the mid-layer
2501 * while we are still processing the job.
2502 */
2500 job->dd_data = NULL; 2503 job->dd_data = NULL;
2504 dd_data->context_un.mbox.set_job = NULL;
2505 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2501 job->job_done(job); 2506 job->job_done(job);
2507 } else {
2508 dd_data->context_un.mbox.set_job = NULL;
2509 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2502 } 2510 }
2503 dd_data->context_un.mbox.set_job = NULL;
2504 /* need to hold the lock until we call job done to hold off
2505 * the timeout handler returning to the midlayer while
2506 * we are stillprocessing the job
2507 */
2508 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
2509 2511
2510 kfree(dd_data->context_un.mbox.mb); 2512 kfree(dd_data->context_un.mbox.mb);
2511 mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); 2513 mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);
@@ -2644,6 +2646,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2644 struct ulp_bde64 *rxbpl = NULL; 2646 struct ulp_bde64 *rxbpl = NULL;
2645 struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *) 2647 struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *)
2646 job->request->rqst_data.h_vendor.vendor_cmd; 2648 job->request->rqst_data.h_vendor.vendor_cmd;
2649 struct READ_EVENT_LOG_VAR *rdEventLog;
2650 uint32_t transmit_length, receive_length, mode;
2651 struct lpfc_mbx_nembed_cmd *nembed_sge;
2652 struct mbox_header *header;
2653 struct ulp_bde64 *bde;
2647 uint8_t *ext = NULL; 2654 uint8_t *ext = NULL;
2648 int rc = 0; 2655 int rc = 0;
2649 uint8_t *from; 2656 uint8_t *from;
@@ -2651,9 +2658,16 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2651 /* in case no data is transferred */ 2658 /* in case no data is transferred */
2652 job->reply->reply_payload_rcv_len = 0; 2659 job->reply->reply_payload_rcv_len = 0;
2653 2660
2661 /* sanity check to protect driver */
2662 if (job->reply_payload.payload_len > BSG_MBOX_SIZE ||
2663 job->request_payload.payload_len > BSG_MBOX_SIZE) {
2664 rc = -ERANGE;
2665 goto job_done;
2666 }
2667
2654 /* check if requested extended data lengths are valid */ 2668 /* check if requested extended data lengths are valid */
2655 if ((mbox_req->inExtWLen > MAILBOX_EXT_SIZE) || 2669 if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||
2656 (mbox_req->outExtWLen > MAILBOX_EXT_SIZE)) { 2670 (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) {
2657 rc = -ERANGE; 2671 rc = -ERANGE;
2658 goto job_done; 2672 goto job_done;
2659 } 2673 }
@@ -2744,8 +2758,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2744 * use ours 2758 * use ours
2745 */ 2759 */
2746 if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) { 2760 if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) {
2747 uint32_t transmit_length = pmb->un.varWords[1]; 2761 transmit_length = pmb->un.varWords[1];
2748 uint32_t receive_length = pmb->un.varWords[4]; 2762 receive_length = pmb->un.varWords[4];
2749 /* transmit length cannot be greater than receive length or 2763 /* transmit length cannot be greater than receive length or
2750 * mailbox extension size 2764 * mailbox extension size
2751 */ 2765 */
@@ -2795,10 +2809,9 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2795 from += sizeof(MAILBOX_t); 2809 from += sizeof(MAILBOX_t);
2796 memcpy((uint8_t *)dmp->dma.virt, from, transmit_length); 2810 memcpy((uint8_t *)dmp->dma.virt, from, transmit_length);
2797 } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { 2811 } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) {
2798 struct READ_EVENT_LOG_VAR *rdEventLog = 2812 rdEventLog = &pmb->un.varRdEventLog;
2799 &pmb->un.varRdEventLog ; 2813 receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
2800 uint32_t receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; 2814 mode = bf_get(lpfc_event_log, rdEventLog);
2801 uint32_t mode = bf_get(lpfc_event_log, rdEventLog);
2802 2815
2803 /* receive length cannot be greater than mailbox 2816 /* receive length cannot be greater than mailbox
2804 * extension size 2817 * extension size
@@ -2843,7 +2856,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2843 /* rebuild the command for sli4 using our own buffers 2856 /* rebuild the command for sli4 using our own buffers
2844 * like we do for biu diags 2857 * like we do for biu diags
2845 */ 2858 */
2846 uint32_t receive_length = pmb->un.varWords[2]; 2859 receive_length = pmb->un.varWords[2];
2847 /* receive length cannot be greater than mailbox 2860 /* receive length cannot be greater than mailbox
2848 * extension size 2861 * extension size
2849 */ 2862 */
@@ -2879,8 +2892,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2879 pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); 2892 pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys);
2880 } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && 2893 } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) &&
2881 pmb->un.varUpdateCfg.co) { 2894 pmb->un.varUpdateCfg.co) {
2882 struct ulp_bde64 *bde = 2895 bde = (struct ulp_bde64 *)&pmb->un.varWords[4];
2883 (struct ulp_bde64 *)&pmb->un.varWords[4];
2884 2896
2885 /* bde size cannot be greater than mailbox ext size */ 2897 /* bde size cannot be greater than mailbox ext size */
2886 if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) { 2898 if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) {
@@ -2921,10 +2933,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
2921 memcpy((uint8_t *)dmp->dma.virt, from, 2933 memcpy((uint8_t *)dmp->dma.virt, from,
2922 bde->tus.f.bdeSize); 2934 bde->tus.f.bdeSize);
2923 } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { 2935 } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
2924 struct lpfc_mbx_nembed_cmd *nembed_sge;
2925 struct mbox_header *header;
2926 uint32_t receive_length;
2927
2928 /* rebuild the command for sli4 using our own buffers 2936 /* rebuild the command for sli4 using our own buffers
2929 * like we do for biu diags 2937 * like we do for biu diags
2930 */ 2938 */
@@ -3386,6 +3394,7 @@ no_dd_data:
3386 job->dd_data = NULL; 3394 job->dd_data = NULL;
3387 return rc; 3395 return rc;
3388} 3396}
3397
3389/** 3398/**
3390 * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job 3399 * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
3391 * @job: fc_bsg_job to handle 3400 * @job: fc_bsg_job to handle