Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 604a3e30 authored by James Bottomley's avatar James Bottomley
Browse files

[SCSI] lpfc: Fix for "command completion for iotax x?? not found"



From: James Smart <James.Smart@emulex.com>

There were scenarios where the error handlers could reuse an iotag
value of an active io.  Remove all possibility of this by
pre-assigning iotag resources to command resources.

Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>

Rejections fixed up and
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 21568f53
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *);
void lpfc_mem_free(struct lpfc_hba *);

void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
+4 −5
Original line number Diff line number Diff line
@@ -235,7 +235,6 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,

	if (geniocb == NULL)
		return 1;
	memset(geniocb, 0, sizeof (struct lpfc_iocbq));

	icmd = &geniocb->iocb;
	icmd->un.genreq64.bdl.ulpIoTag32 = 0;
@@ -279,7 +278,7 @@ lpfc_gen_req(struct lpfc_hba *phba, struct lpfc_dmabuf *bmp,
	geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
	spin_lock_irq(phba->host->host_lock);
	if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) {
		list_add_tail(&geniocb->list, lpfc_iocb_list);
		lpfc_sli_release_iocbq(phba, geniocb);
		spin_unlock_irq(phba->host->host_lock);
		return 1;
	}
@@ -487,7 +486,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
	kfree(inp);
	kfree(bmp);
	spin_lock_irq(phba->host->host_lock);
	list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
	lpfc_sli_release_iocbq(phba, cmdiocb);
	spin_unlock_irq(phba->host->host_lock);
	return;
}
@@ -526,7 +525,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
	kfree(inp);
	kfree(bmp);
	spin_lock_irq(phba->host->host_lock);
	list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
	lpfc_sli_release_iocbq(phba, cmdiocb);
	spin_unlock_irq(phba->host->host_lock);
	return;
}
@@ -735,7 +734,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
	kfree(inp);
	kfree(bmp);
	spin_lock_irq(phba->host->host_lock);
	list_add_tail(&cmdiocb->list, &phba->lpfc_iocb_list);
	lpfc_sli_release_iocbq(phba, cmdiocb);
	spin_unlock_irq(phba->host->host_lock);
	return;
}
+16 −14
Original line number Diff line number Diff line
@@ -122,7 +122,6 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,

	if (elsiocb == NULL)
		return NULL;
	memset(elsiocb, 0, sizeof (struct lpfc_iocbq));
	icmd = &elsiocb->iocb;

	/* fill in BDEs for command */
@@ -133,7 +132,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
		if (pcmd)
			kfree(pcmd);

		list_add_tail(&elsiocb->list, lpfc_iocb_list);
		spin_lock_irq(phba->host->host_lock);
		lpfc_sli_release_iocbq(phba, elsiocb);
		spin_unlock_irq(phba->host->host_lock);
		return NULL;
	}

@@ -150,7 +151,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
				kfree(prsp);
			lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
			kfree(pcmd);
			list_add_tail(&elsiocb->list, lpfc_iocb_list);
			spin_lock_irq(phba->host->host_lock);
			lpfc_sli_release_iocbq(phba, elsiocb);
			spin_unlock_irq(phba->host->host_lock);
			return NULL;
		}
		INIT_LIST_HEAD(&prsp->list);
@@ -164,7 +167,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
	    pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
					     &pbuflist->phys);
	if (pbuflist == 0 || pbuflist->virt == 0) {
		list_add_tail(&elsiocb->list, lpfc_iocb_list);
		spin_lock_irq(phba->host->host_lock);
		lpfc_sli_release_iocbq(phba, elsiocb);
		spin_unlock_irq(phba->host->host_lock);
		lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
		lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
		kfree(pcmd);
@@ -596,10 +601,8 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba)
					spin_unlock_irq(phba->host->host_lock);
					(iocb->iocb_cmpl) (phba, iocb, iocb);
					spin_lock_irq(phba->host->host_lock);
				} else {
					list_add_tail(&iocb->list,
						      &phba->lpfc_iocb_list);
				}
				} else
					lpfc_sli_release_iocbq(phba, iocb);
			}
		}
	}
@@ -1713,7 +1716,7 @@ lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb)
		kfree(buf_ptr);
	}
	spin_lock_irq(phba->host->host_lock);
	list_add_tail(&elsiocb->list, &phba->lpfc_iocb_list);
	lpfc_sli_release_iocbq(phba, elsiocb);
	spin_unlock_irq(phba->host->host_lock);
	return 0;
}
@@ -2929,9 +2932,8 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
			spin_unlock_irq(phba->host->host_lock);
			(piocb->iocb_cmpl) (phba, piocb, piocb);
			spin_lock_irq(phba->host->host_lock);
		} else {
			list_add_tail(&piocb->list, &phba->lpfc_iocb_list);
		}
		} else
			lpfc_sli_release_iocbq(phba, piocb);
	}
	if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) {
		phba->els_tmofunc.expires = jiffies + HZ * timeout;
@@ -2996,7 +2998,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
			spin_lock_irq(phba->host->host_lock);
		}
		else
			list_add_tail(&piocb->list, &phba->lpfc_iocb_list);
			lpfc_sli_release_iocbq(phba, piocb);
	}

	list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
@@ -3033,7 +3035,7 @@ lpfc_els_flush_cmd(struct lpfc_hba * phba)
			spin_lock_irq(phba->host->host_lock);
		}
		else
			list_add_tail(&piocb->list, &phba->lpfc_iocb_list);
			lpfc_sli_release_iocbq(phba, piocb);
	}
	spin_unlock_irq(phba->host->host_lock);
	return;
+3 −4
Original line number Diff line number Diff line
@@ -1445,10 +1445,9 @@ lpfc_no_rpi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
								   iocb, iocb);
						spin_lock_irq(phba->host->
							      host_lock);
					} else {
						list_add_tail(&iocb->list,
							&phba->lpfc_iocb_list);
					}
					} else
						lpfc_sli_release_iocbq(phba,
								       iocb);
				}
			}
			spin_unlock_irq(phba->host->host_lock);
+13 −4
Original line number Diff line number Diff line
@@ -886,7 +886,6 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
			pring->missbufcnt = cnt;
			return cnt;
		}
		memset(iocb, 0, sizeof (struct lpfc_iocbq));
		icmd = &iocb->iocb;

		/* 2 buffers can be posted per command */
@@ -899,7 +898,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
			if (mp1)
				kfree(mp1);
			spin_lock_irq(phba->host->host_lock);
			list_add_tail(&iocb->list, lpfc_iocb_list);
			lpfc_sli_release_iocbq(phba, iocb);
			spin_unlock_irq(phba->host->host_lock);
			pring->missbufcnt = cnt;
			return cnt;
@@ -918,7 +917,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
				lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
				kfree(mp1);
				spin_lock_irq(phba->host->host_lock);
				list_add_tail(&iocb->list, lpfc_iocb_list);
				lpfc_sli_release_iocbq(phba, iocb);
				spin_unlock_irq(phba->host->host_lock);
				pring->missbufcnt = cnt;
				return cnt;
@@ -955,7 +954,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
				kfree(mp2);
				cnt++;
			}
			list_add_tail(&iocb->list, lpfc_iocb_list);
			lpfc_sli_release_iocbq(phba, iocb);
			pring->missbufcnt = cnt;
			spin_unlock_irq(phba->host->host_lock);
			return cnt;
@@ -1328,6 +1327,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
	unsigned long bar0map_len, bar2map_len;
	int error = -ENODEV, retval;
	int i;
	uint16_t iotag;

	if (pci_enable_device(pdev))
		goto out;
@@ -1452,6 +1452,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
		}

		memset(iocbq_entry, 0, sizeof(struct lpfc_iocbq));
		iotag = lpfc_sli_next_iotag(phba, iocbq_entry);
		if (iotag == 0) {
			kfree (iocbq_entry);
			printk(KERN_ERR "%s: failed to allocate IOTAG. "
			       "Unloading driver.\n",
				__FUNCTION__);
			error = -ENOMEM;
			goto out_free_iocbq;
		}
		spin_lock_irq(phba->host->host_lock);
		list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
		phba->total_iocbq_bufs++;
Loading