mirror of https://gitee.com/openkylin/linux.git
SCSI misc on 20170503
This update includes the usual round of major driver updates (hisi_sas, ufs, fnic, cxlflash, be2iscsi, ipr, stex). There's also the usual amount of cosmetic and spelling stuff. Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJZClQkAAoJEAVr7HOZEZN4OmkP/j/JJx2ImGzTgil5S8yeSWPY 5Gqb8IK9rCQ+OJgCZYCz3JsLZZnwY4ODZ9tC1lO/3he6VfjIhcEs2/eXbTnEfsZx D3EwWEVR3wYBNZN0d4hQoudVbdCf6UuvsUvM1hDFO7by10qFEs0DqsufccpDlpG/ us96BWf7PgiNzHYSvZIlmsfEDzNDRRg7Dm1NuLOQvXw56zFGsrysCO6Tqg7/ScJm Unz/VlEe1DE7zE9QotsKNCht7xHkmn1vfuva1wqG2wMp7EHf0rKnavRYrWUrxiEy 2ig6GpR7mIHmVHS8PAMNhyS6iNxGQ3e50sAvZdqDlq42P73AEwbrOo5YhgsTJxWT vCpRAzSuHwPOPY3W2Aa1yJ10iOpoPKxXs2xSZuzpcz8XJ3RjHy+l90Y0VT4Jrvzv +dSY1cynshFccZmw2HQanlt1Ly9G3U8xmx8KIbnsIPCdSIQaQQD27H+Ip0YZ0fKt aLmMcQzffma3UP/LPmRAQ45bwx8rLi9M3DWbWOGmSkIRY3etPCXqNuDcC6h5p9TF 4W74oVcELTql/u8ATZNSbdHBsWAg3GATIkAgdqwLTk/CU/0OgGY8epILr3EM2bc6 vVbglwP9DiyVOikTLhVNJdZA97qHjZ1WXNo03eefFTBfPDcUlkZw4j2gufGuNFh2 5vA4C/aSl9uxaLInr3aC =kj7u -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI updates from James Bottomley: "This update includes the usual round of major driver updates (hisi_sas, ufs, fnic, cxlflash, be2iscsi, ipr, stex). There's also the usual amount of cosmetic and spelling stuff" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (155 commits) scsi: qla4xxx: fix spelling mistake: "Tempalate" -> "Template" scsi: stex: make S6flag static scsi: mac_esp: fix to pass correct device identity to free_irq() scsi: aacraid: pci_alloc_consistent() failures on ARM64 scsi: ufs: make ufshcd_get_lists_status() register operation obvious scsi: ufs: use MASK_EE_STATUS scsi: mac_esp: Replace bogus memory barrier with spinlock scsi: fcoe: make fcoe_e_d_tov and fcoe_r_a_tov static scsi: sd_zbc: Do not write lock zones for reset scsi: sd_zbc: Remove superfluous assignments scsi: sd: sd_zbc: Rename sd_zbc_setup_write_cmnd scsi: Improve scsi_get_sense_info_fld scsi: sd: Cleanup sd_done sense data handling scsi: sd: Improve sd_completed_bytes scsi: sd: Fix function descriptions scsi: mpt3sas: remove redundant wmb scsi: mpt: Move scsi_remove_host() out of mptscsih_remove_host() scsi: sg: reset 'res_in_use' after unlinking reserved array scsi: mvumi: remove code handling zero scsi_sg_count(scmd) case scsi: fusion: fix spelling mistake: "Persistancy" -> "Persistency" ...
This commit is contained in:
commit
8d5e72dfdf
|
@ -239,6 +239,11 @@ DK_CXLFLASH_USER_VIRTUAL
|
|||
resource handle that is provided is already referencing provisioned
|
||||
storage. This is reflected by the last LBA being a non-zero value.
|
||||
|
||||
When a LUN is accessible from more than one port, this ioctl will
|
||||
return with the DK_CXLFLASH_ALL_PORTS_ACTIVE return flag set. This
|
||||
provides the user with a hint that I/O can be retried in the event
|
||||
of an I/O error as the LUN can be reached over multiple paths.
|
||||
|
||||
DK_CXLFLASH_VLUN_RESIZE
|
||||
-----------------------
|
||||
This ioctl is responsible for resizing a previously created virtual
|
||||
|
|
|
@ -70,7 +70,7 @@ with the command.
|
|||
scmd is requeued to blk queue.
|
||||
|
||||
- otherwise
|
||||
scsi_eh_scmd_add(scmd, 0) is invoked for the command. See
|
||||
scsi_eh_scmd_add(scmd) is invoked for the command. See
|
||||
[1-3] for details of this function.
|
||||
|
||||
|
||||
|
@ -103,13 +103,14 @@ function
|
|||
eh_timed_out() callback did not handle the command.
|
||||
Step #2 is taken.
|
||||
|
||||
2. If the host supports asynchronous completion (as indicated by the
|
||||
no_async_abort setting in the host template) scsi_abort_command()
|
||||
is invoked to schedule an asynchrous abort. If that fails
|
||||
Step #3 is taken.
|
||||
2. scsi_abort_command() is invoked to schedule an asynchrous abort.
|
||||
Asynchronous abort are not invoked for commands which the
|
||||
SCSI_EH_ABORT_SCHEDULED flag is set (this indicates that the command
|
||||
already had been aborted once, and this is a retry which failed),
|
||||
or when the EH deadline is expired. In these case Step #3 is taken.
|
||||
|
||||
2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the
|
||||
command. See [1-3] for more information.
|
||||
3. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the
|
||||
command. See [1-4] for more information.
|
||||
|
||||
[1-3] Asynchronous command aborts
|
||||
|
||||
|
@ -124,16 +125,13 @@ function
|
|||
|
||||
scmds enter EH via scsi_eh_scmd_add(), which does the following.
|
||||
|
||||
1. Turns on scmd->eh_eflags as requested. It's 0 for error
|
||||
completions and SCSI_EH_CANCEL_CMD for timeouts.
|
||||
1. Links scmd->eh_entry to shost->eh_cmd_q
|
||||
|
||||
2. Links scmd->eh_entry to shost->eh_cmd_q
|
||||
2. Sets SHOST_RECOVERY bit in shost->shost_state
|
||||
|
||||
3. Sets SHOST_RECOVERY bit in shost->shost_state
|
||||
3. Increments shost->host_failed
|
||||
|
||||
4. Increments shost->host_failed
|
||||
|
||||
5. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed
|
||||
4. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed
|
||||
|
||||
As can be seen above, once any scmd is added to shost->eh_cmd_q,
|
||||
SHOST_RECOVERY shost_state bit is turned on. This prevents any new
|
||||
|
@ -249,7 +247,6 @@ scmd->allowed.
|
|||
|
||||
1. Error completion / time out
|
||||
ACTION: scsi_eh_scmd_add() is invoked for scmd
|
||||
- set scmd->eh_eflags
|
||||
- add scmd to shost->eh_cmd_q
|
||||
- set SHOST_RECOVERY
|
||||
- shost->host_failed++
|
||||
|
@ -263,7 +260,6 @@ scmd->allowed.
|
|||
|
||||
3. scmd recovered
|
||||
ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
|
||||
- clear scmd->eh_eflags
|
||||
- scsi_setup_cmd_retry()
|
||||
- move from local eh_work_q to local eh_done_q
|
||||
LOCKING: none
|
||||
|
@ -456,8 +452,6 @@ except for #1 must be implemented by eh_strategy_handler().
|
|||
|
||||
- shost->host_failed is zero.
|
||||
|
||||
- Each scmd's eh_eflags field is cleared.
|
||||
|
||||
- Each scmd is in such a state that scsi_setup_cmd_retry() on the
|
||||
scmd doesn't make any difference.
|
||||
|
||||
|
|
|
@ -10079,7 +10079,6 @@ F: drivers/scsi/pmcraid.*
|
|||
PMC SIERRA PM8001 DRIVER
|
||||
M: Jack Wang <jinpu.wang@profitbricks.com>
|
||||
M: lindar_liu@usish.com
|
||||
L: pmchba@pmcs.com
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/scsi/pm8001/
|
||||
|
|
|
@ -7396,7 +7396,7 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
|
|||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: No Persistancy: "
|
||||
"SAS Device Status Change: No Persistency: "
|
||||
"id=%d channel=%d", id, channel);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
|
||||
|
|
|
@ -1329,7 +1329,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
WQ_MEM_RECLAIM);
|
||||
if (!ioc->fc_rescan_work_q) {
|
||||
error = -ENOMEM;
|
||||
goto out_mptfc_probe;
|
||||
goto out_mptfc_host;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1351,6 +1351,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
|
||||
return 0;
|
||||
|
||||
out_mptfc_host:
|
||||
scsi_remove_host(sh);
|
||||
|
||||
out_mptfc_probe:
|
||||
|
||||
mptscsih_remove(pdev);
|
||||
|
@ -1530,6 +1533,8 @@ static void mptfc_remove(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
scsi_remove_host(ioc->sh);
|
||||
|
||||
mptscsih_remove(pdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -1176,8 +1176,6 @@ mptscsih_remove(struct pci_dev *pdev)
|
|||
MPT_SCSI_HOST *hd;
|
||||
int sz1;
|
||||
|
||||
scsi_remove_host(host);
|
||||
|
||||
if((hd = shost_priv(host)) == NULL)
|
||||
return;
|
||||
|
||||
|
|
|
@ -1548,11 +1548,19 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
return error;
|
||||
}
|
||||
|
||||
static void mptspi_remove(struct pci_dev *pdev)
|
||||
{
|
||||
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
||||
|
||||
scsi_remove_host(ioc->sh);
|
||||
mptscsih_remove(pdev);
|
||||
}
|
||||
|
||||
static struct pci_driver mptspi_driver = {
|
||||
.name = "mptspi",
|
||||
.id_table = mptspi_pci_table,
|
||||
.probe = mptspi_probe,
|
||||
.remove = mptscsih_remove,
|
||||
.remove = mptspi_remove,
|
||||
.shutdown = mptscsih_shutdown,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mptscsih_suspend,
|
||||
|
|
|
@ -148,7 +148,7 @@ enclosure_register(struct device *dev, const char *name, int components,
|
|||
for (i = 0; i < components; i++) {
|
||||
edev->component[i].number = -1;
|
||||
edev->component[i].slot = -1;
|
||||
edev->component[i].power_status = 1;
|
||||
edev->component[i].power_status = -1;
|
||||
}
|
||||
|
||||
mutex_lock(&container_list_lock);
|
||||
|
@ -594,6 +594,11 @@ static ssize_t get_component_power_status(struct device *cdev,
|
|||
|
||||
if (edev->cb->get_power_status)
|
||||
edev->cb->get_power_status(edev, ecomp);
|
||||
|
||||
/* If still uninitialized, the callback failed or does not exist. */
|
||||
if (ecomp->power_status == -1)
|
||||
return (edev->cb->get_power_status) ? -EIO : -ENOTTY;
|
||||
|
||||
return snprintf(buf, 40, "%s\n", ecomp->power_status ? "on" : "off");
|
||||
}
|
||||
|
||||
|
|
|
@ -3009,7 +3009,7 @@ static int blogic_hostreset(struct scsi_cmnd *SCpnt)
|
|||
|
||||
spin_lock_irq(SCpnt->device->host->host_lock);
|
||||
|
||||
blogic_inc_count(&stats->adatper_reset_req);
|
||||
blogic_inc_count(&stats->adapter_reset_req);
|
||||
|
||||
rc = blogic_resetadapter(adapter, false);
|
||||
spin_unlock_irq(SCpnt->device->host->host_lock);
|
||||
|
@ -3560,8 +3560,16 @@ Target Requested Completed Requested Completed Requested Completed\n\
|
|||
struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
|
||||
if (!tgt_flags->tgt_exists)
|
||||
continue;
|
||||
seq_printf(m, "\
|
||||
%2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", tgt, tgt_stats[tgt].aborts_request, tgt_stats[tgt].aborts_tried, tgt_stats[tgt].aborts_done, tgt_stats[tgt].bdr_request, tgt_stats[tgt].bdr_tried, tgt_stats[tgt].bdr_done, tgt_stats[tgt].adatper_reset_req, tgt_stats[tgt].adapter_reset_attempt, tgt_stats[tgt].adapter_reset_done);
|
||||
seq_printf(m, " %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n",
|
||||
tgt, tgt_stats[tgt].aborts_request,
|
||||
tgt_stats[tgt].aborts_tried,
|
||||
tgt_stats[tgt].aborts_done,
|
||||
tgt_stats[tgt].bdr_request,
|
||||
tgt_stats[tgt].bdr_tried,
|
||||
tgt_stats[tgt].bdr_done,
|
||||
tgt_stats[tgt].adapter_reset_req,
|
||||
tgt_stats[tgt].adapter_reset_attempt,
|
||||
tgt_stats[tgt].adapter_reset_done);
|
||||
}
|
||||
seq_printf(m, "\nExternal Host Adapter Resets: %d\n", adapter->ext_resets);
|
||||
seq_printf(m, "Host Adapter Internal Errors: %d\n", adapter->adapter_intern_errors);
|
||||
|
|
|
@ -935,7 +935,7 @@ struct blogic_tgt_stats {
|
|||
unsigned short bdr_request;
|
||||
unsigned short bdr_tried;
|
||||
unsigned short bdr_done;
|
||||
unsigned short adatper_reset_req;
|
||||
unsigned short adapter_reset_req;
|
||||
unsigned short adapter_reset_attempt;
|
||||
unsigned short adapter_reset_done;
|
||||
};
|
||||
|
|
|
@ -1678,8 +1678,8 @@ int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target)
|
|||
sizeof(struct sgentry) + sizeof(struct sgentry64);
|
||||
datasize = sizeof(struct aac_ciss_identify_pd);
|
||||
|
||||
identify_resp = pci_alloc_consistent(dev->pdev, datasize, &addr);
|
||||
|
||||
identify_resp = dma_alloc_coherent(&dev->pdev->dev, datasize, &addr,
|
||||
GFP_KERNEL);
|
||||
if (!identify_resp)
|
||||
goto fib_free_ptr;
|
||||
|
||||
|
@ -1720,7 +1720,7 @@ int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target)
|
|||
dev->hba_map[bus][target].qd_limit =
|
||||
identify_resp->current_queue_depth_limit;
|
||||
|
||||
pci_free_consistent(dev->pdev, datasize, (void *)identify_resp, addr);
|
||||
dma_free_coherent(&dev->pdev->dev, datasize, identify_resp, addr);
|
||||
|
||||
aac_fib_complete(fibptr);
|
||||
|
||||
|
@ -1814,9 +1814,8 @@ int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan)
|
|||
datasize = sizeof(struct aac_ciss_phys_luns_resp)
|
||||
+ (AAC_MAX_TARGETS - 1) * sizeof(struct _ciss_lun);
|
||||
|
||||
phys_luns = (struct aac_ciss_phys_luns_resp *) pci_alloc_consistent(
|
||||
dev->pdev, datasize, &addr);
|
||||
|
||||
phys_luns = dma_alloc_coherent(&dev->pdev->dev, datasize, &addr,
|
||||
GFP_KERNEL);
|
||||
if (phys_luns == NULL) {
|
||||
rcode = -ENOMEM;
|
||||
goto err_out;
|
||||
|
@ -1861,7 +1860,7 @@ int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan)
|
|||
aac_update_hba_map(dev, phys_luns, rescan);
|
||||
}
|
||||
|
||||
pci_free_consistent(dev->pdev, datasize, (void *) phys_luns, addr);
|
||||
dma_free_coherent(&dev->pdev->dev, datasize, phys_luns, addr);
|
||||
err_out:
|
||||
return rcode;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
kfib = pci_alloc_consistent(dev->pdev, size, &daddr);
|
||||
kfib = dma_alloc_coherent(&dev->pdev->dev, size, &daddr,
|
||||
GFP_KERNEL);
|
||||
if (!kfib) {
|
||||
retval = -ENOMEM;
|
||||
goto cleanup;
|
||||
|
@ -160,7 +161,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
|
|||
retval = -EFAULT;
|
||||
cleanup:
|
||||
if (hw_fib) {
|
||||
pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
|
||||
dma_free_coherent(&dev->pdev->dev, size, kfib,
|
||||
fibptr->hw_fib_pa);
|
||||
fibptr->hw_fib_pa = hw_fib_pa;
|
||||
fibptr->hw_fib_va = hw_fib;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
|
|||
size = fibsize + aac_init_size + commsize + commalign +
|
||||
printfbufsiz + host_rrq_size;
|
||||
|
||||
base = pci_alloc_consistent(dev->pdev, size, &phys);
|
||||
|
||||
base = dma_alloc_coherent(&dev->pdev->dev, size, &phys, GFP_KERNEL);
|
||||
if (base == NULL) {
|
||||
printk(KERN_ERR "aacraid: unable to create mapping.\n");
|
||||
return 0;
|
||||
|
|
|
@ -73,13 +73,13 @@ static int fib_map_alloc(struct aac_dev *dev)
|
|||
}
|
||||
|
||||
dprintk((KERN_INFO
|
||||
"allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
|
||||
dev->pdev, dev->max_cmd_size, dev->scsi_host_ptr->can_queue,
|
||||
"allocate hardware fibs dma_alloc_coherent(%p, %d * (%d + %d), %p)\n",
|
||||
&dev->pdev->dev, dev->max_cmd_size, dev->scsi_host_ptr->can_queue,
|
||||
AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
|
||||
dev->hw_fib_va = pci_alloc_consistent(dev->pdev,
|
||||
dev->hw_fib_va = dma_alloc_coherent(&dev->pdev->dev,
|
||||
(dev->max_cmd_size + sizeof(struct aac_fib_xporthdr))
|
||||
* (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1),
|
||||
&dev->hw_fib_pa);
|
||||
&dev->hw_fib_pa, GFP_KERNEL);
|
||||
if (dev->hw_fib_va == NULL)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
|
@ -106,8 +106,8 @@ void aac_fib_map_free(struct aac_dev *dev)
|
|||
fib_size = dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
|
||||
alloc_size = fib_size * num_fibs + ALIGN32 - 1;
|
||||
|
||||
pci_free_consistent(dev->pdev, alloc_size, dev->hw_fib_va,
|
||||
dev->hw_fib_pa);
|
||||
dma_free_coherent(&dev->pdev->dev, alloc_size, dev->hw_fib_va,
|
||||
dev->hw_fib_pa);
|
||||
|
||||
dev->hw_fib_va = NULL;
|
||||
dev->hw_fib_pa = 0;
|
||||
|
@ -1571,7 +1571,8 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
|
|||
* case.
|
||||
*/
|
||||
aac_fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
|
||||
dma_free_coherent(&aac->pdev->dev, aac->comm_size, aac->comm_addr,
|
||||
aac->comm_phys);
|
||||
aac->comm_addr = NULL;
|
||||
aac->comm_phys = 0;
|
||||
kfree(aac->queues);
|
||||
|
@ -2319,7 +2320,8 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str,
|
|||
if (!fibptr)
|
||||
goto out;
|
||||
|
||||
dma_buf = pci_alloc_consistent(dev->pdev, datasize, &addr);
|
||||
dma_buf = dma_alloc_coherent(&dev->pdev->dev, datasize, &addr,
|
||||
GFP_KERNEL);
|
||||
if (!dma_buf)
|
||||
goto fib_free_out;
|
||||
|
||||
|
@ -2354,7 +2356,7 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str,
|
|||
ret = aac_fib_send(ScsiPortCommand64, fibptr, sizeof(struct aac_srb),
|
||||
FsaNormal, 1, 1, NULL, NULL);
|
||||
|
||||
pci_free_consistent(dev->pdev, datasize, (void *)dma_buf, addr);
|
||||
dma_free_coherent(&dev->pdev->dev, datasize, dma_buf, addr);
|
||||
|
||||
/*
|
||||
* Do not set XferState to zero unless
|
||||
|
|
|
@ -1592,8 +1592,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
out_unmap:
|
||||
aac_fib_map_free(aac);
|
||||
if (aac->comm_addr)
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
|
||||
aac->comm_phys);
|
||||
dma_free_coherent(&aac->pdev->dev, aac->comm_size,
|
||||
aac->comm_addr, aac->comm_phys);
|
||||
kfree(aac->queues);
|
||||
aac_adapter_ioremap(aac, 0);
|
||||
kfree(aac->fibs);
|
||||
|
@ -1729,8 +1729,8 @@ static void aac_remove_one(struct pci_dev *pdev)
|
|||
|
||||
__aac_shutdown(aac);
|
||||
aac_fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
|
||||
aac->comm_phys);
|
||||
dma_free_coherent(&aac->pdev->dev, aac->comm_size, aac->comm_addr,
|
||||
aac->comm_phys);
|
||||
kfree(aac->queues);
|
||||
|
||||
aac_adapter_ioremap(aac, 0);
|
||||
|
|
|
@ -355,14 +355,16 @@ static int aac_rx_check_health(struct aac_dev *dev)
|
|||
|
||||
if (likely((status & 0xFF000000L) == 0xBC000000L))
|
||||
return (status >> 16) & 0xFF;
|
||||
buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
|
||||
buffer = dma_alloc_coherent(&dev->pdev->dev, 512, &baddr,
|
||||
GFP_KERNEL);
|
||||
ret = -2;
|
||||
if (unlikely(buffer == NULL))
|
||||
return ret;
|
||||
post = pci_alloc_consistent(dev->pdev,
|
||||
sizeof(struct POSTSTATUS), &paddr);
|
||||
post = dma_alloc_coherent(&dev->pdev->dev,
|
||||
sizeof(struct POSTSTATUS), &paddr,
|
||||
GFP_KERNEL);
|
||||
if (unlikely(post == NULL)) {
|
||||
pci_free_consistent(dev->pdev, 512, buffer, baddr);
|
||||
dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr);
|
||||
return ret;
|
||||
}
|
||||
memset(buffer, 0, 512);
|
||||
|
@ -371,13 +373,13 @@ static int aac_rx_check_health(struct aac_dev *dev)
|
|||
rx_writel(dev, MUnit.IMRx[0], paddr);
|
||||
rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
|
||||
post, paddr);
|
||||
dma_free_coherent(&dev->pdev->dev, sizeof(struct POSTSTATUS),
|
||||
post, paddr);
|
||||
if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
|
||||
ret = (hex_to_bin(buffer[2]) << 4) +
|
||||
hex_to_bin(buffer[3]);
|
||||
}
|
||||
pci_free_consistent(dev->pdev, 512, buffer, baddr);
|
||||
dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -6291,18 +6291,17 @@ static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
|
|||
static uchar
|
||||
AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
|
||||
{
|
||||
EXT_MSG sdtr_buf;
|
||||
uchar sdtr_period_index;
|
||||
PortAddr iop_base;
|
||||
|
||||
iop_base = asc_dvc->iop_base;
|
||||
sdtr_buf.msg_type = EXTENDED_MESSAGE;
|
||||
sdtr_buf.msg_len = MS_SDTR_LEN;
|
||||
sdtr_buf.msg_req = EXTENDED_SDTR;
|
||||
sdtr_buf.xfer_period = sdtr_period;
|
||||
PortAddr iop_base = asc_dvc->iop_base;
|
||||
uchar sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
|
||||
EXT_MSG sdtr_buf = {
|
||||
.msg_type = EXTENDED_MESSAGE,
|
||||
.msg_len = MS_SDTR_LEN,
|
||||
.msg_req = EXTENDED_SDTR,
|
||||
.xfer_period = sdtr_period,
|
||||
.req_ack_offset = sdtr_offset,
|
||||
};
|
||||
sdtr_offset &= ASC_SYN_MAX_OFFSET;
|
||||
sdtr_buf.req_ack_offset = sdtr_offset;
|
||||
sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
|
||||
|
||||
if (sdtr_period_index <= asc_dvc->max_sdtr_index) {
|
||||
AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG,
|
||||
(uchar *)&sdtr_buf,
|
||||
|
|
|
@ -601,8 +601,8 @@ static const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table);
|
|||
#define STA 0x08
|
||||
#define DPR 0x01
|
||||
|
||||
static int ahc_9005_subdevinfo_valid(uint16_t vendor, uint16_t device,
|
||||
uint16_t subvendor, uint16_t subdevice);
|
||||
static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
|
||||
uint16_t subdevice, uint16_t subvendor);
|
||||
static int ahc_ext_scbram_present(struct ahc_softc *ahc);
|
||||
static void ahc_scbram_config(struct ahc_softc *ahc, int enable,
|
||||
int pcheck, int fast, int large);
|
||||
|
|
|
@ -703,7 +703,6 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha)
|
|||
{
|
||||
int err;
|
||||
|
||||
scsi_remove_host(asd_ha->sas_ha.core.shost);
|
||||
err = sas_unregister_ha(&asd_ha->sas_ha);
|
||||
|
||||
sas_remove_host(asd_ha->sas_ha.core.shost);
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#ifndef BEISCSI_H
|
||||
|
@ -154,7 +151,6 @@ struct be_ctrl_info {
|
|||
#define PAGE_SHIFT_4K 12
|
||||
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
|
||||
#define mcc_timeout 120000 /* 12s timeout */
|
||||
#define BEISCSI_LOGOUT_SYNC_DELAY 250
|
||||
|
||||
/* Returns number of pages spanned by the data starting at the given addr */
|
||||
#define PAGES_4K_SPANNED(_address, size) \
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#include <scsi/iscsi_proto.h>
|
||||
|
@ -246,6 +243,12 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba,
|
|||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!tag || tag > MAX_MCC_CMD) {
|
||||
__beiscsi_log(phba, KERN_ERR,
|
||||
"BC_%d : invalid tag %u\n", tag);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (beiscsi_hba_in_error(phba)) {
|
||||
clear_bit(MCC_TAG_STATE_RUNNING,
|
||||
&phba->ctrl.ptag_state[tag].tag_state);
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#ifndef BEISCSI_CMDS_H
|
||||
|
@ -1145,24 +1142,49 @@ struct tcp_connect_and_offload_out {
|
|||
#define DB_DEF_PDU_EVENT_SHIFT 15
|
||||
#define DB_DEF_PDU_CQPROC_SHIFT 16
|
||||
|
||||
struct dmsg_cqe {
|
||||
u32 dw[4];
|
||||
struct be_invalidate_connection_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 session_handle;
|
||||
u16 cid;
|
||||
u16 unused;
|
||||
#define BE_CLEANUP_TYPE_INVALIDATE 0x8001
|
||||
#define BE_CLEANUP_TYPE_ISSUE_TCP_RST 0x8002
|
||||
u16 cleanup_type;
|
||||
u16 save_cfg;
|
||||
} __packed;
|
||||
|
||||
struct tcp_upload_params_in {
|
||||
struct be_invalidate_connection_params_out {
|
||||
u32 session_handle;
|
||||
u16 cid;
|
||||
u16 unused;
|
||||
} __packed;
|
||||
|
||||
union be_invalidate_connection_params {
|
||||
struct be_invalidate_connection_params_in req;
|
||||
struct be_invalidate_connection_params_out resp;
|
||||
} __packed;
|
||||
|
||||
struct be_tcp_upload_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u16 id;
|
||||
#define BE_UPLOAD_TYPE_GRACEFUL 1
|
||||
/* abortive upload with reset */
|
||||
#define BE_UPLOAD_TYPE_ABORT_RESET 2
|
||||
/* abortive upload without reset */
|
||||
#define BE_UPLOAD_TYPE_ABORT 3
|
||||
/* abortive upload with reset, sequence number by driver */
|
||||
#define BE_UPLOAD_TYPE_ABORT_WITH_SEQ 4
|
||||
u16 upload_type;
|
||||
u32 reset_seq;
|
||||
} __packed;
|
||||
|
||||
struct tcp_upload_params_out {
|
||||
struct be_tcp_upload_params_out {
|
||||
u32 dw[32];
|
||||
} __packed;
|
||||
|
||||
union tcp_upload_params {
|
||||
struct tcp_upload_params_in request;
|
||||
struct tcp_upload_params_out response;
|
||||
union be_tcp_upload_params {
|
||||
struct be_tcp_upload_params_in request;
|
||||
struct be_tcp_upload_params_out response;
|
||||
} __packed;
|
||||
|
||||
struct be_ulp_fw_cfg {
|
||||
|
@ -1243,10 +1265,7 @@ struct be_cmd_get_port_name {
|
|||
#define OPCODE_COMMON_WRITE_FLASH 96
|
||||
#define OPCODE_COMMON_READ_FLASH 97
|
||||
|
||||
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
|
||||
#define CMD_ISCSI_COMMAND_INVALIDATE 1
|
||||
#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001
|
||||
#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002
|
||||
|
||||
#define INI_WR_CMD 1 /* Initiator write command */
|
||||
#define INI_TMF_CMD 2 /* Initiator TMF command */
|
||||
|
@ -1269,27 +1288,6 @@ struct be_cmd_get_port_name {
|
|||
* preparedby
|
||||
* driver should not be touched
|
||||
*/
|
||||
/* --- CMD_CHUTE_TYPE --- */
|
||||
#define CMD_CONNECTION_CHUTE_0 1
|
||||
#define CMD_CONNECTION_CHUTE_1 2
|
||||
#define CMD_CONNECTION_CHUTE_2 3
|
||||
|
||||
#define EQ_MAJOR_CODE_COMPLETION 0
|
||||
|
||||
#define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0
|
||||
#define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1
|
||||
|
||||
/* --- CONNECTION_UPLOAD_PARAMS --- */
|
||||
/* These parameters are used to define the type of upload desired. */
|
||||
#define CONNECTION_UPLOAD_GRACEFUL 1 /* Graceful upload */
|
||||
#define CONNECTION_UPLOAD_ABORT_RESET 2 /* Abortive upload with
|
||||
* reset
|
||||
*/
|
||||
#define CONNECTION_UPLOAD_ABORT 3 /* Abortive upload without
|
||||
* reset
|
||||
*/
|
||||
#define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset,
|
||||
* sequence number by driver */
|
||||
|
||||
/* Returns the number of items in the field array. */
|
||||
#define BE_NUMBER_OF_FIELD(_type_, _field_) \
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#include <scsi/libiscsi.h>
|
||||
|
@ -1263,31 +1258,58 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba)
|
|||
}
|
||||
|
||||
/**
|
||||
* beiscsi_close_conn - Upload the connection
|
||||
* beiscsi_conn_close - Invalidate and upload connection
|
||||
* @ep: The iscsi endpoint
|
||||
* @flag: The type of connection closure
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
|
||||
static int beiscsi_conn_close(struct beiscsi_endpoint *beiscsi_ep)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int tag;
|
||||
struct beiscsi_hba *phba = beiscsi_ep->phba;
|
||||
unsigned int tag, attempts;
|
||||
int ret;
|
||||
|
||||
tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag);
|
||||
if (!tag) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : upload failed for cid 0x%x\n",
|
||||
beiscsi_ep->ep_cid);
|
||||
|
||||
ret = -EAGAIN;
|
||||
/**
|
||||
* Without successfully invalidating and uploading connection
|
||||
* driver can't reuse the CID so attempt more than once.
|
||||
*/
|
||||
attempts = 0;
|
||||
while (attempts++ < 3) {
|
||||
tag = beiscsi_invalidate_cxn(phba, beiscsi_ep);
|
||||
if (tag) {
|
||||
ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
|
||||
if (!ret)
|
||||
break;
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : invalidate conn failed cid %d\n",
|
||||
beiscsi_ep->ep_cid);
|
||||
}
|
||||
}
|
||||
|
||||
ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
|
||||
|
||||
/* Flush the CQ entries */
|
||||
/* wait for all completions to arrive, then process them */
|
||||
msleep(250);
|
||||
/* flush CQ entries */
|
||||
beiscsi_flush_cq(phba);
|
||||
|
||||
return ret;
|
||||
if (attempts > 3)
|
||||
return -1;
|
||||
|
||||
attempts = 0;
|
||||
while (attempts++ < 3) {
|
||||
tag = beiscsi_upload_cxn(phba, beiscsi_ep);
|
||||
if (tag) {
|
||||
ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
|
||||
if (!ret)
|
||||
break;
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : upload conn failed cid %d\n",
|
||||
beiscsi_ep->ep_cid);
|
||||
}
|
||||
}
|
||||
if (attempts > 3)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1298,12 +1320,9 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
|
|||
*/
|
||||
void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
|
||||
{
|
||||
struct beiscsi_conn *beiscsi_conn;
|
||||
struct beiscsi_endpoint *beiscsi_ep;
|
||||
struct beiscsi_conn *beiscsi_conn;
|
||||
struct beiscsi_hba *phba;
|
||||
unsigned int tag;
|
||||
uint8_t mgmt_invalidate_flag, tcp_upload_flag;
|
||||
unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
|
||||
uint16_t cri_index;
|
||||
|
||||
beiscsi_ep = ep->dd_data;
|
||||
|
@ -1324,39 +1343,27 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
|
|||
if (beiscsi_ep->conn) {
|
||||
beiscsi_conn = beiscsi_ep->conn;
|
||||
iscsi_suspend_queue(beiscsi_conn->conn);
|
||||
mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE;
|
||||
tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL;
|
||||
} else {
|
||||
mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE;
|
||||
tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
|
||||
}
|
||||
|
||||
if (!beiscsi_hba_is_online(phba)) {
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : HBA in error 0x%lx\n", phba->state);
|
||||
goto free_ep;
|
||||
} else {
|
||||
/**
|
||||
* Make CID available even if close fails.
|
||||
* If not freed, FW might fail open using the CID.
|
||||
*/
|
||||
if (beiscsi_conn_close(beiscsi_ep) < 0)
|
||||
__beiscsi_log(phba, KERN_ERR,
|
||||
"BS_%d : close conn failed cid %d\n",
|
||||
beiscsi_ep->ep_cid);
|
||||
}
|
||||
|
||||
tag = mgmt_invalidate_connection(phba, beiscsi_ep,
|
||||
beiscsi_ep->ep_cid,
|
||||
mgmt_invalidate_flag,
|
||||
savecfg_flag);
|
||||
if (!tag) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
|
||||
"BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
|
||||
beiscsi_ep->ep_cid);
|
||||
}
|
||||
|
||||
beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
|
||||
beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
|
||||
free_ep:
|
||||
msleep(BEISCSI_LOGOUT_SYNC_DELAY);
|
||||
beiscsi_free_ep(beiscsi_ep);
|
||||
if (!phba->conn_table[cri_index])
|
||||
__beiscsi_log(phba, KERN_ERR,
|
||||
"BS_%d : conn_table empty at %u: cid %u\n",
|
||||
cri_index,
|
||||
beiscsi_ep->ep_cid);
|
||||
"BS_%d : conn_table empty at %u: cid %u\n",
|
||||
cri_index, beiscsi_ep->ep_cid);
|
||||
phba->conn_table[cri_index] = NULL;
|
||||
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
|
||||
}
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Avago Technologies
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#ifndef _BE_ISCSI_
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#include <linux/reboot.h>
|
||||
|
@ -337,7 +332,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
|
|||
inv_tbl->task[nents] = task;
|
||||
nents++;
|
||||
}
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
spin_unlock(&session->back_lock);
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
|
||||
rc = SUCCESS;
|
||||
|
@ -636,7 +631,6 @@ static void beiscsi_get_params(struct beiscsi_hba *phba)
|
|||
(total_cid_count +
|
||||
BE2_TMFS + BE2_NOPOUT_REQ));
|
||||
phba->params.cxns_per_ctrl = total_cid_count;
|
||||
phba->params.asyncpdus_per_ctrl = total_cid_count;
|
||||
phba->params.icds_per_ctrl = total_icd_count;
|
||||
phba->params.num_sge_per_io = BE2_SGE;
|
||||
phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
|
||||
|
@ -802,12 +796,12 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
|
|||
struct pci_dev *pcidev = phba->pcidev;
|
||||
struct hwi_controller *phwi_ctrlr;
|
||||
struct hwi_context_memory *phwi_context;
|
||||
int ret, msix_vec, i, j;
|
||||
int ret, i, j;
|
||||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
phwi_context = phwi_ctrlr->phwi_ctxt;
|
||||
|
||||
if (phba->msix_enabled) {
|
||||
if (pcidev->msix_enabled) {
|
||||
for (i = 0; i < phba->num_cpus; i++) {
|
||||
phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME,
|
||||
GFP_KERNEL);
|
||||
|
@ -818,9 +812,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
|
|||
|
||||
sprintf(phba->msi_name[i], "beiscsi_%02x_%02x",
|
||||
phba->shost->host_no, i);
|
||||
msix_vec = phba->msix_entries[i].vector;
|
||||
ret = request_irq(msix_vec, be_isr_msix, 0,
|
||||
phba->msi_name[i],
|
||||
ret = request_irq(pci_irq_vector(pcidev, i),
|
||||
be_isr_msix, 0, phba->msi_name[i],
|
||||
&phwi_context->be_eq[i]);
|
||||
if (ret) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
|
||||
|
@ -838,9 +831,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
|
|||
}
|
||||
sprintf(phba->msi_name[i], "beiscsi_mcc_%02x",
|
||||
phba->shost->host_no);
|
||||
msix_vec = phba->msix_entries[i].vector;
|
||||
ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i],
|
||||
&phwi_context->be_eq[i]);
|
||||
ret = request_irq(pci_irq_vector(pcidev, i), be_isr_mcc, 0,
|
||||
phba->msi_name[i], &phwi_context->be_eq[i]);
|
||||
if (ret) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT ,
|
||||
"BM_%d : beiscsi_init_irqs-"
|
||||
|
@ -862,9 +854,8 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
|
|||
return 0;
|
||||
free_msix_irqs:
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
free_irq(pci_irq_vector(pcidev, i), &phwi_context->be_eq[j]);
|
||||
kfree(phba->msi_name[j]);
|
||||
msix_vec = phba->msix_entries[j].vector;
|
||||
free_irq(msix_vec, &phwi_context->be_eq[j]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1454,30 +1445,45 @@ static inline void
|
|||
beiscsi_hdl_put_handle(struct hd_async_context *pasync_ctx,
|
||||
struct hd_async_handle *pasync_handle)
|
||||
{
|
||||
if (pasync_handle->is_header) {
|
||||
list_add_tail(&pasync_handle->link,
|
||||
&pasync_ctx->async_header.free_list);
|
||||
pasync_ctx->async_header.free_entries++;
|
||||
} else {
|
||||
list_add_tail(&pasync_handle->link,
|
||||
&pasync_ctx->async_data.free_list);
|
||||
pasync_ctx->async_data.free_entries++;
|
||||
}
|
||||
pasync_handle->is_final = 0;
|
||||
pasync_handle->buffer_len = 0;
|
||||
pasync_handle->in_use = 0;
|
||||
list_del_init(&pasync_handle->link);
|
||||
}
|
||||
|
||||
static void
|
||||
beiscsi_hdl_purge_handles(struct beiscsi_hba *phba,
|
||||
struct hd_async_context *pasync_ctx,
|
||||
u16 cri)
|
||||
{
|
||||
struct hd_async_handle *pasync_handle, *tmp_handle;
|
||||
struct list_head *plist;
|
||||
|
||||
plist = &pasync_ctx->async_entry[cri].wq.list;
|
||||
list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link)
|
||||
beiscsi_hdl_put_handle(pasync_ctx, pasync_handle);
|
||||
|
||||
INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list);
|
||||
pasync_ctx->async_entry[cri].wq.hdr_len = 0;
|
||||
pasync_ctx->async_entry[cri].wq.bytes_received = 0;
|
||||
pasync_ctx->async_entry[cri].wq.bytes_needed = 0;
|
||||
}
|
||||
|
||||
static struct hd_async_handle *
|
||||
beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
|
||||
struct hd_async_context *pasync_ctx,
|
||||
struct i_t_dpdu_cqe *pdpdu_cqe)
|
||||
struct i_t_dpdu_cqe *pdpdu_cqe,
|
||||
u8 *header)
|
||||
{
|
||||
struct beiscsi_hba *phba = beiscsi_conn->phba;
|
||||
struct hd_async_handle *pasync_handle;
|
||||
struct be_bus_address phys_addr;
|
||||
u16 cid, code, ci, cri;
|
||||
u8 final, error = 0;
|
||||
u16 cid, code, ci;
|
||||
u32 dpl;
|
||||
|
||||
cid = beiscsi_conn->beiscsi_conn_cid;
|
||||
cri = BE_GET_ASYNC_CRI_FROM_CID(cid);
|
||||
/**
|
||||
* This function is invoked to get the right async_handle structure
|
||||
* from a given DEF PDU CQ entry.
|
||||
|
@ -1516,6 +1522,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
|
|||
switch (code) {
|
||||
case UNSOL_HDR_NOTIFY:
|
||||
pasync_handle = pasync_ctx->async_entry[ci].header;
|
||||
*header = 1;
|
||||
break;
|
||||
case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
|
||||
error = 1;
|
||||
|
@ -1524,15 +1531,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
|
|||
break;
|
||||
/* called only for above codes */
|
||||
default:
|
||||
pasync_handle = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pasync_handle) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
|
||||
"BM_%d : cid %d async PDU handle not found - code %d ci %d addr %llx\n",
|
||||
cid, code, ci, phys_addr.u.a64.address);
|
||||
return pasync_handle;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pasync_handle->pa.u.a64.address != phys_addr.u.a64.address ||
|
||||
|
@ -1548,50 +1547,35 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn,
|
|||
/* FW has stale address - attempt continuing by dropping */
|
||||
}
|
||||
|
||||
/**
|
||||
* Each CID is associated with unique CRI.
|
||||
* ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different.
|
||||
**/
|
||||
pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID(cid);
|
||||
pasync_handle->is_final = final;
|
||||
pasync_handle->buffer_len = dpl;
|
||||
/* empty the slot */
|
||||
if (pasync_handle->is_header)
|
||||
pasync_ctx->async_entry[ci].header = NULL;
|
||||
else
|
||||
pasync_ctx->async_entry[ci].data = NULL;
|
||||
|
||||
/**
|
||||
* DEF PDU header and data buffers with errors should be simply
|
||||
* dropped as there are no consumers for it.
|
||||
*/
|
||||
if (error) {
|
||||
beiscsi_hdl_put_handle(pasync_ctx, pasync_handle);
|
||||
pasync_handle = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pasync_handle->in_use || !list_empty(&pasync_handle->link)) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
|
||||
"BM_%d : cid %d async PDU handle in use - code %d ci %d addr %llx\n",
|
||||
cid, code, ci, phys_addr.u.a64.address);
|
||||
beiscsi_hdl_purge_handles(phba, pasync_ctx, cri);
|
||||
}
|
||||
|
||||
list_del_init(&pasync_handle->link);
|
||||
/**
|
||||
* Each CID is associated with unique CRI.
|
||||
* ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different.
|
||||
**/
|
||||
pasync_handle->cri = cri;
|
||||
pasync_handle->is_final = final;
|
||||
pasync_handle->buffer_len = dpl;
|
||||
pasync_handle->in_use = 1;
|
||||
|
||||
return pasync_handle;
|
||||
}
|
||||
|
||||
static void
|
||||
beiscsi_hdl_purge_handles(struct beiscsi_hba *phba,
|
||||
struct hd_async_context *pasync_ctx,
|
||||
u16 cri)
|
||||
{
|
||||
struct hd_async_handle *pasync_handle, *tmp_handle;
|
||||
struct list_head *plist;
|
||||
|
||||
plist = &pasync_ctx->async_entry[cri].wq.list;
|
||||
list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {
|
||||
list_del(&pasync_handle->link);
|
||||
beiscsi_hdl_put_handle(pasync_ctx, pasync_handle);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list);
|
||||
pasync_ctx->async_entry[cri].wq.hdr_len = 0;
|
||||
pasync_ctx->async_entry[cri].wq.bytes_received = 0;
|
||||
pasync_ctx->async_entry[cri].wq.bytes_needed = 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn,
|
||||
struct hd_async_context *pasync_ctx,
|
||||
|
@ -1619,6 +1603,10 @@ beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn,
|
|||
dlen = pasync_handle->buffer_len;
|
||||
continue;
|
||||
}
|
||||
if (!pasync_handle->buffer_len ||
|
||||
(dlen + pasync_handle->buffer_len) >
|
||||
pasync_ctx->async_data.buffer_size)
|
||||
break;
|
||||
memcpy(pdata + dlen, pasync_handle->pbuffer,
|
||||
pasync_handle->buffer_len);
|
||||
dlen += pasync_handle->buffer_len;
|
||||
|
@ -1627,8 +1615,9 @@ beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn,
|
|||
if (!plast_handle->is_final) {
|
||||
/* last handle should have final PDU notification from FW */
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
|
||||
"BM_%d : cid %u %p fwd async PDU with last handle missing - HL%u:DN%u:DR%u\n",
|
||||
"BM_%d : cid %u %p fwd async PDU opcode %x with last handle missing - HL%u:DN%u:DR%u\n",
|
||||
beiscsi_conn->beiscsi_conn_cid, plast_handle,
|
||||
AMAP_GET_BITS(struct amap_pdu_base, opcode, phdr),
|
||||
pasync_ctx->async_entry[cri].wq.hdr_len,
|
||||
pasync_ctx->async_entry[cri].wq.bytes_needed,
|
||||
pasync_ctx->async_entry[cri].wq.bytes_received);
|
||||
|
@ -1709,85 +1698,53 @@ beiscsi_hdl_gather_pdu(struct beiscsi_conn *beiscsi_conn,
|
|||
|
||||
static void
|
||||
beiscsi_hdq_post_handles(struct beiscsi_hba *phba,
|
||||
u8 header, u8 ulp_num)
|
||||
u8 header, u8 ulp_num, u16 nbuf)
|
||||
{
|
||||
struct hd_async_handle *pasync_handle, *tmp, **slot;
|
||||
struct hd_async_handle *pasync_handle;
|
||||
struct hd_async_context *pasync_ctx;
|
||||
struct hwi_controller *phwi_ctrlr;
|
||||
struct list_head *hfree_list;
|
||||
struct phys_addr *pasync_sge;
|
||||
u32 ring_id, doorbell = 0;
|
||||
u32 doorbell_offset;
|
||||
u16 prod = 0, cons;
|
||||
u16 index;
|
||||
u16 prod, pi;
|
||||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num);
|
||||
if (header) {
|
||||
cons = pasync_ctx->async_header.free_entries;
|
||||
hfree_list = &pasync_ctx->async_header.free_list;
|
||||
pasync_sge = pasync_ctx->async_header.ring_base;
|
||||
pi = pasync_ctx->async_header.pi;
|
||||
ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id;
|
||||
doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num].
|
||||
doorbell_offset;
|
||||
} else {
|
||||
cons = pasync_ctx->async_data.free_entries;
|
||||
hfree_list = &pasync_ctx->async_data.free_list;
|
||||
pasync_sge = pasync_ctx->async_data.ring_base;
|
||||
pi = pasync_ctx->async_data.pi;
|
||||
ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id;
|
||||
doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num].
|
||||
doorbell_offset;
|
||||
}
|
||||
/* number of entries posted must be in multiples of 8 */
|
||||
if (cons % 8)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(pasync_handle, tmp, hfree_list, link) {
|
||||
list_del_init(&pasync_handle->link);
|
||||
pasync_handle->is_final = 0;
|
||||
pasync_handle->buffer_len = 0;
|
||||
|
||||
/* handles can be consumed out of order, use index in handle */
|
||||
index = pasync_handle->index;
|
||||
for (prod = 0; prod < nbuf; prod++) {
|
||||
if (header)
|
||||
pasync_handle = pasync_ctx->async_entry[pi].header;
|
||||
else
|
||||
pasync_handle = pasync_ctx->async_entry[pi].data;
|
||||
WARN_ON(pasync_handle->is_header != header);
|
||||
if (header)
|
||||
slot = &pasync_ctx->async_entry[index].header;
|
||||
else
|
||||
slot = &pasync_ctx->async_entry[index].data;
|
||||
/**
|
||||
* The slot just tracks handle's hold and release, so
|
||||
* overwriting at the same index won't do any harm but
|
||||
* needs to be caught.
|
||||
*/
|
||||
if (*slot != NULL) {
|
||||
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI,
|
||||
"BM_%d : async PDU %s slot at %u not empty\n",
|
||||
header ? "header" : "data", index);
|
||||
WARN_ON(pasync_handle->index != pi);
|
||||
/* setup the ring only once */
|
||||
if (nbuf == pasync_ctx->num_entries) {
|
||||
/* note hi is lo */
|
||||
pasync_sge[pi].hi = pasync_handle->pa.u.a32.address_lo;
|
||||
pasync_sge[pi].lo = pasync_handle->pa.u.a32.address_hi;
|
||||
}
|
||||
/**
|
||||
* We use same freed index as in completion to post so this
|
||||
* operation is not required for refills. Its required only
|
||||
* for ring creation.
|
||||
*/
|
||||
if (header)
|
||||
pasync_sge = pasync_ctx->async_header.ring_base;
|
||||
else
|
||||
pasync_sge = pasync_ctx->async_data.ring_base;
|
||||
pasync_sge += index;
|
||||
/* if its a refill then address is same; hi is lo */
|
||||
WARN_ON(pasync_sge->hi &&
|
||||
pasync_sge->hi != pasync_handle->pa.u.a32.address_lo);
|
||||
WARN_ON(pasync_sge->lo &&
|
||||
pasync_sge->lo != pasync_handle->pa.u.a32.address_hi);
|
||||
pasync_sge->hi = pasync_handle->pa.u.a32.address_lo;
|
||||
pasync_sge->lo = pasync_handle->pa.u.a32.address_hi;
|
||||
|
||||
*slot = pasync_handle;
|
||||
if (++prod == cons)
|
||||
break;
|
||||
if (++pi == pasync_ctx->num_entries)
|
||||
pi = 0;
|
||||
}
|
||||
|
||||
if (header)
|
||||
pasync_ctx->async_header.free_entries -= prod;
|
||||
pasync_ctx->async_header.pi = pi;
|
||||
else
|
||||
pasync_ctx->async_data.free_entries -= prod;
|
||||
pasync_ctx->async_data.pi = pi;
|
||||
|
||||
doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK;
|
||||
doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT;
|
||||
|
@ -1804,20 +1761,26 @@ beiscsi_hdq_process_compl(struct beiscsi_conn *beiscsi_conn,
|
|||
struct hd_async_handle *pasync_handle = NULL;
|
||||
struct hd_async_context *pasync_ctx;
|
||||
struct hwi_controller *phwi_ctrlr;
|
||||
u8 ulp_num, consumed, header = 0;
|
||||
u16 cid_cri;
|
||||
u8 ulp_num;
|
||||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
cid_cri = BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid);
|
||||
ulp_num = BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cid_cri);
|
||||
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num);
|
||||
pasync_handle = beiscsi_hdl_get_handle(beiscsi_conn, pasync_ctx,
|
||||
pdpdu_cqe);
|
||||
if (!pasync_handle)
|
||||
return;
|
||||
|
||||
beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle);
|
||||
beiscsi_hdq_post_handles(phba, pasync_handle->is_header, ulp_num);
|
||||
pdpdu_cqe, &header);
|
||||
if (is_chip_be2_be3r(phba))
|
||||
consumed = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
|
||||
num_cons, pdpdu_cqe);
|
||||
else
|
||||
consumed = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
|
||||
num_cons, pdpdu_cqe);
|
||||
if (pasync_handle)
|
||||
beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle);
|
||||
/* num_cons indicates number of 8 RQEs consumed */
|
||||
if (consumed)
|
||||
beiscsi_hdq_post_handles(phba, header, ulp_num, 8 * consumed);
|
||||
}
|
||||
|
||||
void beiscsi_process_mcc_cq(struct beiscsi_hba *phba)
|
||||
|
@ -2407,22 +2370,22 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
|
|||
if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
|
||||
|
||||
num_async_pdu_buf_sgl_pages =
|
||||
PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
|
||||
PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
|
||||
phba, ulp_num) *
|
||||
sizeof(struct phys_addr));
|
||||
|
||||
num_async_pdu_buf_pages =
|
||||
PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
|
||||
PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
|
||||
phba, ulp_num) *
|
||||
phba->params.defpdu_hdr_sz);
|
||||
|
||||
num_async_pdu_data_pages =
|
||||
PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
|
||||
PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
|
||||
phba, ulp_num) *
|
||||
phba->params.defpdu_data_sz);
|
||||
|
||||
num_async_pdu_data_sgl_pages =
|
||||
PAGES_REQUIRED(BEISCSI_GET_CID_COUNT(
|
||||
PAGES_REQUIRED(BEISCSI_ASYNC_HDQ_SIZE(
|
||||
phba, ulp_num) *
|
||||
sizeof(struct phys_addr));
|
||||
|
||||
|
@ -2459,21 +2422,21 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
|
|||
mem_descr_index = (HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 +
|
||||
(ulp_num * MEM_DESCR_OFFSET));
|
||||
phba->mem_req[mem_descr_index] =
|
||||
BEISCSI_GET_CID_COUNT(phba, ulp_num) *
|
||||
sizeof(struct hd_async_handle);
|
||||
BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) *
|
||||
sizeof(struct hd_async_handle);
|
||||
|
||||
mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 +
|
||||
(ulp_num * MEM_DESCR_OFFSET));
|
||||
phba->mem_req[mem_descr_index] =
|
||||
BEISCSI_GET_CID_COUNT(phba, ulp_num) *
|
||||
sizeof(struct hd_async_handle);
|
||||
BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) *
|
||||
sizeof(struct hd_async_handle);
|
||||
|
||||
mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 +
|
||||
(ulp_num * MEM_DESCR_OFFSET));
|
||||
phba->mem_req[mem_descr_index] =
|
||||
sizeof(struct hd_async_context) +
|
||||
(BEISCSI_GET_CID_COUNT(phba, ulp_num) *
|
||||
sizeof(struct hd_async_entry));
|
||||
sizeof(struct hd_async_context) +
|
||||
(BEISCSI_ASYNC_HDQ_SIZE(phba, ulp_num) *
|
||||
sizeof(struct hd_async_entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2757,7 +2720,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
((long unsigned int)pasync_ctx +
|
||||
sizeof(struct hd_async_context));
|
||||
|
||||
pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba,
|
||||
pasync_ctx->num_entries = BEISCSI_ASYNC_HDQ_SIZE(phba,
|
||||
ulp_num);
|
||||
/* setup header buffers */
|
||||
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
|
||||
|
@ -2776,6 +2739,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
"BM_%d : No Virtual address for ULP : %d\n",
|
||||
ulp_num);
|
||||
|
||||
pasync_ctx->async_header.pi = 0;
|
||||
pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz;
|
||||
pasync_ctx->async_header.va_base =
|
||||
mem_descr->mem_array[0].virtual_address;
|
||||
|
@ -2823,7 +2787,6 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
|
||||
pasync_ctx->async_header.handle_base =
|
||||
mem_descr->mem_array[0].virtual_address;
|
||||
INIT_LIST_HEAD(&pasync_ctx->async_header.free_list);
|
||||
|
||||
/* setup data buffer sgls */
|
||||
mem_descr = (struct be_mem_descriptor *)phba->init_mem;
|
||||
|
@ -2857,7 +2820,6 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
|
||||
pasync_ctx->async_data.handle_base =
|
||||
mem_descr->mem_array[0].virtual_address;
|
||||
INIT_LIST_HEAD(&pasync_ctx->async_data.free_list);
|
||||
|
||||
pasync_header_h =
|
||||
(struct hd_async_handle *)
|
||||
|
@ -2884,6 +2846,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
ulp_num);
|
||||
|
||||
idx = 0;
|
||||
pasync_ctx->async_data.pi = 0;
|
||||
pasync_ctx->async_data.buffer_size = p->defpdu_data_sz;
|
||||
pasync_ctx->async_data.va_base =
|
||||
mem_descr->mem_array[idx].virtual_address;
|
||||
|
@ -2895,7 +2858,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
phba->params.defpdu_data_sz);
|
||||
num_per_mem = 0;
|
||||
|
||||
for (index = 0; index < BEISCSI_GET_CID_COUNT
|
||||
for (index = 0; index < BEISCSI_ASYNC_HDQ_SIZE
|
||||
(phba, ulp_num); index++) {
|
||||
pasync_header_h->cri = -1;
|
||||
pasync_header_h->is_header = 1;
|
||||
|
@ -2911,14 +2874,11 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
pasync_ctx->async_header.pa_base.u.a64.
|
||||
address + (p->defpdu_hdr_sz * index);
|
||||
|
||||
list_add_tail(&pasync_header_h->link,
|
||||
&pasync_ctx->async_header.
|
||||
free_list);
|
||||
pasync_ctx->async_entry[index].header =
|
||||
pasync_header_h;
|
||||
pasync_header_h++;
|
||||
pasync_ctx->async_header.free_entries++;
|
||||
INIT_LIST_HEAD(&pasync_ctx->async_entry[index].
|
||||
wq.list);
|
||||
pasync_ctx->async_entry[index].header = NULL;
|
||||
|
||||
pasync_data_h->cri = -1;
|
||||
pasync_data_h->is_header = 0;
|
||||
|
@ -2952,12 +2912,9 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
|
|||
num_per_mem++;
|
||||
num_async_data--;
|
||||
|
||||
list_add_tail(&pasync_data_h->link,
|
||||
&pasync_ctx->async_data.
|
||||
free_list);
|
||||
pasync_ctx->async_entry[index].data =
|
||||
pasync_data_h;
|
||||
pasync_data_h++;
|
||||
pasync_ctx->async_data.free_entries++;
|
||||
pasync_ctx->async_entry[index].data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3040,7 +2997,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
|
|||
num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
|
||||
sizeof(struct be_eq_entry));
|
||||
|
||||
if (phba->msix_enabled)
|
||||
if (phba->pcidev->msix_enabled)
|
||||
eq_for_mcc = 1;
|
||||
else
|
||||
eq_for_mcc = 0;
|
||||
|
@ -3550,7 +3507,7 @@ static int be_mcc_queues_create(struct beiscsi_hba *phba,
|
|||
sizeof(struct be_mcc_compl)))
|
||||
goto err;
|
||||
/* Ask BE to create MCC compl queue; */
|
||||
if (phba->msix_enabled) {
|
||||
if (phba->pcidev->msix_enabled) {
|
||||
if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq
|
||||
[phba->num_cpus].q, false, true, 0))
|
||||
goto mcc_cq_free;
|
||||
|
@ -3581,42 +3538,35 @@ static int be_mcc_queues_create(struct beiscsi_hba *phba,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_num_cpus()- Get the CPU online count
|
||||
* @phba: ptr to priv structure
|
||||
*
|
||||
* CPU count is used for creating EQ.
|
||||
**/
|
||||
static void find_num_cpus(struct beiscsi_hba *phba)
|
||||
static void be2iscsi_enable_msix(struct beiscsi_hba *phba)
|
||||
{
|
||||
int num_cpus = 0;
|
||||
|
||||
num_cpus = num_online_cpus();
|
||||
int nvec = 1;
|
||||
|
||||
switch (phba->generation) {
|
||||
case BE_GEN2:
|
||||
case BE_GEN3:
|
||||
phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ?
|
||||
BEISCSI_MAX_NUM_CPUS : num_cpus;
|
||||
nvec = BEISCSI_MAX_NUM_CPUS + 1;
|
||||
break;
|
||||
case BE_GEN4:
|
||||
/*
|
||||
* If eqid_count == 1 fall back to
|
||||
* INTX mechanism
|
||||
**/
|
||||
if (phba->fw_config.eqid_count == 1) {
|
||||
enable_msix = 0;
|
||||
phba->num_cpus = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
phba->num_cpus =
|
||||
(num_cpus > (phba->fw_config.eqid_count - 1)) ?
|
||||
(phba->fw_config.eqid_count - 1) : num_cpus;
|
||||
nvec = phba->fw_config.eqid_count;
|
||||
break;
|
||||
default:
|
||||
phba->num_cpus = 1;
|
||||
nvec = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if eqid_count == 1 fall back to INTX */
|
||||
if (enable_msix && nvec > 1) {
|
||||
const struct irq_affinity desc = { .post_vectors = 1 };
|
||||
|
||||
if (pci_alloc_irq_vectors_affinity(phba->pcidev, 2, nvec,
|
||||
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc) < 0) {
|
||||
phba->num_cpus = nvec - 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
phba->num_cpus = 1;
|
||||
}
|
||||
|
||||
static void hwi_purge_eq(struct beiscsi_hba *phba)
|
||||
|
@ -3633,7 +3583,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
|
|||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
phwi_context = phwi_ctrlr->phwi_ctxt;
|
||||
if (phba->msix_enabled)
|
||||
if (phba->pcidev->msix_enabled)
|
||||
eq_msix = 1;
|
||||
else
|
||||
eq_msix = 0;
|
||||
|
@ -3711,7 +3661,7 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba)
|
|||
}
|
||||
|
||||
be_mcc_queues_destroy(phba);
|
||||
if (phba->msix_enabled)
|
||||
if (phba->pcidev->msix_enabled)
|
||||
eq_for_mcc = 1;
|
||||
else
|
||||
eq_for_mcc = 0;
|
||||
|
@ -3735,6 +3685,7 @@ static int hwi_init_port(struct beiscsi_hba *phba)
|
|||
unsigned int def_pdu_ring_sz;
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
int status, ulp_num;
|
||||
u16 nbufs;
|
||||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
phwi_context = phwi_ctrlr->phwi_ctxt;
|
||||
|
@ -3771,9 +3722,8 @@ static int hwi_init_port(struct beiscsi_hba *phba)
|
|||
|
||||
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
|
||||
if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
|
||||
def_pdu_ring_sz =
|
||||
BEISCSI_GET_CID_COUNT(phba, ulp_num) *
|
||||
sizeof(struct phys_addr);
|
||||
nbufs = phwi_context->pasync_ctx[ulp_num]->num_entries;
|
||||
def_pdu_ring_sz = nbufs * sizeof(struct phys_addr);
|
||||
|
||||
status = beiscsi_create_def_hdr(phba, phwi_context,
|
||||
phwi_ctrlr,
|
||||
|
@ -3801,9 +3751,9 @@ static int hwi_init_port(struct beiscsi_hba *phba)
|
|||
* let EP know about it.
|
||||
*/
|
||||
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR,
|
||||
ulp_num);
|
||||
ulp_num, nbufs);
|
||||
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA,
|
||||
ulp_num);
|
||||
ulp_num, nbufs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4157,7 +4107,7 @@ static void hwi_enable_intr(struct beiscsi_hba *phba)
|
|||
iowrite32(reg, addr);
|
||||
}
|
||||
|
||||
if (!phba->msix_enabled) {
|
||||
if (!phba->pcidev->msix_enabled) {
|
||||
eq = &phwi_context->be_eq[0].q;
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
|
||||
"BM_%d : eq->id=%d\n", eq->id);
|
||||
|
@ -5280,19 +5230,6 @@ static void beiscsi_eqd_update_work(struct work_struct *work)
|
|||
msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL));
|
||||
}
|
||||
|
||||
static void beiscsi_msix_enable(struct beiscsi_hba *phba)
|
||||
{
|
||||
int i, status;
|
||||
|
||||
for (i = 0; i <= phba->num_cpus; i++)
|
||||
phba->msix_entries[i].entry = i;
|
||||
|
||||
status = pci_enable_msix_range(phba->pcidev, phba->msix_entries,
|
||||
phba->num_cpus + 1, phba->num_cpus + 1);
|
||||
if (status > 0)
|
||||
phba->msix_enabled = true;
|
||||
}
|
||||
|
||||
static void beiscsi_hw_tpe_check(unsigned long ptr)
|
||||
{
|
||||
struct beiscsi_hba *phba;
|
||||
|
@ -5360,15 +5297,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (enable_msix)
|
||||
find_num_cpus(phba);
|
||||
else
|
||||
phba->num_cpus = 1;
|
||||
if (enable_msix) {
|
||||
beiscsi_msix_enable(phba);
|
||||
if (!phba->msix_enabled)
|
||||
phba->num_cpus = 1;
|
||||
}
|
||||
be2iscsi_enable_msix(phba);
|
||||
|
||||
beiscsi_get_params(phba);
|
||||
/* Re-enable UER. If different TPE occurs then it is recoverable. */
|
||||
|
@ -5397,7 +5326,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
|
|||
irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll);
|
||||
}
|
||||
|
||||
i = (phba->msix_enabled) ? i : 0;
|
||||
i = (phba->pcidev->msix_enabled) ? i : 0;
|
||||
/* Work item for MCC handling */
|
||||
pbe_eq = &phwi_context->be_eq[i];
|
||||
INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work);
|
||||
|
@ -5435,9 +5364,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
|
|||
hwi_cleanup_port(phba);
|
||||
|
||||
disable_msix:
|
||||
if (phba->msix_enabled)
|
||||
pci_disable_msix(phba->pcidev);
|
||||
|
||||
pci_free_irq_vectors(phba->pcidev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -5454,7 +5381,7 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload)
|
|||
struct hwi_context_memory *phwi_context;
|
||||
struct hwi_controller *phwi_ctrlr;
|
||||
struct be_eq_obj *pbe_eq;
|
||||
unsigned int i, msix_vec;
|
||||
unsigned int i;
|
||||
|
||||
if (!test_and_clear_bit(BEISCSI_HBA_ONLINE, &phba->state))
|
||||
return;
|
||||
|
@ -5462,16 +5389,16 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload)
|
|||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
phwi_context = phwi_ctrlr->phwi_ctxt;
|
||||
hwi_disable_intr(phba);
|
||||
if (phba->msix_enabled) {
|
||||
if (phba->pcidev->msix_enabled) {
|
||||
for (i = 0; i <= phba->num_cpus; i++) {
|
||||
msix_vec = phba->msix_entries[i].vector;
|
||||
free_irq(msix_vec, &phwi_context->be_eq[i]);
|
||||
free_irq(pci_irq_vector(phba->pcidev, i),
|
||||
&phwi_context->be_eq[i]);
|
||||
kfree(phba->msi_name[i]);
|
||||
}
|
||||
} else
|
||||
if (phba->pcidev->irq)
|
||||
free_irq(phba->pcidev->irq, phba);
|
||||
pci_disable_msix(phba->pcidev);
|
||||
pci_free_irq_vectors(phba->pcidev);
|
||||
|
||||
for (i = 0; i < phba->num_cpus; i++) {
|
||||
pbe_eq = &phwi_context->be_eq[i];
|
||||
|
@ -5681,21 +5608,12 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
|
|||
beiscsi_get_params(phba);
|
||||
beiscsi_set_uer_feature(phba);
|
||||
|
||||
if (enable_msix)
|
||||
find_num_cpus(phba);
|
||||
else
|
||||
phba->num_cpus = 1;
|
||||
be2iscsi_enable_msix(phba);
|
||||
|
||||
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
|
||||
"BM_%d : num_cpus = %d\n",
|
||||
phba->num_cpus);
|
||||
|
||||
if (enable_msix) {
|
||||
beiscsi_msix_enable(phba);
|
||||
if (!phba->msix_enabled)
|
||||
phba->num_cpus = 1;
|
||||
}
|
||||
|
||||
phba->shost->max_id = phba->params.cxns_per_ctrl;
|
||||
phba->shost->can_queue = phba->params.ios_per_ctrl;
|
||||
ret = beiscsi_get_memory(phba);
|
||||
|
@ -5745,7 +5663,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
|
|||
irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll);
|
||||
}
|
||||
|
||||
i = (phba->msix_enabled) ? i : 0;
|
||||
i = (phba->pcidev->msix_enabled) ? i : 0;
|
||||
/* Work item for MCC handling */
|
||||
pbe_eq = &phwi_context->be_eq[i];
|
||||
INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work);
|
||||
|
@ -5816,8 +5734,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
|
|||
phba->ctrl.mbox_mem_alloced.dma);
|
||||
beiscsi_unmap_pci_function(phba);
|
||||
hba_free:
|
||||
if (phba->msix_enabled)
|
||||
pci_disable_msix(phba->pcidev);
|
||||
pci_disable_msix(phba->pcidev);
|
||||
pci_dev_put(phba->pcidev);
|
||||
iscsi_host_free(phba->shost);
|
||||
pci_set_drvdata(pcidev, NULL);
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#ifndef _BEISCSI_MAIN_
|
||||
|
@ -36,7 +31,7 @@
|
|||
#include <scsi/scsi_transport_iscsi.h>
|
||||
|
||||
#define DRV_NAME "be2iscsi"
|
||||
#define BUILD_STR "11.2.1.0"
|
||||
#define BUILD_STR "11.4.0.0"
|
||||
#define BE_NAME "Emulex OneConnect" \
|
||||
"Open-iSCSI Driver version" BUILD_STR
|
||||
#define DRV_DESC BE_NAME " " "Driver"
|
||||
|
@ -235,7 +230,6 @@ struct sgl_handle {
|
|||
struct hba_parameters {
|
||||
unsigned int ios_per_ctrl;
|
||||
unsigned int cxns_per_ctrl;
|
||||
unsigned int asyncpdus_per_ctrl;
|
||||
unsigned int icds_per_ctrl;
|
||||
unsigned int num_sge_per_io;
|
||||
unsigned int defpdu_hdr_sz;
|
||||
|
@ -323,9 +317,7 @@ struct beiscsi_hba {
|
|||
struct pci_dev *pcidev;
|
||||
unsigned int num_cpus;
|
||||
unsigned int nxt_cqid;
|
||||
struct msix_entry msix_entries[MAX_CPUS];
|
||||
char *msi_name[MAX_CPUS];
|
||||
bool msix_enabled;
|
||||
struct be_mem_descriptor *init_mem;
|
||||
|
||||
unsigned short io_sgl_alloc_index;
|
||||
|
@ -597,8 +589,12 @@ struct hd_async_handle {
|
|||
u16 cri;
|
||||
u8 is_header;
|
||||
u8 is_final;
|
||||
u8 in_use;
|
||||
};
|
||||
|
||||
#define BEISCSI_ASYNC_HDQ_SIZE(phba, ulp) \
|
||||
(BEISCSI_GET_CID_COUNT((phba), (ulp)) * 2)
|
||||
|
||||
/**
|
||||
* This has list of async PDUs that are waiting to be processed.
|
||||
* Buffers live in this list for a brief duration before they get
|
||||
|
@ -624,14 +620,8 @@ struct hd_async_buf_context {
|
|||
void *va_base;
|
||||
void *ring_base;
|
||||
struct hd_async_handle *handle_base;
|
||||
u16 free_entries;
|
||||
u32 buffer_size;
|
||||
/**
|
||||
* Once iSCSI layer finishes processing an async PDU, the
|
||||
* handles used for the PDU are added to this list.
|
||||
* They are posted back to FW in groups of 8.
|
||||
*/
|
||||
struct list_head free_list;
|
||||
u16 pi;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#include <linux/bsg-lib.h>
|
||||
|
@ -126,67 +121,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
|
|||
return tag;
|
||||
}
|
||||
|
||||
unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep,
|
||||
unsigned short cid,
|
||||
unsigned short issue_reset,
|
||||
unsigned short savecfg_flag)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct iscsi_invalidate_connection_params_in *req;
|
||||
unsigned int tag = 0;
|
||||
|
||||
mutex_lock(&ctrl->mbox_lock);
|
||||
wrb = alloc_mcc_wrb(phba, &tag);
|
||||
if (!wrb) {
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = embedded_payload(wrb);
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
|
||||
OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
|
||||
sizeof(*req));
|
||||
req->session_handle = beiscsi_ep->fw_handle;
|
||||
req->cid = cid;
|
||||
if (issue_reset)
|
||||
req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST;
|
||||
else
|
||||
req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
|
||||
req->save_cfg = savecfg_flag;
|
||||
be_mcc_notify(phba, tag);
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
|
||||
unsigned short cid, unsigned int upload_flag)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct tcp_upload_params_in *req;
|
||||
unsigned int tag;
|
||||
|
||||
mutex_lock(&ctrl->mbox_lock);
|
||||
wrb = alloc_mcc_wrb(phba, &tag);
|
||||
if (!wrb) {
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = embedded_payload(wrb);
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
|
||||
OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
|
||||
req->id = (unsigned short)cid;
|
||||
req->upload_type = (unsigned char)upload_flag;
|
||||
be_mcc_notify(phba, tag);
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* mgmt_open_connection()- Establish a TCP CXN
|
||||
* @dst_addr: Destination Address
|
||||
|
@ -1449,6 +1383,72 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
|
|||
exp_statsn) / 32] + 1));
|
||||
}
|
||||
|
||||
unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep)
|
||||
{
|
||||
struct be_invalidate_connection_params_in *req;
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb;
|
||||
unsigned int tag = 0;
|
||||
|
||||
mutex_lock(&ctrl->mbox_lock);
|
||||
wrb = alloc_mcc_wrb(phba, &tag);
|
||||
if (!wrb) {
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = embedded_payload(wrb);
|
||||
be_wrb_hdr_prepare(wrb, sizeof(union be_invalidate_connection_params),
|
||||
true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
|
||||
OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
|
||||
sizeof(*req));
|
||||
req->session_handle = beiscsi_ep->fw_handle;
|
||||
req->cid = beiscsi_ep->ep_cid;
|
||||
if (beiscsi_ep->conn)
|
||||
req->cleanup_type = BE_CLEANUP_TYPE_INVALIDATE;
|
||||
else
|
||||
req->cleanup_type = BE_CLEANUP_TYPE_ISSUE_TCP_RST;
|
||||
/**
|
||||
* 0 - non-persistent targets
|
||||
* 1 - save session info on flash
|
||||
*/
|
||||
req->save_cfg = 0;
|
||||
be_mcc_notify(phba, tag);
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_tcp_upload_params_in *req;
|
||||
unsigned int tag;
|
||||
|
||||
mutex_lock(&ctrl->mbox_lock);
|
||||
wrb = alloc_mcc_wrb(phba, &tag);
|
||||
if (!wrb) {
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
req = embedded_payload(wrb);
|
||||
be_wrb_hdr_prepare(wrb, sizeof(union be_tcp_upload_params), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
|
||||
OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
|
||||
req->id = beiscsi_ep->ep_cid;
|
||||
if (beiscsi_ep->conn)
|
||||
req->upload_type = BE_UPLOAD_TYPE_GRACEFUL;
|
||||
else
|
||||
req->upload_type = BE_UPLOAD_TYPE_ABORT;
|
||||
be_mcc_notify(phba, tag);
|
||||
mutex_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
struct invldt_cmd_tbl *inv_tbl,
|
||||
unsigned int nents)
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2005 - 2016 Broadcom
|
||||
* All rights reserved.
|
||||
/*
|
||||
* Copyright 2017 Broadcom. All Rights Reserved.
|
||||
* The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* as published by the Free Software Foundation. The full GNU General
|
||||
* Public License is included in this distribution in the file called COPYING.
|
||||
*
|
||||
* Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com)
|
||||
*
|
||||
* Contact Information:
|
||||
* linux-drivers@broadcom.com
|
||||
*
|
||||
* Emulex
|
||||
* 3333 Susan Street
|
||||
* Costa Mesa, CA 92626
|
||||
*/
|
||||
|
||||
#ifndef _BEISCSI_MGMT_
|
||||
|
@ -41,35 +36,11 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
|
|||
struct beiscsi_endpoint *beiscsi_ep,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
|
||||
unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
|
||||
unsigned short cid,
|
||||
unsigned int upload_flag);
|
||||
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba,
|
||||
struct bsg_job *job,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
|
||||
#define BEISCSI_NO_RST_ISSUE 0
|
||||
struct iscsi_invalidate_connection_params_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
unsigned int session_handle;
|
||||
unsigned short cid;
|
||||
unsigned short unused;
|
||||
unsigned short cleanup_type;
|
||||
unsigned short save_cfg;
|
||||
} __packed;
|
||||
|
||||
struct iscsi_invalidate_connection_params_out {
|
||||
unsigned int session_handle;
|
||||
unsigned short cid;
|
||||
unsigned short unused;
|
||||
} __packed;
|
||||
|
||||
union iscsi_invalidate_connection_params {
|
||||
struct iscsi_invalidate_connection_params_in request;
|
||||
struct iscsi_invalidate_connection_params_out response;
|
||||
} __packed;
|
||||
|
||||
#define BE_INVLDT_CMD_TBL_SZ 128
|
||||
struct invldt_cmd_tbl {
|
||||
unsigned short icd;
|
||||
|
@ -265,6 +236,12 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
|
|||
struct wrb_handle *pwrb_handle,
|
||||
struct hwi_wrb_context *pwrb_context);
|
||||
|
||||
unsigned int beiscsi_invalidate_cxn(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep);
|
||||
|
||||
unsigned int beiscsi_upload_cxn(struct beiscsi_hba *phba,
|
||||
struct beiscsi_endpoint *beiscsi_ep);
|
||||
|
||||
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
|
||||
struct be_set_eqd *, int num);
|
||||
|
||||
|
|
|
@ -22,22 +22,6 @@
|
|||
|
||||
BFA_TRC_FILE(HAL, CORE);
|
||||
|
||||
/*
|
||||
* BFA module list terminated by NULL
|
||||
*/
|
||||
static struct bfa_module_s *hal_mods[] = {
|
||||
&hal_mod_fcdiag,
|
||||
&hal_mod_sgpg,
|
||||
&hal_mod_fcport,
|
||||
&hal_mod_fcxp,
|
||||
&hal_mod_lps,
|
||||
&hal_mod_uf,
|
||||
&hal_mod_rport,
|
||||
&hal_mod_fcp,
|
||||
&hal_mod_dconf,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Message handlers for various modules.
|
||||
*/
|
||||
|
@ -1191,8 +1175,13 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
|
|||
for (i = 0; i < BFI_IOC_MAX_CQS; i++)
|
||||
bfa_isr_rspq_ack(bfa, i, bfa_rspq_ci(bfa, i));
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->start(bfa);
|
||||
bfa_fcport_start(bfa);
|
||||
bfa_uf_start(bfa);
|
||||
/*
|
||||
* bfa_init() with flash read is complete. now invalidate the stale
|
||||
* content of lun mask like unit attention, rp tag and lp tag.
|
||||
*/
|
||||
bfa_ioim_lm_init(BFA_FCP_MOD(bfa)->bfa);
|
||||
|
||||
bfa->iocfc.submod_enabled = BFA_TRUE;
|
||||
}
|
||||
|
@ -1203,13 +1192,16 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
|
|||
static void
|
||||
bfa_iocfc_disable_submod(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (bfa->iocfc.submod_enabled == BFA_FALSE)
|
||||
return;
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->iocdisable(bfa);
|
||||
bfa_fcdiag_iocdisable(bfa);
|
||||
bfa_fcport_iocdisable(bfa);
|
||||
bfa_fcxp_iocdisable(bfa);
|
||||
bfa_lps_iocdisable(bfa);
|
||||
bfa_rport_iocdisable(bfa);
|
||||
bfa_fcp_iocdisable(bfa);
|
||||
bfa_dconf_iocdisable(bfa);
|
||||
|
||||
bfa->iocfc.submod_enabled = BFA_FALSE;
|
||||
}
|
||||
|
@ -1773,7 +1765,6 @@ void
|
|||
bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa);
|
||||
struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
|
||||
struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
|
||||
|
@ -1792,9 +1783,14 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
|
|||
INIT_LIST_HEAD(&meminfo->kva_info.qe);
|
||||
|
||||
bfa_iocfc_meminfo(cfg, meminfo, bfa);
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->meminfo(cfg, meminfo, bfa);
|
||||
bfa_sgpg_meminfo(cfg, meminfo, bfa);
|
||||
bfa_fcport_meminfo(cfg, meminfo, bfa);
|
||||
bfa_fcxp_meminfo(cfg, meminfo, bfa);
|
||||
bfa_lps_meminfo(cfg, meminfo, bfa);
|
||||
bfa_uf_meminfo(cfg, meminfo, bfa);
|
||||
bfa_rport_meminfo(cfg, meminfo, bfa);
|
||||
bfa_fcp_meminfo(cfg, meminfo, bfa);
|
||||
bfa_dconf_meminfo(cfg, meminfo, bfa);
|
||||
|
||||
/* dma info setup */
|
||||
bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo());
|
||||
|
@ -1840,7 +1836,6 @@ void
|
|||
bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
int i;
|
||||
struct bfa_mem_dma_s *dma_info, *dma_elem;
|
||||
struct bfa_mem_kva_s *kva_info, *kva_elem;
|
||||
struct list_head *dm_qe, *km_qe;
|
||||
|
@ -1869,10 +1864,15 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
}
|
||||
|
||||
bfa_iocfc_attach(bfa, bfad, cfg, pcidev);
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->attach(bfa, bfad, cfg, pcidev);
|
||||
|
||||
bfa_fcdiag_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_sgpg_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_fcport_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_fcxp_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_lps_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_uf_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_rport_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_fcp_attach(bfa, bfad, cfg, pcidev);
|
||||
bfa_dconf_attach(bfa, bfad, cfg);
|
||||
bfa_com_port_attach(bfa);
|
||||
bfa_com_ablk_attach(bfa);
|
||||
bfa_com_cee_attach(bfa);
|
||||
|
@ -1899,10 +1899,6 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
void
|
||||
bfa_detach(struct bfa_s *bfa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; hal_mods[i]; i++)
|
||||
hal_mods[i]->detach(bfa);
|
||||
bfa_ioc_detach(&bfa->ioc);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ BFA_TRC_FILE(HAL, FCPIM);
|
|||
* BFA ITNIM Related definitions
|
||||
*/
|
||||
static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
|
||||
static void bfa_ioim_lm_init(struct bfa_s *bfa);
|
||||
|
||||
#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
|
||||
(((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))
|
||||
|
@ -339,7 +338,7 @@ bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad,
|
|||
bfa_ioim_attach(fcpim);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)
|
||||
{
|
||||
struct bfa_fcpim_s *fcpim = &fcp->fcpim;
|
||||
|
@ -2105,7 +2104,7 @@ bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
|
|||
* is complete by driver. now invalidate the stale content of lun mask
|
||||
* like unit attention, rp tag and lp tag.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_ioim_lm_init(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_lun_mask_s *lunm_list;
|
||||
|
@ -3634,11 +3633,7 @@ bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw)
|
|||
}
|
||||
}
|
||||
|
||||
/* BFA FCP module - parent module for fcpim */
|
||||
|
||||
BFA_MODULE(fcp);
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -3696,7 +3691,7 @@ bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
|||
bfa_mem_kva_setup(minfo, fcp_kva, km_len);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -3739,29 +3734,7 @@ bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
(fcp->num_itns * sizeof(struct bfa_itn_s)));
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcp_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcp_start(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
|
||||
|
||||
/*
|
||||
* bfa_init() with flash read is complete. now invalidate the stale
|
||||
* content of lun mask like unit attention, rp tag and lp tag.
|
||||
*/
|
||||
bfa_ioim_lm_init(fcp->bfa);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcp_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcp_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
|
||||
|
|
|
@ -89,16 +89,27 @@ static struct {
|
|||
void (*online) (struct bfa_fcs_lport_s *port);
|
||||
void (*offline) (struct bfa_fcs_lport_s *port);
|
||||
} __port_action[] = {
|
||||
{
|
||||
bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
|
||||
bfa_fcs_lport_unknown_offline}, {
|
||||
bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
|
||||
bfa_fcs_lport_fab_offline}, {
|
||||
bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
|
||||
bfa_fcs_lport_n2n_offline}, {
|
||||
bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online,
|
||||
bfa_fcs_lport_loop_offline},
|
||||
};
|
||||
[BFA_FCS_FABRIC_UNKNOWN] = {
|
||||
.init = bfa_fcs_lport_unknown_init,
|
||||
.online = bfa_fcs_lport_unknown_online,
|
||||
.offline = bfa_fcs_lport_unknown_offline
|
||||
},
|
||||
[BFA_FCS_FABRIC_SWITCHED] = {
|
||||
.init = bfa_fcs_lport_fab_init,
|
||||
.online = bfa_fcs_lport_fab_online,
|
||||
.offline = bfa_fcs_lport_fab_offline
|
||||
},
|
||||
[BFA_FCS_FABRIC_N2N] = {
|
||||
.init = bfa_fcs_lport_n2n_init,
|
||||
.online = bfa_fcs_lport_n2n_online,
|
||||
.offline = bfa_fcs_lport_n2n_offline
|
||||
},
|
||||
[BFA_FCS_FABRIC_LOOP] = {
|
||||
.init = bfa_fcs_lport_loop_init,
|
||||
.online = bfa_fcs_lport_loop_online,
|
||||
.offline = bfa_fcs_lport_loop_offline
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* fcs_port_sm FCS logical port state machine
|
||||
|
|
|
@ -5821,12 +5821,6 @@ bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DCONF module specific
|
||||
*/
|
||||
|
||||
BFA_MODULE(dconf);
|
||||
|
||||
/*
|
||||
* DCONF state machine events
|
||||
*/
|
||||
|
@ -6073,7 +6067,7 @@ bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
|
|||
/*
|
||||
* Compute and return memory needed by DRV_CFG module.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -6087,9 +6081,8 @@ bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
|
|||
sizeof(struct bfa_dconf_s));
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
void
|
||||
bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg)
|
||||
{
|
||||
struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
|
||||
|
||||
|
@ -6134,33 +6127,20 @@ bfa_dconf_modinit(struct bfa_s *bfa)
|
|||
struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
|
||||
bfa_sm_send_event(dconf, BFA_DCONF_SM_INIT);
|
||||
}
|
||||
static void
|
||||
bfa_dconf_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_dconf_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void bfa_dconf_timer(void *cbarg)
|
||||
{
|
||||
struct bfa_dconf_mod_s *dconf = cbarg;
|
||||
bfa_sm_send_event(dconf, BFA_DCONF_SM_TIMEOUT);
|
||||
}
|
||||
static void
|
||||
|
||||
void
|
||||
bfa_dconf_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
|
||||
bfa_sm_send_event(dconf, BFA_DCONF_SM_IOCDISABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_dconf_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static bfa_status_t
|
||||
bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf)
|
||||
{
|
||||
|
|
|
@ -61,54 +61,8 @@ enum {
|
|||
BFA_TRC_HAL_IOCFC_CB = 5,
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro to define a new BFA module
|
||||
*/
|
||||
#define BFA_MODULE(__mod) \
|
||||
static void bfa_ ## __mod ## _meminfo( \
|
||||
struct bfa_iocfc_cfg_s *cfg, \
|
||||
struct bfa_meminfo_s *meminfo, \
|
||||
struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _attach(struct bfa_s *bfa, \
|
||||
void *bfad, struct bfa_iocfc_cfg_s *cfg, \
|
||||
struct bfa_pcidev_s *pcidev); \
|
||||
static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _start(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _stop(struct bfa_s *bfa); \
|
||||
static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa); \
|
||||
\
|
||||
extern struct bfa_module_s hal_mod_ ## __mod; \
|
||||
struct bfa_module_s hal_mod_ ## __mod = { \
|
||||
bfa_ ## __mod ## _meminfo, \
|
||||
bfa_ ## __mod ## _attach, \
|
||||
bfa_ ## __mod ## _detach, \
|
||||
bfa_ ## __mod ## _start, \
|
||||
bfa_ ## __mod ## _stop, \
|
||||
bfa_ ## __mod ## _iocdisable, \
|
||||
}
|
||||
|
||||
#define BFA_CACHELINE_SZ (256)
|
||||
|
||||
/*
|
||||
* Structure used to interact between different BFA sub modules
|
||||
*
|
||||
* Each sub module needs to implement only the entry points relevant to it (and
|
||||
* can leave entry points as NULL)
|
||||
*/
|
||||
struct bfa_module_s {
|
||||
void (*meminfo) (struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_s *bfa);
|
||||
void (*attach) (struct bfa_s *bfa, void *bfad,
|
||||
struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev);
|
||||
void (*detach) (struct bfa_s *bfa);
|
||||
void (*start) (struct bfa_s *bfa);
|
||||
void (*stop) (struct bfa_s *bfa);
|
||||
void (*iocdisable) (struct bfa_s *bfa);
|
||||
};
|
||||
|
||||
|
||||
struct bfa_s {
|
||||
void *bfad; /* BFA driver instance */
|
||||
struct bfa_plog_s *plog; /* portlog buffer */
|
||||
|
@ -127,14 +81,51 @@ struct bfa_s {
|
|||
};
|
||||
|
||||
extern bfa_boolean_t bfa_auto_recover;
|
||||
extern struct bfa_module_s hal_mod_fcdiag;
|
||||
extern struct bfa_module_s hal_mod_sgpg;
|
||||
extern struct bfa_module_s hal_mod_fcport;
|
||||
extern struct bfa_module_s hal_mod_fcxp;
|
||||
extern struct bfa_module_s hal_mod_lps;
|
||||
extern struct bfa_module_s hal_mod_uf;
|
||||
extern struct bfa_module_s hal_mod_rport;
|
||||
extern struct bfa_module_s hal_mod_fcp;
|
||||
extern struct bfa_module_s hal_mod_dconf;
|
||||
|
||||
void bfa_dconf_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *);
|
||||
void bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_dconf_iocdisable(struct bfa_s *);
|
||||
void bfa_fcp_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_fcp_iocdisable(struct bfa_s *bfa);
|
||||
void bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *);
|
||||
void bfa_fcport_start(struct bfa_s *);
|
||||
void bfa_fcport_iocdisable(struct bfa_s *);
|
||||
void bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_fcport_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_fcxp_iocdisable(struct bfa_s *);
|
||||
void bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_fcxp_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_fcdiag_iocdisable(struct bfa_s *);
|
||||
void bfa_fcdiag_attach(struct bfa_s *bfa, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_ioim_lm_init(struct bfa_s *);
|
||||
void bfa_lps_iocdisable(struct bfa_s *bfa);
|
||||
void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_lps_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_rport_iocdisable(struct bfa_s *bfa);
|
||||
void bfa_rport_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_rport_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_sgpg_attach(struct bfa_s *, void *bfad, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_uf_iocdisable(struct bfa_s *);
|
||||
void bfa_uf_meminfo(struct bfa_iocfc_cfg_s *, struct bfa_meminfo_s *,
|
||||
struct bfa_s *);
|
||||
void bfa_uf_attach(struct bfa_s *, void *, struct bfa_iocfc_cfg_s *,
|
||||
struct bfa_pcidev_s *);
|
||||
void bfa_uf_start(struct bfa_s *);
|
||||
|
||||
#endif /* __BFA_MODULES_H__ */
|
||||
|
|
|
@ -23,13 +23,6 @@
|
|||
#include "bfa_modules.h"
|
||||
|
||||
BFA_TRC_FILE(HAL, FCXP);
|
||||
BFA_MODULE(fcdiag);
|
||||
BFA_MODULE(fcxp);
|
||||
BFA_MODULE(sgpg);
|
||||
BFA_MODULE(lps);
|
||||
BFA_MODULE(fcport);
|
||||
BFA_MODULE(rport);
|
||||
BFA_MODULE(uf);
|
||||
|
||||
/*
|
||||
* LPS related definitions
|
||||
|
@ -121,15 +114,6 @@ static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
|
|||
/*
|
||||
* forward declarations for LPS functions
|
||||
*/
|
||||
static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_meminfo_s *minfo, struct bfa_s *bfa);
|
||||
static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
|
||||
struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev);
|
||||
static void bfa_lps_detach(struct bfa_s *bfa);
|
||||
static void bfa_lps_start(struct bfa_s *bfa);
|
||||
static void bfa_lps_stop(struct bfa_s *bfa);
|
||||
static void bfa_lps_iocdisable(struct bfa_s *bfa);
|
||||
static void bfa_lps_login_rsp(struct bfa_s *bfa,
|
||||
struct bfi_lps_login_rsp_s *rsp);
|
||||
static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
|
||||
|
@ -484,7 +468,7 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
|
|||
bfa_mem_kva_curp(mod) = (void *)fcxp;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -522,7 +506,7 @@ bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
|||
cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -544,22 +528,7 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
claim_fcxps_mem(mod);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcxp_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcxp_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
|
||||
|
@ -1510,7 +1479,7 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
|
|||
/*
|
||||
* return memory requirement
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -1527,7 +1496,7 @@ bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
|||
/*
|
||||
* bfa module attach at initialization time
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -1557,25 +1526,10 @@ bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_lps_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* IOC in disabled state -- consider all lps offline
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_lps_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
|
||||
|
@ -3055,7 +3009,7 @@ bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
|
|||
#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
|
||||
BFA_CACHELINE_SZ))
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -3086,7 +3040,7 @@ bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
|
|||
/*
|
||||
* Memory initialization.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -3131,34 +3085,16 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcport_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when IOC is ready.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_fcport_start(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called before IOC is stopped.
|
||||
*/
|
||||
static void
|
||||
bfa_fcport_stop(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
|
||||
bfa_trunk_iocdisable(bfa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when IOC failure is detected.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_fcport_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
|
||||
|
@ -4886,7 +4822,7 @@ bfa_rport_qresume(void *cbarg)
|
|||
bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -4900,7 +4836,7 @@ bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
|||
cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -4940,22 +4876,7 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
bfa_mem_kva_curp(mod) = (u8 *) rp;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_rport_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_rport_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
|
||||
|
@ -5246,7 +5167,7 @@ bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
|
|||
/*
|
||||
* Compute and return memory needed by FCP(im) module.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -5281,7 +5202,7 @@ bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
|||
cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -5344,26 +5265,6 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_sgpg_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
bfa_status_t
|
||||
bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
|
||||
{
|
||||
|
@ -5547,7 +5448,7 @@ uf_mem_claim(struct bfa_uf_mod_s *ufm)
|
|||
claim_uf_post_msgs(ufm);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
|
@ -5575,7 +5476,7 @@ bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
|
|||
(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -5590,11 +5491,6 @@ bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
uf_mem_claim(ufm);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static struct bfa_uf_s *
|
||||
bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
|
||||
{
|
||||
|
@ -5682,12 +5578,7 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
|
|||
bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_uf_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_uf_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
|
||||
|
@ -5704,7 +5595,7 @@ bfa_uf_iocdisable(struct bfa_s *bfa)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_uf_start(struct bfa_s *bfa)
|
||||
{
|
||||
bfa_uf_post_all(BFA_UF_MOD(bfa));
|
||||
|
@ -5845,13 +5736,7 @@ bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
|
|||
fcport->diag_busy = BFA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcdiag_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
|
||||
struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
||||
struct bfa_pcidev_s *pcidev)
|
||||
{
|
||||
|
@ -5870,7 +5755,7 @@ bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
|
|||
memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
bfa_fcdiag_iocdisable(struct bfa_s *bfa)
|
||||
{
|
||||
struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
|
||||
|
@ -5887,21 +5772,6 @@ bfa_fcdiag_iocdisable(struct bfa_s *bfa)
|
|||
bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcdiag_detach(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcdiag_start(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcdiag_stop(struct bfa_s *bfa)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
bfa_fcdiag_queuetest_timeout(void *cbarg)
|
||||
{
|
||||
|
|
|
@ -95,7 +95,6 @@ enum {
|
|||
};
|
||||
|
||||
struct csio_msix_entries {
|
||||
unsigned short vector; /* Assigned MSI-X vector */
|
||||
void *dev_id; /* Priv object associated w/ this msix*/
|
||||
char desc[24]; /* Description of this vector */
|
||||
};
|
||||
|
|
|
@ -383,17 +383,15 @@ csio_request_irqs(struct csio_hw *hw)
|
|||
int rv, i, j, k = 0;
|
||||
struct csio_msix_entries *entryp = &hw->msix_entries[0];
|
||||
struct csio_scsi_cpu_info *info;
|
||||
struct pci_dev *pdev = hw->pdev;
|
||||
|
||||
if (hw->intr_mode != CSIO_IM_MSIX) {
|
||||
rv = request_irq(hw->pdev->irq, csio_fcoe_isr,
|
||||
(hw->intr_mode == CSIO_IM_MSI) ?
|
||||
0 : IRQF_SHARED,
|
||||
KBUILD_MODNAME, hw);
|
||||
rv = request_irq(pci_irq_vector(pdev, 0), csio_fcoe_isr,
|
||||
hw->intr_mode == CSIO_IM_MSI ? 0 : IRQF_SHARED,
|
||||
KBUILD_MODNAME, hw);
|
||||
if (rv) {
|
||||
if (hw->intr_mode == CSIO_IM_MSI)
|
||||
pci_disable_msi(hw->pdev);
|
||||
csio_err(hw, "Failed to allocate interrupt line.\n");
|
||||
return -EINVAL;
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
@ -402,22 +400,22 @@ csio_request_irqs(struct csio_hw *hw)
|
|||
/* Add the MSIX vector descriptions */
|
||||
csio_add_msix_desc(hw);
|
||||
|
||||
rv = request_irq(entryp[k].vector, csio_nondata_isr, 0,
|
||||
rv = request_irq(pci_irq_vector(pdev, k), csio_nondata_isr, 0,
|
||||
entryp[k].desc, hw);
|
||||
if (rv) {
|
||||
csio_err(hw, "IRQ request failed for vec %d err:%d\n",
|
||||
entryp[k].vector, rv);
|
||||
goto err;
|
||||
pci_irq_vector(pdev, k), rv);
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
entryp[k++].dev_id = (void *)hw;
|
||||
entryp[k++].dev_id = hw;
|
||||
|
||||
rv = request_irq(entryp[k].vector, csio_fwevt_isr, 0,
|
||||
rv = request_irq(pci_irq_vector(pdev, k), csio_fwevt_isr, 0,
|
||||
entryp[k].desc, hw);
|
||||
if (rv) {
|
||||
csio_err(hw, "IRQ request failed for vec %d err:%d\n",
|
||||
entryp[k].vector, rv);
|
||||
goto err;
|
||||
pci_irq_vector(pdev, k), rv);
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
entryp[k++].dev_id = (void *)hw;
|
||||
|
@ -429,51 +427,31 @@ csio_request_irqs(struct csio_hw *hw)
|
|||
struct csio_scsi_qset *sqset = &hw->sqset[i][j];
|
||||
struct csio_q *q = hw->wrm.q_arr[sqset->iq_idx];
|
||||
|
||||
rv = request_irq(entryp[k].vector, csio_scsi_isr, 0,
|
||||
rv = request_irq(pci_irq_vector(pdev, k), csio_scsi_isr, 0,
|
||||
entryp[k].desc, q);
|
||||
if (rv) {
|
||||
csio_err(hw,
|
||||
"IRQ request failed for vec %d err:%d\n",
|
||||
entryp[k].vector, rv);
|
||||
goto err;
|
||||
pci_irq_vector(pdev, k), rv);
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
entryp[k].dev_id = (void *)q;
|
||||
entryp[k].dev_id = q;
|
||||
|
||||
} /* for all scsi cpus */
|
||||
} /* for all ports */
|
||||
|
||||
out:
|
||||
hw->flags |= CSIO_HWF_HOST_INTR_ENABLED;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = 0; i < k; i++) {
|
||||
entryp = &hw->msix_entries[i];
|
||||
free_irq(entryp->vector, entryp->dev_id);
|
||||
}
|
||||
pci_disable_msix(hw->pdev);
|
||||
|
||||
out_free_irqs:
|
||||
for (i = 0; i < k; i++)
|
||||
free_irq(pci_irq_vector(pdev, i), hw->msix_entries[i].dev_id);
|
||||
pci_free_irq_vectors(hw->pdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
csio_disable_msix(struct csio_hw *hw, bool free)
|
||||
{
|
||||
int i;
|
||||
struct csio_msix_entries *entryp;
|
||||
int cnt = hw->num_sqsets + CSIO_EXTRA_VECS;
|
||||
|
||||
if (free) {
|
||||
for (i = 0; i < cnt; i++) {
|
||||
entryp = &hw->msix_entries[i];
|
||||
free_irq(entryp->vector, entryp->dev_id);
|
||||
}
|
||||
}
|
||||
pci_disable_msix(hw->pdev);
|
||||
}
|
||||
|
||||
/* Reduce per-port max possible CPUs */
|
||||
static void
|
||||
csio_reduce_sqsets(struct csio_hw *hw, int cnt)
|
||||
|
@ -500,10 +478,9 @@ static int
|
|||
csio_enable_msix(struct csio_hw *hw)
|
||||
{
|
||||
int i, j, k, n, min, cnt;
|
||||
struct csio_msix_entries *entryp;
|
||||
struct msix_entry *entries;
|
||||
int extra = CSIO_EXTRA_VECS;
|
||||
struct csio_scsi_cpu_info *info;
|
||||
struct irq_affinity desc = { .pre_vectors = 2 };
|
||||
|
||||
min = hw->num_pports + extra;
|
||||
cnt = hw->num_sqsets + extra;
|
||||
|
@ -512,50 +489,35 @@ csio_enable_msix(struct csio_hw *hw)
|
|||
if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS || !csio_is_hw_master(hw))
|
||||
cnt = min_t(uint8_t, hw->cfg_niq, cnt);
|
||||
|
||||
entries = kzalloc(sizeof(struct msix_entry) * cnt, GFP_KERNEL);
|
||||
if (!entries)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
entries[i].entry = (uint16_t)i;
|
||||
|
||||
csio_dbg(hw, "FW supp #niq:%d, trying %d msix's\n", hw->cfg_niq, cnt);
|
||||
|
||||
cnt = pci_enable_msix_range(hw->pdev, entries, min, cnt);
|
||||
if (cnt < 0) {
|
||||
kfree(entries);
|
||||
cnt = pci_alloc_irq_vectors_affinity(hw->pdev, min, cnt,
|
||||
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc);
|
||||
if (cnt < 0)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
if (cnt < (hw->num_sqsets + extra)) {
|
||||
csio_dbg(hw, "Reducing sqsets to %d\n", cnt - extra);
|
||||
csio_reduce_sqsets(hw, cnt - extra);
|
||||
}
|
||||
|
||||
/* Save off vectors */
|
||||
for (i = 0; i < cnt; i++) {
|
||||
entryp = &hw->msix_entries[i];
|
||||
entryp->vector = entries[i].vector;
|
||||
}
|
||||
|
||||
/* Distribute vectors */
|
||||
k = 0;
|
||||
csio_set_nondata_intr_idx(hw, entries[k].entry);
|
||||
csio_set_mb_intr_idx(csio_hw_to_mbm(hw), entries[k++].entry);
|
||||
csio_set_fwevt_intr_idx(hw, entries[k++].entry);
|
||||
csio_set_nondata_intr_idx(hw, k);
|
||||
csio_set_mb_intr_idx(csio_hw_to_mbm(hw), k++);
|
||||
csio_set_fwevt_intr_idx(hw, k++);
|
||||
|
||||
for (i = 0; i < hw->num_pports; i++) {
|
||||
info = &hw->scsi_cpu_info[i];
|
||||
|
||||
for (j = 0; j < hw->num_scsi_msix_cpus; j++) {
|
||||
n = (j % info->max_cpus) + k;
|
||||
hw->sqset[i][j].intr_idx = entries[n].entry;
|
||||
hw->sqset[i][j].intr_idx = n;
|
||||
}
|
||||
|
||||
k += info->max_cpus;
|
||||
}
|
||||
|
||||
kfree(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -597,22 +559,26 @@ csio_intr_disable(struct csio_hw *hw, bool free)
|
|||
{
|
||||
csio_hw_intr_disable(hw);
|
||||
|
||||
switch (hw->intr_mode) {
|
||||
case CSIO_IM_MSIX:
|
||||
csio_disable_msix(hw, free);
|
||||
break;
|
||||
case CSIO_IM_MSI:
|
||||
if (free)
|
||||
free_irq(hw->pdev->irq, hw);
|
||||
pci_disable_msi(hw->pdev);
|
||||
break;
|
||||
case CSIO_IM_INTX:
|
||||
if (free)
|
||||
free_irq(hw->pdev->irq, hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (free) {
|
||||
int i;
|
||||
|
||||
switch (hw->intr_mode) {
|
||||
case CSIO_IM_MSIX:
|
||||
for (i = 0; i < hw->num_sqsets + CSIO_EXTRA_VECS; i++) {
|
||||
free_irq(pci_irq_vector(hw->pdev, i),
|
||||
hw->msix_entries[i].dev_id);
|
||||
}
|
||||
break;
|
||||
case CSIO_IM_MSI:
|
||||
case CSIO_IM_INTX:
|
||||
free_irq(pci_irq_vector(hw->pdev, 0), hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pci_free_irq_vectors(hw->pdev);
|
||||
hw->intr_mode = CSIO_IM_NONE;
|
||||
hw->flags &= ~CSIO_HWF_HOST_INTR_ENABLED;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ static unsigned int dbg_level;
|
|||
#include "../libcxgbi.h"
|
||||
|
||||
#define DRV_MODULE_NAME "cxgb4i"
|
||||
#define DRV_MODULE_DESC "Chelsio T4/T5 iSCSI Driver"
|
||||
#define DRV_MODULE_DESC "Chelsio T4-T6 iSCSI Driver"
|
||||
#define DRV_MODULE_VERSION "0.9.5-ko"
|
||||
#define DRV_MODULE_RELDATE "Apr. 2015"
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef _CXLFLASH_COMMON_H
|
||||
#define _CXLFLASH_COMMON_H
|
||||
|
||||
#include <linux/irq_poll.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -24,30 +25,32 @@
|
|||
|
||||
extern const struct file_operations cxlflash_cxl_fops;
|
||||
|
||||
#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */
|
||||
#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */
|
||||
#define MAX_FC_PORTS CXLFLASH_MAX_FC_PORTS /* max ports per AFU */
|
||||
#define LEGACY_FC_PORTS 2 /* legacy ports per AFU */
|
||||
|
||||
#define CXLFLASH_BLOCK_SIZE 4096 /* 4K blocks */
|
||||
#define CHAN2PORTBANK(_x) ((_x) >> ilog2(CXLFLASH_NUM_FC_PORTS_PER_BANK))
|
||||
#define CHAN2BANKPORT(_x) ((_x) & (CXLFLASH_NUM_FC_PORTS_PER_BANK - 1))
|
||||
|
||||
#define CHAN2PORTMASK(_x) (1 << (_x)) /* channel to port mask */
|
||||
#define PORTMASK2CHAN(_x) (ilog2((_x))) /* port mask to channel */
|
||||
#define PORTNUM2CHAN(_x) ((_x) - 1) /* port number to channel */
|
||||
|
||||
#define CXLFLASH_BLOCK_SIZE 4096 /* 4K blocks */
|
||||
#define CXLFLASH_MAX_XFER_SIZE 16777216 /* 16MB transfer */
|
||||
#define CXLFLASH_MAX_SECTORS (CXLFLASH_MAX_XFER_SIZE/512) /* SCSI wants
|
||||
max_sectors
|
||||
in units of
|
||||
512 byte
|
||||
sectors
|
||||
*/
|
||||
* max_sectors
|
||||
* in units of
|
||||
* 512 byte
|
||||
* sectors
|
||||
*/
|
||||
|
||||
#define MAX_RHT_PER_CONTEXT (PAGE_SIZE / sizeof(struct sisl_rht_entry))
|
||||
|
||||
/* AFU command retry limit */
|
||||
#define MC_RETRY_CNT 5 /* sufficient for SCSI check and
|
||||
certain AFU errors */
|
||||
#define MC_RETRY_CNT 5 /* Sufficient for SCSI and certain AFU errors */
|
||||
|
||||
/* Command management definitions */
|
||||
#define CXLFLASH_NUM_CMDS (2 * CXLFLASH_MAX_CMDS) /* Must be a pow2 for
|
||||
alignment and more
|
||||
efficient array
|
||||
index derivation
|
||||
*/
|
||||
|
||||
#define CXLFLASH_MAX_CMDS 256
|
||||
#define CXLFLASH_MAX_CMDS_PER_LUN CXLFLASH_MAX_CMDS
|
||||
|
||||
|
@ -57,10 +60,16 @@ extern const struct file_operations cxlflash_cxl_fops;
|
|||
/* SQ for master issued cmds */
|
||||
#define NUM_SQ_ENTRY CXLFLASH_MAX_CMDS
|
||||
|
||||
/* Hardware queue definitions */
|
||||
#define CXLFLASH_DEF_HWQS 1
|
||||
#define CXLFLASH_MAX_HWQS 8
|
||||
#define PRIMARY_HWQ 0
|
||||
|
||||
|
||||
static inline void check_sizes(void)
|
||||
{
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_NUM_CMDS);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_NUM_FC_PORTS_PER_BANK);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_MAX_CMDS);
|
||||
}
|
||||
|
||||
/* AFU defines a fixed size of 4K for command buffers (borrow 4K page define) */
|
||||
|
@ -80,11 +89,20 @@ enum cxlflash_init_state {
|
|||
};
|
||||
|
||||
enum cxlflash_state {
|
||||
STATE_PROBING, /* Initial state during probe */
|
||||
STATE_PROBED, /* Temporary state, probe completed but EEH occurred */
|
||||
STATE_NORMAL, /* Normal running state, everything good */
|
||||
STATE_RESET, /* Reset state, trying to reset/recover */
|
||||
STATE_FAILTERM /* Failed/terminating state, error out users/threads */
|
||||
};
|
||||
|
||||
enum cxlflash_hwq_mode {
|
||||
HWQ_MODE_RR, /* Roundrobin (default) */
|
||||
HWQ_MODE_TAG, /* Distribute based on block MQ tag */
|
||||
HWQ_MODE_CPU, /* CPU affinity */
|
||||
MAX_HWQ_MODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Each context has its own set of resource handles that is visible
|
||||
* only from that context.
|
||||
|
@ -92,11 +110,11 @@ enum cxlflash_state {
|
|||
|
||||
struct cxlflash_cfg {
|
||||
struct afu *afu;
|
||||
struct cxl_context *mcctx;
|
||||
|
||||
struct pci_dev *dev;
|
||||
struct pci_device_id *dev_id;
|
||||
struct Scsi_Host *host;
|
||||
int num_fc_ports;
|
||||
|
||||
ulong cxlflash_regs_pci;
|
||||
|
||||
|
@ -117,7 +135,7 @@ struct cxlflash_cfg {
|
|||
struct file_operations cxl_fops;
|
||||
|
||||
/* Parameters that are LUN table related */
|
||||
int last_lun_index[CXLFLASH_NUM_FC_PORTS];
|
||||
int last_lun_index[MAX_FC_PORTS];
|
||||
int promote_lun_index;
|
||||
struct list_head lluns; /* list of llun_info structs */
|
||||
|
||||
|
@ -134,6 +152,8 @@ struct afu_cmd {
|
|||
struct afu *parent;
|
||||
struct scsi_cmnd *scp;
|
||||
struct completion cevent;
|
||||
struct list_head queue;
|
||||
u32 hwq_index;
|
||||
|
||||
u8 cmd_tmf:1;
|
||||
|
||||
|
@ -156,7 +176,7 @@ static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc)
|
|||
return afuc;
|
||||
}
|
||||
|
||||
struct afu {
|
||||
struct hwq {
|
||||
/* Stuff requiring alignment go first. */
|
||||
struct sisl_ioarcb sq[NUM_SQ_ENTRY]; /* 16K SQ */
|
||||
u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */
|
||||
|
@ -164,40 +184,67 @@ struct afu {
|
|||
/* Beware of alignment till here. Preferably introduce new
|
||||
* fields after this point
|
||||
*/
|
||||
|
||||
int (*send_cmd)(struct afu *, struct afu_cmd *);
|
||||
void (*context_reset)(struct afu_cmd *);
|
||||
|
||||
/* AFU HW */
|
||||
struct afu *afu;
|
||||
struct cxl_context *ctx;
|
||||
struct cxl_ioctl_start_work work;
|
||||
struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */
|
||||
struct sisl_host_map __iomem *host_map; /* MC host map */
|
||||
struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */
|
||||
|
||||
ctx_hndl_t ctx_hndl; /* master's context handle */
|
||||
u32 index; /* Index of this hwq */
|
||||
|
||||
atomic_t hsq_credits;
|
||||
spinlock_t hsq_slock;
|
||||
struct sisl_ioarcb *hsq_start;
|
||||
struct sisl_ioarcb *hsq_end;
|
||||
struct sisl_ioarcb *hsq_curr;
|
||||
spinlock_t hrrq_slock;
|
||||
u64 *hrrq_start;
|
||||
u64 *hrrq_end;
|
||||
u64 *hrrq_curr;
|
||||
bool toggle;
|
||||
atomic_t cmds_active; /* Number of currently active AFU commands */
|
||||
|
||||
s64 room;
|
||||
spinlock_t rrin_slock; /* Lock to rrin queuing and cmd_room updates */
|
||||
|
||||
struct irq_poll irqpoll;
|
||||
} __aligned(cache_line_size());
|
||||
|
||||
struct afu {
|
||||
struct hwq hwqs[CXLFLASH_MAX_HWQS];
|
||||
int (*send_cmd)(struct afu *, struct afu_cmd *);
|
||||
void (*context_reset)(struct afu_cmd *);
|
||||
|
||||
/* AFU HW */
|
||||
struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */
|
||||
|
||||
atomic_t cmds_active; /* Number of currently active AFU commands */
|
||||
u64 hb;
|
||||
u32 internal_lun; /* User-desired LUN mode for this AFU */
|
||||
|
||||
u32 num_hwqs; /* Number of hardware queues */
|
||||
u32 desired_hwqs; /* Desired h/w queues, effective on AFU reset */
|
||||
enum cxlflash_hwq_mode hwq_mode; /* Steering mode for h/w queues */
|
||||
u32 hwq_rr_count; /* Count to distribute traffic for roundrobin */
|
||||
|
||||
char version[16];
|
||||
u64 interface_version;
|
||||
|
||||
u32 irqpoll_weight;
|
||||
struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */
|
||||
|
||||
};
|
||||
|
||||
static inline struct hwq *get_hwq(struct afu *afu, u32 index)
|
||||
{
|
||||
WARN_ON(index >= CXLFLASH_MAX_HWQS);
|
||||
|
||||
return &afu->hwqs[index];
|
||||
}
|
||||
|
||||
static inline bool afu_is_irqpoll_enabled(struct afu *afu)
|
||||
{
|
||||
return !!afu->irqpoll_weight;
|
||||
}
|
||||
|
||||
static inline bool afu_is_cmd_mode(struct afu *afu, u64 cmd_mode)
|
||||
{
|
||||
u64 afu_cap = afu->interface_version >> SISL_INTVER_CAP_SHIFT;
|
||||
|
@ -223,14 +270,36 @@ static inline u64 lun_to_lunid(u64 lun)
|
|||
return be64_to_cpu(lun_id);
|
||||
}
|
||||
|
||||
int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8);
|
||||
static inline struct fc_port_bank __iomem *get_fc_port_bank(
|
||||
struct cxlflash_cfg *cfg, int i)
|
||||
{
|
||||
struct afu *afu = cfg->afu;
|
||||
|
||||
return &afu->afu_map->global.bank[CHAN2PORTBANK(i)];
|
||||
}
|
||||
|
||||
static inline __be64 __iomem *get_fc_port_regs(struct cxlflash_cfg *cfg, int i)
|
||||
{
|
||||
struct fc_port_bank __iomem *fcpb = get_fc_port_bank(cfg, i);
|
||||
|
||||
return &fcpb->fc_port_regs[CHAN2BANKPORT(i)][0];
|
||||
}
|
||||
|
||||
static inline __be64 __iomem *get_fc_port_luns(struct cxlflash_cfg *cfg, int i)
|
||||
{
|
||||
struct fc_port_bank __iomem *fcpb = get_fc_port_bank(cfg, i);
|
||||
|
||||
return &fcpb->fc_port_luns[CHAN2BANKPORT(i)][0];
|
||||
}
|
||||
|
||||
int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t c, res_hndl_t r, u8 mode);
|
||||
void cxlflash_list_init(void);
|
||||
void cxlflash_term_global_luns(void);
|
||||
void cxlflash_free_errpage(void);
|
||||
int cxlflash_ioctl(struct scsi_device *, int, void __user *);
|
||||
void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *);
|
||||
int cxlflash_mark_contexts_error(struct cxlflash_cfg *);
|
||||
void cxlflash_term_local_luns(struct cxlflash_cfg *);
|
||||
void cxlflash_restore_luntable(struct cxlflash_cfg *);
|
||||
int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
|
||||
void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg);
|
||||
int cxlflash_mark_contexts_error(struct cxlflash_cfg *cfg);
|
||||
void cxlflash_term_local_luns(struct cxlflash_cfg *cfg);
|
||||
void cxlflash_restore_luntable(struct cxlflash_cfg *cfg);
|
||||
|
||||
#endif /* ifndef _CXLFLASH_COMMON_H */
|
||||
|
|
|
@ -252,7 +252,7 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
|
|||
* in unpacked, AFU-friendly format, and hang LUN reference in
|
||||
* the sdev.
|
||||
*/
|
||||
lli->port_sel |= CHAN2PORT(chan);
|
||||
lli->port_sel |= CHAN2PORTMASK(chan);
|
||||
lli->lun_id[chan] = lun_to_lunid(sdev->lun);
|
||||
sdev->hostdata = lli;
|
||||
} else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) {
|
||||
|
@ -264,7 +264,7 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
|
|||
* tracking when no more references exist.
|
||||
*/
|
||||
sdev->hostdata = NULL;
|
||||
lli->port_sel &= ~CHAN2PORT(chan);
|
||||
lli->port_sel &= ~CHAN2PORTMASK(chan);
|
||||
if (lli->port_sel == 0U)
|
||||
lli->in_table = false;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37,8 +37,6 @@
|
|||
|
||||
#define CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT (120 * HZ)
|
||||
|
||||
#define NUM_FC_PORTS CXLFLASH_NUM_FC_PORTS /* ports per AFU */
|
||||
|
||||
/* FC defines */
|
||||
#define FC_MTIP_CMDCONFIG 0x010
|
||||
#define FC_MTIP_STATUS 0x018
|
||||
|
|
|
@ -90,15 +90,15 @@ struct sisl_rc {
|
|||
#define SISL_AFU_RC_RHT_UNALIGNED 0x02U /* should never happen */
|
||||
#define SISL_AFU_RC_RHT_OUT_OF_BOUNDS 0x03u /* user error */
|
||||
#define SISL_AFU_RC_RHT_DMA_ERR 0x04u /* see afu_extra
|
||||
may retry if afu_retry is off
|
||||
possible on master exit
|
||||
* may retry if afu_retry is off
|
||||
* possible on master exit
|
||||
*/
|
||||
#define SISL_AFU_RC_RHT_RW_PERM 0x05u /* no RW perms, user error */
|
||||
#define SISL_AFU_RC_LXT_UNALIGNED 0x12U /* should never happen */
|
||||
#define SISL_AFU_RC_LXT_OUT_OF_BOUNDS 0x13u /* user error */
|
||||
#define SISL_AFU_RC_LXT_DMA_ERR 0x14u /* see afu_extra
|
||||
may retry if afu_retry is off
|
||||
possible on master exit
|
||||
* may retry if afu_retry is off
|
||||
* possible on master exit
|
||||
*/
|
||||
#define SISL_AFU_RC_LXT_RW_PERM 0x15u /* no RW perms, user error */
|
||||
|
||||
|
@ -111,11 +111,11 @@ struct sisl_rc {
|
|||
*/
|
||||
#define SISL_AFU_RC_NO_CHANNELS 0x20U /* see afu_extra, may retry */
|
||||
#define SISL_AFU_RC_CAP_VIOLATION 0x21U /* either user error or
|
||||
afu reset/master restart
|
||||
* afu reset/master restart
|
||||
*/
|
||||
#define SISL_AFU_RC_OUT_OF_DATA_BUFS 0x30U /* always retry */
|
||||
#define SISL_AFU_RC_DATA_DMA_ERR 0x31U /* see afu_extra
|
||||
may retry if afu_retry is off
|
||||
* may retry if afu_retry is off
|
||||
*/
|
||||
|
||||
u8 scsi_rc; /* SCSI status byte, retry as appropriate */
|
||||
|
@ -149,8 +149,9 @@ struct sisl_rc {
|
|||
#define SISL_FC_RC_ABORTFAIL 0x59 /* pending abort completed w/fail */
|
||||
#define SISL_FC_RC_RESID 0x5A /* ioasa underrun/overrun flags set */
|
||||
#define SISL_FC_RC_RESIDERR 0x5B /* actual data len does not match SCSI
|
||||
reported len, possibly due to dropped
|
||||
frames */
|
||||
* reported len, possibly due to dropped
|
||||
* frames
|
||||
*/
|
||||
#define SISL_FC_RC_TGTABORT 0x5C /* command aborted by target */
|
||||
};
|
||||
|
||||
|
@ -227,10 +228,10 @@ struct sisl_ioasa {
|
|||
|
||||
/* per context host transport MMIO */
|
||||
struct sisl_host_map {
|
||||
__be64 endian_ctrl; /* Per context Endian Control. The AFU will
|
||||
* operate on whatever the context is of the
|
||||
* host application.
|
||||
*/
|
||||
__be64 endian_ctrl; /* Per context Endian Control. The AFU will
|
||||
* operate on whatever the context is of the
|
||||
* host application.
|
||||
*/
|
||||
|
||||
__be64 intr_status; /* this sends LISN# programmed in ctx_ctrl.
|
||||
* Only recovery in a PERM_ERR is a context
|
||||
|
@ -292,28 +293,54 @@ struct sisl_ctrl_map {
|
|||
/* single copy global regs */
|
||||
struct sisl_global_regs {
|
||||
__be64 aintr_status;
|
||||
/* In cxlflash, each FC port/link gets a byte of status */
|
||||
#define SISL_ASTATUS_FC0_OTHER 0x8000ULL /* b48, other err,
|
||||
FC_ERRCAP[31:20] */
|
||||
#define SISL_ASTATUS_FC0_LOGO 0x4000ULL /* b49, target sent FLOGI/PLOGI/LOGO
|
||||
while logged in */
|
||||
#define SISL_ASTATUS_FC0_CRC_T 0x2000ULL /* b50, CRC threshold exceeded */
|
||||
#define SISL_ASTATUS_FC0_LOGI_R 0x1000ULL /* b51, login state machine timed out
|
||||
and retrying */
|
||||
#define SISL_ASTATUS_FC0_LOGI_F 0x0800ULL /* b52, login failed,
|
||||
FC_ERROR[19:0] */
|
||||
#define SISL_ASTATUS_FC0_LOGI_S 0x0400ULL /* b53, login succeeded */
|
||||
#define SISL_ASTATUS_FC0_LINK_DN 0x0200ULL /* b54, link online to offline */
|
||||
#define SISL_ASTATUS_FC0_LINK_UP 0x0100ULL /* b55, link offline to online */
|
||||
/*
|
||||
* In cxlflash, FC port/link are arranged in port pairs, each
|
||||
* gets a byte of status:
|
||||
*
|
||||
* *_OTHER: other err, FC_ERRCAP[31:20]
|
||||
* *_LOGO: target sent FLOGI/PLOGI/LOGO while logged in
|
||||
* *_CRC_T: CRC threshold exceeded
|
||||
* *_LOGI_R: login state machine timed out and retrying
|
||||
* *_LOGI_F: login failed, FC_ERROR[19:0]
|
||||
* *_LOGI_S: login succeeded
|
||||
* *_LINK_DN: link online to offline
|
||||
* *_LINK_UP: link offline to online
|
||||
*/
|
||||
#define SISL_ASTATUS_FC2_OTHER 0x80000000ULL /* b32 */
|
||||
#define SISL_ASTATUS_FC2_LOGO 0x40000000ULL /* b33 */
|
||||
#define SISL_ASTATUS_FC2_CRC_T 0x20000000ULL /* b34 */
|
||||
#define SISL_ASTATUS_FC2_LOGI_R 0x10000000ULL /* b35 */
|
||||
#define SISL_ASTATUS_FC2_LOGI_F 0x08000000ULL /* b36 */
|
||||
#define SISL_ASTATUS_FC2_LOGI_S 0x04000000ULL /* b37 */
|
||||
#define SISL_ASTATUS_FC2_LINK_DN 0x02000000ULL /* b38 */
|
||||
#define SISL_ASTATUS_FC2_LINK_UP 0x01000000ULL /* b39 */
|
||||
|
||||
#define SISL_ASTATUS_FC1_OTHER 0x0080ULL /* b56 */
|
||||
#define SISL_ASTATUS_FC1_LOGO 0x0040ULL /* b57 */
|
||||
#define SISL_ASTATUS_FC1_CRC_T 0x0020ULL /* b58 */
|
||||
#define SISL_ASTATUS_FC1_LOGI_R 0x0010ULL /* b59 */
|
||||
#define SISL_ASTATUS_FC1_LOGI_F 0x0008ULL /* b60 */
|
||||
#define SISL_ASTATUS_FC1_LOGI_S 0x0004ULL /* b61 */
|
||||
#define SISL_ASTATUS_FC1_LINK_DN 0x0002ULL /* b62 */
|
||||
#define SISL_ASTATUS_FC1_LINK_UP 0x0001ULL /* b63 */
|
||||
#define SISL_ASTATUS_FC3_OTHER 0x00800000ULL /* b40 */
|
||||
#define SISL_ASTATUS_FC3_LOGO 0x00400000ULL /* b41 */
|
||||
#define SISL_ASTATUS_FC3_CRC_T 0x00200000ULL /* b42 */
|
||||
#define SISL_ASTATUS_FC3_LOGI_R 0x00100000ULL /* b43 */
|
||||
#define SISL_ASTATUS_FC3_LOGI_F 0x00080000ULL /* b44 */
|
||||
#define SISL_ASTATUS_FC3_LOGI_S 0x00040000ULL /* b45 */
|
||||
#define SISL_ASTATUS_FC3_LINK_DN 0x00020000ULL /* b46 */
|
||||
#define SISL_ASTATUS_FC3_LINK_UP 0x00010000ULL /* b47 */
|
||||
|
||||
#define SISL_ASTATUS_FC0_OTHER 0x00008000ULL /* b48 */
|
||||
#define SISL_ASTATUS_FC0_LOGO 0x00004000ULL /* b49 */
|
||||
#define SISL_ASTATUS_FC0_CRC_T 0x00002000ULL /* b50 */
|
||||
#define SISL_ASTATUS_FC0_LOGI_R 0x00001000ULL /* b51 */
|
||||
#define SISL_ASTATUS_FC0_LOGI_F 0x00000800ULL /* b52 */
|
||||
#define SISL_ASTATUS_FC0_LOGI_S 0x00000400ULL /* b53 */
|
||||
#define SISL_ASTATUS_FC0_LINK_DN 0x00000200ULL /* b54 */
|
||||
#define SISL_ASTATUS_FC0_LINK_UP 0x00000100ULL /* b55 */
|
||||
|
||||
#define SISL_ASTATUS_FC1_OTHER 0x00000080ULL /* b56 */
|
||||
#define SISL_ASTATUS_FC1_LOGO 0x00000040ULL /* b57 */
|
||||
#define SISL_ASTATUS_FC1_CRC_T 0x00000020ULL /* b58 */
|
||||
#define SISL_ASTATUS_FC1_LOGI_R 0x00000010ULL /* b59 */
|
||||
#define SISL_ASTATUS_FC1_LOGI_F 0x00000008ULL /* b60 */
|
||||
#define SISL_ASTATUS_FC1_LOGI_S 0x00000004ULL /* b61 */
|
||||
#define SISL_ASTATUS_FC1_LINK_DN 0x00000002ULL /* b62 */
|
||||
#define SISL_ASTATUS_FC1_LINK_UP 0x00000001ULL /* b63 */
|
||||
|
||||
#define SISL_FC_INTERNAL_UNMASK 0x0000000300000000ULL /* 1 means unmasked */
|
||||
#define SISL_FC_INTERNAL_MASK ~(SISL_FC_INTERNAL_UNMASK)
|
||||
|
@ -325,7 +352,7 @@ struct sisl_global_regs {
|
|||
#define SISL_STATUS_SHUTDOWN_ACTIVE 0x0000000000000010ULL
|
||||
#define SISL_STATUS_SHUTDOWN_COMPLETE 0x0000000000000020ULL
|
||||
|
||||
#define SISL_ASTATUS_UNMASK 0xFFFFULL /* 1 means unmasked */
|
||||
#define SISL_ASTATUS_UNMASK 0xFFFFFFFFULL /* 1 means unmasked */
|
||||
#define SISL_ASTATUS_MASK ~(SISL_ASTATUS_UNMASK) /* 1 means masked */
|
||||
|
||||
__be64 aintr_clear;
|
||||
|
@ -367,9 +394,18 @@ struct sisl_global_regs {
|
|||
#define SISL_INTVER_CAP_RESERVED_CMD_MODE_B 0x100000000000ULL
|
||||
};
|
||||
|
||||
#define CXLFLASH_NUM_FC_PORTS 2
|
||||
#define CXLFLASH_MAX_CONTEXT 512 /* how many contexts per afu */
|
||||
#define CXLFLASH_NUM_VLUNS 512
|
||||
#define CXLFLASH_NUM_FC_PORTS_PER_BANK 2 /* fixed # of ports per bank */
|
||||
#define CXLFLASH_MAX_FC_BANKS 2 /* max # of banks supported */
|
||||
#define CXLFLASH_MAX_FC_PORTS (CXLFLASH_NUM_FC_PORTS_PER_BANK * \
|
||||
CXLFLASH_MAX_FC_BANKS)
|
||||
#define CXLFLASH_MAX_CONTEXT 512 /* number of contexts per AFU */
|
||||
#define CXLFLASH_NUM_VLUNS 512 /* number of vluns per AFU/port */
|
||||
#define CXLFLASH_NUM_REGS 512 /* number of registers per port */
|
||||
|
||||
struct fc_port_bank {
|
||||
__be64 fc_port_regs[CXLFLASH_NUM_FC_PORTS_PER_BANK][CXLFLASH_NUM_REGS];
|
||||
__be64 fc_port_luns[CXLFLASH_NUM_FC_PORTS_PER_BANK][CXLFLASH_NUM_VLUNS];
|
||||
};
|
||||
|
||||
struct sisl_global_map {
|
||||
union {
|
||||
|
@ -379,11 +415,9 @@ struct sisl_global_map {
|
|||
|
||||
char page1[SIZE_4K]; /* page 1 */
|
||||
|
||||
/* pages 2 & 3 */
|
||||
__be64 fc_regs[CXLFLASH_NUM_FC_PORTS][CXLFLASH_NUM_VLUNS];
|
||||
struct fc_port_bank bank[CXLFLASH_MAX_FC_BANKS]; /* pages 2 - 9 */
|
||||
|
||||
/* pages 4 & 5 (lun tbl) */
|
||||
__be64 fc_port[CXLFLASH_NUM_FC_PORTS][CXLFLASH_NUM_VLUNS];
|
||||
/* pages 10 - 15 are reserved */
|
||||
|
||||
};
|
||||
|
||||
|
@ -402,7 +436,7 @@ struct sisl_global_map {
|
|||
* | 64 KB Global |
|
||||
* | Trusted Process accessible |
|
||||
* +-------------------------------+
|
||||
*/
|
||||
*/
|
||||
struct cxlflash_afu_map {
|
||||
union {
|
||||
struct sisl_host_map host;
|
||||
|
@ -478,7 +512,9 @@ struct sisl_rht_entry_f1 {
|
|||
|
||||
#define PORT0 0x01U
|
||||
#define PORT1 0x02U
|
||||
#define BOTH_PORTS (PORT0 | PORT1)
|
||||
#define PORT2 0x04U
|
||||
#define PORT3 0x08U
|
||||
#define PORT_MASK(_n) ((1 << (_n)) - 1)
|
||||
|
||||
/* AFU Sync Mode byte */
|
||||
#define AFU_LW_SYNC 0x0U
|
||||
|
|
|
@ -78,17 +78,18 @@ void cxlflash_free_errpage(void)
|
|||
* memory freed. This is accomplished by putting the contexts in error
|
||||
* state which will notify the user and let them 'drive' the tear down.
|
||||
* Meanwhile, this routine camps until all user contexts have been removed.
|
||||
*
|
||||
* Note that the main loop in this routine will always execute at least once
|
||||
* to flush the reset_waitq.
|
||||
*/
|
||||
void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg)
|
||||
{
|
||||
struct device *dev = &cfg->dev->dev;
|
||||
int i, found;
|
||||
int i, found = true;
|
||||
|
||||
cxlflash_mark_contexts_error(cfg);
|
||||
|
||||
while (true) {
|
||||
found = false;
|
||||
|
||||
for (i = 0; i < MAX_CONTEXT; i++)
|
||||
if (cfg->ctx_tbl[i]) {
|
||||
found = true;
|
||||
|
@ -102,6 +103,7 @@ void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg)
|
|||
__func__);
|
||||
wake_up_all(&cfg->reset_waitq);
|
||||
ssleep(1);
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,6 +254,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
|
|||
struct afu *afu = cfg->afu;
|
||||
struct sisl_ctrl_map __iomem *ctrl_map = ctxi->ctrl_map;
|
||||
int rc = 0;
|
||||
struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
|
||||
u64 val;
|
||||
|
||||
/* Unlock cap and restrict user to read/write cmds in translated mode */
|
||||
|
@ -268,7 +271,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
|
|||
|
||||
/* Set up MMIO registers pointing to the RHT */
|
||||
writeq_be((u64)ctxi->rht_start, &ctrl_map->rht_start);
|
||||
val = SISL_RHT_CNT_ID((u64)MAX_RHT_PER_CONTEXT, (u64)(afu->ctx_hndl));
|
||||
val = SISL_RHT_CNT_ID((u64)MAX_RHT_PER_CONTEXT, (u64)(hwq->ctx_hndl));
|
||||
writeq_be(val, &ctrl_map->rht_cnt_id);
|
||||
out:
|
||||
dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
|
||||
|
@ -1624,6 +1627,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
|
|||
struct afu *afu = cfg->afu;
|
||||
struct ctx_info *ctxi = NULL;
|
||||
struct mutex *mutex = &cfg->ctx_recovery_mutex;
|
||||
struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
|
||||
u64 flags;
|
||||
u64 ctxid = DECODE_CTXID(recover->context_id),
|
||||
rctxid = recover->context_id;
|
||||
|
@ -1694,7 +1698,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
|
|||
}
|
||||
|
||||
/* Test if in error state */
|
||||
reg = readq_be(&afu->ctrl_map->mbox_r);
|
||||
reg = readq_be(&hwq->ctrl_map->mbox_r);
|
||||
if (reg == -1) {
|
||||
dev_dbg(dev, "%s: MMIO fail, wait for recovery.\n", __func__);
|
||||
|
||||
|
@ -1933,7 +1937,7 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
|
|||
u64 lun_size = 0;
|
||||
u64 last_lba = 0;
|
||||
u64 rsrc_handle = -1;
|
||||
u32 port = CHAN2PORT(sdev->channel);
|
||||
u32 port = CHAN2PORTMASK(sdev->channel);
|
||||
|
||||
int rc = 0;
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ extern struct cxlflash_global global;
|
|||
*/
|
||||
|
||||
/* Chunk size parms: note sislite minimum chunk size is
|
||||
0x10000 LBAs corresponding to a NMASK or 16.
|
||||
*/
|
||||
* 0x10000 LBAs corresponding to a NMASK or 16.
|
||||
*/
|
||||
#define MC_CHUNK_SIZE (1 << MC_RHT_NMASK) /* in LBAs */
|
||||
|
||||
#define CMD_TIMEOUT 30 /* 30 secs */
|
||||
|
@ -33,9 +33,6 @@ extern struct cxlflash_global global;
|
|||
|
||||
#define MAX_SECTOR_UNIT 512 /* max_sector is in 512 byte multiples */
|
||||
|
||||
#define CHAN2PORT(_x) ((_x) + 1)
|
||||
#define PORT2CHAN(_x) ((_x) - 1)
|
||||
|
||||
enum lun_mode {
|
||||
MODE_NONE = 0,
|
||||
MODE_VIRTUAL,
|
||||
|
@ -59,7 +56,7 @@ struct glun_info {
|
|||
|
||||
/* Local (per-adapter) lun_info structure */
|
||||
struct llun_info {
|
||||
u64 lun_id[CXLFLASH_NUM_FC_PORTS]; /* from REPORT_LUNS */
|
||||
u64 lun_id[MAX_FC_PORTS]; /* from REPORT_LUNS */
|
||||
u32 lun_index; /* Index in the LUN table */
|
||||
u32 host_no; /* host_no from Scsi_host */
|
||||
u32 port_sel; /* What port to use for this LUN */
|
||||
|
@ -92,7 +89,8 @@ enum ctx_ctrl {
|
|||
struct ctx_info {
|
||||
struct sisl_ctrl_map __iomem *ctrl_map; /* initialized at startup */
|
||||
struct sisl_rht_entry *rht_start; /* 1 page (req'd for alignment),
|
||||
alloc/free on attach/detach */
|
||||
* alloc/free on attach/detach
|
||||
*/
|
||||
u32 rht_out; /* Number of checked out RHT entries */
|
||||
u32 rht_perms; /* User-defined permissions for RHT entries */
|
||||
struct llun_info **rht_lun; /* Mapping of RHT entries to LUNs */
|
||||
|
@ -120,34 +118,40 @@ struct cxlflash_global {
|
|||
struct page *err_page; /* One page of all 0xF for error notification */
|
||||
};
|
||||
|
||||
int cxlflash_vlun_resize(struct scsi_device *, struct dk_cxlflash_resize *);
|
||||
int _cxlflash_vlun_resize(struct scsi_device *, struct ctx_info *,
|
||||
struct dk_cxlflash_resize *);
|
||||
int cxlflash_vlun_resize(struct scsi_device *sdev,
|
||||
struct dk_cxlflash_resize *resize);
|
||||
int _cxlflash_vlun_resize(struct scsi_device *sdev, struct ctx_info *ctxi,
|
||||
struct dk_cxlflash_resize *resize);
|
||||
|
||||
int cxlflash_disk_release(struct scsi_device *, struct dk_cxlflash_release *);
|
||||
int _cxlflash_disk_release(struct scsi_device *, struct ctx_info *,
|
||||
struct dk_cxlflash_release *);
|
||||
int cxlflash_disk_release(struct scsi_device *sdev,
|
||||
struct dk_cxlflash_release *release);
|
||||
int _cxlflash_disk_release(struct scsi_device *sdev, struct ctx_info *ctxi,
|
||||
struct dk_cxlflash_release *release);
|
||||
|
||||
int cxlflash_disk_clone(struct scsi_device *, struct dk_cxlflash_clone *);
|
||||
int cxlflash_disk_clone(struct scsi_device *sdev,
|
||||
struct dk_cxlflash_clone *clone);
|
||||
|
||||
int cxlflash_disk_virtual_open(struct scsi_device *, void *);
|
||||
int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg);
|
||||
|
||||
int cxlflash_lun_attach(struct glun_info *, enum lun_mode, bool);
|
||||
void cxlflash_lun_detach(struct glun_info *);
|
||||
int cxlflash_lun_attach(struct glun_info *gli, enum lun_mode mode, bool locked);
|
||||
void cxlflash_lun_detach(struct glun_info *gli);
|
||||
|
||||
struct ctx_info *get_context(struct cxlflash_cfg *, u64, void *, enum ctx_ctrl);
|
||||
void put_context(struct ctx_info *);
|
||||
struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxit, void *arg,
|
||||
enum ctx_ctrl ctrl);
|
||||
void put_context(struct ctx_info *ctxi);
|
||||
|
||||
struct sisl_rht_entry *get_rhte(struct ctx_info *, res_hndl_t,
|
||||
struct llun_info *);
|
||||
struct sisl_rht_entry *get_rhte(struct ctx_info *ctxi, res_hndl_t rhndl,
|
||||
struct llun_info *lli);
|
||||
|
||||
struct sisl_rht_entry *rhte_checkout(struct ctx_info *, struct llun_info *);
|
||||
void rhte_checkin(struct ctx_info *, struct sisl_rht_entry *);
|
||||
struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi,
|
||||
struct llun_info *lli);
|
||||
void rhte_checkin(struct ctx_info *ctxi, struct sisl_rht_entry *rhte);
|
||||
|
||||
void cxlflash_ba_terminate(struct ba_lun *);
|
||||
void cxlflash_ba_terminate(struct ba_lun *ba_lun);
|
||||
|
||||
int cxlflash_manage_lun(struct scsi_device *, struct dk_cxlflash_manage_lun *);
|
||||
int cxlflash_manage_lun(struct scsi_device *sdev,
|
||||
struct dk_cxlflash_manage_lun *manage);
|
||||
|
||||
int check_state(struct cxlflash_cfg *);
|
||||
int check_state(struct cxlflash_cfg *cfg);
|
||||
|
||||
#endif /* ifndef _CXLFLASH_SUPERPIPE_H */
|
||||
|
|
|
@ -819,11 +819,10 @@ int cxlflash_vlun_resize(struct scsi_device *sdev,
|
|||
void cxlflash_restore_luntable(struct cxlflash_cfg *cfg)
|
||||
{
|
||||
struct llun_info *lli, *temp;
|
||||
u32 chan;
|
||||
u32 lind;
|
||||
struct afu *afu = cfg->afu;
|
||||
int k;
|
||||
struct device *dev = &cfg->dev->dev;
|
||||
struct sisl_global_map __iomem *agm = &afu->afu_map->global;
|
||||
__be64 __iomem *fc_port_luns;
|
||||
|
||||
mutex_lock(&global.mutex);
|
||||
|
||||
|
@ -832,33 +831,41 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg)
|
|||
continue;
|
||||
|
||||
lind = lli->lun_index;
|
||||
dev_dbg(dev, "%s: Virtual LUNs on slot %d:\n", __func__, lind);
|
||||
|
||||
if (lli->port_sel == BOTH_PORTS) {
|
||||
writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]);
|
||||
writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]);
|
||||
dev_dbg(dev, "%s: Virtual LUN on slot %d id0=%llx "
|
||||
"id1=%llx\n", __func__, lind,
|
||||
lli->lun_id[0], lli->lun_id[1]);
|
||||
} else {
|
||||
chan = PORT2CHAN(lli->port_sel);
|
||||
writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]);
|
||||
dev_dbg(dev, "%s: Virtual LUN on slot %d chan=%d "
|
||||
"id=%llx\n", __func__, lind, chan,
|
||||
lli->lun_id[chan]);
|
||||
}
|
||||
for (k = 0; k < cfg->num_fc_ports; k++)
|
||||
if (lli->port_sel & (1 << k)) {
|
||||
fc_port_luns = get_fc_port_luns(cfg, k);
|
||||
writeq_be(lli->lun_id[k], &fc_port_luns[lind]);
|
||||
dev_dbg(dev, "\t%d=%llx\n", k, lli->lun_id[k]);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&global.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_num_ports() - compute number of ports from port selection mask
|
||||
* @psm: Port selection mask.
|
||||
*
|
||||
* Return: Population count of port selection mask
|
||||
*/
|
||||
static inline u8 get_num_ports(u32 psm)
|
||||
{
|
||||
static const u8 bits[16] = { 0, 1, 1, 2, 1, 2, 2, 3,
|
||||
1, 2, 2, 3, 2, 3, 3, 4 };
|
||||
|
||||
return bits[psm & 0xf];
|
||||
}
|
||||
|
||||
/**
|
||||
* init_luntable() - write an entry in the LUN table
|
||||
* @cfg: Internal structure associated with the host.
|
||||
* @lli: Per adapter LUN information structure.
|
||||
*
|
||||
* On successful return, a LUN table entry is created.
|
||||
* At the top for LUNs visible on both ports.
|
||||
* At the bottom for LUNs visible only on one port.
|
||||
* On successful return, a LUN table entry is created:
|
||||
* - at the top for LUNs visible on multiple ports.
|
||||
* - at the bottom for LUNs visible only on one port.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure
|
||||
*/
|
||||
|
@ -866,48 +873,68 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli)
|
|||
{
|
||||
u32 chan;
|
||||
u32 lind;
|
||||
u32 nports;
|
||||
int rc = 0;
|
||||
struct afu *afu = cfg->afu;
|
||||
int k;
|
||||
struct device *dev = &cfg->dev->dev;
|
||||
struct sisl_global_map __iomem *agm = &afu->afu_map->global;
|
||||
__be64 __iomem *fc_port_luns;
|
||||
|
||||
mutex_lock(&global.mutex);
|
||||
|
||||
if (lli->in_table)
|
||||
goto out;
|
||||
|
||||
if (lli->port_sel == BOTH_PORTS) {
|
||||
nports = get_num_ports(lli->port_sel);
|
||||
if (nports == 0 || nports > cfg->num_fc_ports) {
|
||||
WARN(1, "Unsupported port configuration nports=%u", nports);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nports > 1) {
|
||||
/*
|
||||
* If this LUN is visible from both ports, we will put
|
||||
* When LUN is visible from multiple ports, we will put
|
||||
* it in the top half of the LUN table.
|
||||
*/
|
||||
if ((cfg->promote_lun_index == cfg->last_lun_index[0]) ||
|
||||
(cfg->promote_lun_index == cfg->last_lun_index[1])) {
|
||||
rc = -ENOSPC;
|
||||
goto out;
|
||||
for (k = 0; k < cfg->num_fc_ports; k++) {
|
||||
if (!(lli->port_sel & (1 << k)))
|
||||
continue;
|
||||
|
||||
if (cfg->promote_lun_index == cfg->last_lun_index[k]) {
|
||||
rc = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
lind = lli->lun_index = cfg->promote_lun_index;
|
||||
writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]);
|
||||
writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]);
|
||||
dev_dbg(dev, "%s: Virtual LUNs on slot %d:\n", __func__, lind);
|
||||
|
||||
for (k = 0; k < cfg->num_fc_ports; k++) {
|
||||
if (!(lli->port_sel & (1 << k)))
|
||||
continue;
|
||||
|
||||
fc_port_luns = get_fc_port_luns(cfg, k);
|
||||
writeq_be(lli->lun_id[k], &fc_port_luns[lind]);
|
||||
dev_dbg(dev, "\t%d=%llx\n", k, lli->lun_id[k]);
|
||||
}
|
||||
|
||||
cfg->promote_lun_index++;
|
||||
dev_dbg(dev, "%s: Virtual LUN on slot %d id0=%llx id1=%llx\n",
|
||||
__func__, lind, lli->lun_id[0], lli->lun_id[1]);
|
||||
} else {
|
||||
/*
|
||||
* If this LUN is visible only from one port, we will put
|
||||
* When LUN is visible only from one port, we will put
|
||||
* it in the bottom half of the LUN table.
|
||||
*/
|
||||
chan = PORT2CHAN(lli->port_sel);
|
||||
chan = PORTMASK2CHAN(lli->port_sel);
|
||||
if (cfg->promote_lun_index == cfg->last_lun_index[chan]) {
|
||||
rc = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lind = lli->lun_index = cfg->last_lun_index[chan];
|
||||
writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]);
|
||||
fc_port_luns = get_fc_port_luns(cfg, chan);
|
||||
writeq_be(lli->lun_id[chan], &fc_port_luns[lind]);
|
||||
cfg->last_lun_index[chan]--;
|
||||
dev_dbg(dev, "%s: Virtual LUN on slot %d chan=%d id=%llx\n",
|
||||
dev_dbg(dev, "%s: Virtual LUNs on slot %d:\n\t%d=%llx\n",
|
||||
__func__, lind, chan, lli->lun_id[chan]);
|
||||
}
|
||||
|
||||
|
@ -1016,7 +1043,7 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
|
|||
virt->last_lba = last_lba;
|
||||
virt->rsrc_handle = rsrc_handle;
|
||||
|
||||
if (lli->port_sel == BOTH_PORTS)
|
||||
if (get_num_ports(lli->port_sel) > 1)
|
||||
virt->hdr.return_flags |= DK_CXLFLASH_ALL_PORTS_ACTIVE;
|
||||
out:
|
||||
if (likely(ctxi))
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
* not stored anywhere.
|
||||
*
|
||||
* The LXT table is re-allocated whenever it needs to cross into another group.
|
||||
*/
|
||||
*/
|
||||
#define LXT_GROUP_SIZE 8
|
||||
#define LXT_NUM_GROUPS(lxt_cnt) (((lxt_cnt) + 7)/8) /* alloc'ed groups */
|
||||
#define LXT_LUNIDX_SHIFT 8 /* LXT entry, shift for LUN index */
|
||||
|
|
|
@ -130,11 +130,6 @@ static int esas2r_log_master(const long level,
|
|||
|
||||
spin_lock_irqsave(&event_buffer_lock, flags);
|
||||
|
||||
if (buffer == NULL) {
|
||||
spin_unlock_irqrestore(&event_buffer_lock, flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buffer, 0, buflen);
|
||||
|
||||
/*
|
||||
|
|
|
@ -63,11 +63,11 @@ unsigned int fcoe_debug_logging;
|
|||
module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
|
||||
|
||||
unsigned int fcoe_e_d_tov = 2 * 1000;
|
||||
static unsigned int fcoe_e_d_tov = 2 * 1000;
|
||||
module_param_named(e_d_tov, fcoe_e_d_tov, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(e_d_tov, "E_D_TOV in ms, default 2000");
|
||||
|
||||
unsigned int fcoe_r_a_tov = 2 * 2 * 1000;
|
||||
static unsigned int fcoe_r_a_tov = 2 * 2 * 1000;
|
||||
module_param_named(r_a_tov, fcoe_r_a_tov, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(r_a_tov, "R_A_TOV in ms, default 4000");
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#define DRV_NAME "fnic"
|
||||
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
|
||||
#define DRV_VERSION "1.6.0.21"
|
||||
#define DRV_VERSION "1.6.0.34"
|
||||
#define PFX DRV_NAME ": "
|
||||
#define DFX DRV_NAME "%d: "
|
||||
|
||||
|
@ -217,7 +217,6 @@ struct fnic {
|
|||
struct fcoe_ctlr ctlr; /* FIP FCoE controller structure */
|
||||
struct vnic_dev_bar bar0;
|
||||
|
||||
struct msix_entry msix_entry[FNIC_MSIX_INTR_MAX];
|
||||
struct fnic_msix_entry msix[FNIC_MSIX_INTR_MAX];
|
||||
|
||||
struct vnic_stats *stats;
|
||||
|
|
|
@ -342,8 +342,11 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
|
|||
|
||||
fnic_fcoe_reset_vlans(fnic);
|
||||
fnic->set_vlan(fnic, 0);
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
"Sending VLAN request...\n");
|
||||
|
||||
if (printk_ratelimit())
|
||||
FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
|
||||
"Sending VLAN request...\n");
|
||||
|
||||
skb = dev_alloc_skb(sizeof(struct fip_vlan));
|
||||
if (!skb)
|
||||
return;
|
||||
|
@ -359,7 +362,7 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
|
|||
|
||||
vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
|
||||
vlan->fip.fip_op = htons(FIP_OP_VLAN);
|
||||
vlan->fip.fip_subcode = FIP_SC_VL_NOTE;
|
||||
vlan->fip.fip_subcode = FIP_SC_VL_REQ;
|
||||
vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
|
||||
|
||||
vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
|
||||
|
@ -1313,10 +1316,11 @@ void fnic_handle_fip_timer(struct fnic *fnic)
|
|||
|
||||
spin_lock_irqsave(&fnic->vlans_lock, flags);
|
||||
if (list_empty(&fnic->vlans)) {
|
||||
/* no vlans available, try again */
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Start VLAN Discovery\n");
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
/* no vlans available, try again */
|
||||
if (printk_ratelimit())
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Start VLAN Discovery\n");
|
||||
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
|
||||
return;
|
||||
}
|
||||
|
@ -1332,10 +1336,11 @@ void fnic_handle_fip_timer(struct fnic *fnic)
|
|||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
break;
|
||||
case FIP_VLAN_FAILED:
|
||||
/* if all vlans are in failed state, restart vlan disc */
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Start VLAN Discovery\n");
|
||||
spin_unlock_irqrestore(&fnic->vlans_lock, flags);
|
||||
/* if all vlans are in failed state, restart vlan disc */
|
||||
if (printk_ratelimit())
|
||||
FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
"Start VLAN Discovery\n");
|
||||
fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
|
||||
break;
|
||||
case FIP_VLAN_SENT:
|
||||
|
|
|
@ -154,13 +154,13 @@ void fnic_free_intr(struct fnic *fnic)
|
|||
switch (vnic_dev_get_intr_mode(fnic->vdev)) {
|
||||
case VNIC_DEV_INTR_MODE_INTX:
|
||||
case VNIC_DEV_INTR_MODE_MSI:
|
||||
free_irq(fnic->pdev->irq, fnic);
|
||||
free_irq(pci_irq_vector(fnic->pdev, 0), fnic);
|
||||
break;
|
||||
|
||||
case VNIC_DEV_INTR_MODE_MSIX:
|
||||
for (i = 0; i < ARRAY_SIZE(fnic->msix); i++)
|
||||
if (fnic->msix[i].requested)
|
||||
free_irq(fnic->msix_entry[i].vector,
|
||||
free_irq(pci_irq_vector(fnic->pdev, i),
|
||||
fnic->msix[i].devid);
|
||||
break;
|
||||
|
||||
|
@ -177,12 +177,12 @@ int fnic_request_intr(struct fnic *fnic)
|
|||
switch (vnic_dev_get_intr_mode(fnic->vdev)) {
|
||||
|
||||
case VNIC_DEV_INTR_MODE_INTX:
|
||||
err = request_irq(fnic->pdev->irq, &fnic_isr_legacy,
|
||||
IRQF_SHARED, DRV_NAME, fnic);
|
||||
err = request_irq(pci_irq_vector(fnic->pdev, 0),
|
||||
&fnic_isr_legacy, IRQF_SHARED, DRV_NAME, fnic);
|
||||
break;
|
||||
|
||||
case VNIC_DEV_INTR_MODE_MSI:
|
||||
err = request_irq(fnic->pdev->irq, &fnic_isr_msi,
|
||||
err = request_irq(pci_irq_vector(fnic->pdev, 0), &fnic_isr_msi,
|
||||
0, fnic->name, fnic);
|
||||
break;
|
||||
|
||||
|
@ -210,7 +210,7 @@ int fnic_request_intr(struct fnic *fnic)
|
|||
fnic->msix[FNIC_MSIX_ERR_NOTIFY].devid = fnic;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fnic->msix); i++) {
|
||||
err = request_irq(fnic->msix_entry[i].vector,
|
||||
err = request_irq(pci_irq_vector(fnic->pdev, i),
|
||||
fnic->msix[i].isr, 0,
|
||||
fnic->msix[i].devname,
|
||||
fnic->msix[i].devid);
|
||||
|
@ -237,7 +237,6 @@ int fnic_set_intr_mode(struct fnic *fnic)
|
|||
unsigned int n = ARRAY_SIZE(fnic->rq);
|
||||
unsigned int m = ARRAY_SIZE(fnic->wq);
|
||||
unsigned int o = ARRAY_SIZE(fnic->wq_copy);
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Set interrupt mode (INTx, MSI, MSI-X) depending
|
||||
|
@ -248,23 +247,20 @@ int fnic_set_intr_mode(struct fnic *fnic)
|
|||
* We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
|
||||
* (last INTR is used for WQ/RQ errors and notification area)
|
||||
*/
|
||||
|
||||
BUG_ON(ARRAY_SIZE(fnic->msix_entry) < n + m + o + 1);
|
||||
for (i = 0; i < n + m + o + 1; i++)
|
||||
fnic->msix_entry[i].entry = i;
|
||||
|
||||
if (fnic->rq_count >= n &&
|
||||
fnic->raw_wq_count >= m &&
|
||||
fnic->wq_copy_count >= o &&
|
||||
fnic->cq_count >= n + m + o) {
|
||||
if (!pci_enable_msix_exact(fnic->pdev, fnic->msix_entry,
|
||||
n + m + o + 1)) {
|
||||
int vecs = n + m + o + 1;
|
||||
|
||||
if (pci_alloc_irq_vectors(fnic->pdev, vecs, vecs,
|
||||
PCI_IRQ_MSIX) < 0) {
|
||||
fnic->rq_count = n;
|
||||
fnic->raw_wq_count = m;
|
||||
fnic->wq_copy_count = o;
|
||||
fnic->wq_count = m + o;
|
||||
fnic->cq_count = n + m + o;
|
||||
fnic->intr_count = n + m + o + 1;
|
||||
fnic->intr_count = vecs;
|
||||
fnic->err_intr_offset = FNIC_MSIX_ERR_NOTIFY;
|
||||
|
||||
FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
|
||||
|
@ -284,8 +280,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
|
|||
fnic->wq_copy_count >= 1 &&
|
||||
fnic->cq_count >= 3 &&
|
||||
fnic->intr_count >= 1 &&
|
||||
!pci_enable_msi(fnic->pdev)) {
|
||||
|
||||
pci_alloc_irq_vectors(fnic->pdev, 1, 1, PCI_IRQ_MSI) < 0) {
|
||||
fnic->rq_count = 1;
|
||||
fnic->raw_wq_count = 1;
|
||||
fnic->wq_copy_count = 1;
|
||||
|
@ -334,17 +329,7 @@ int fnic_set_intr_mode(struct fnic *fnic)
|
|||
|
||||
void fnic_clear_intr_mode(struct fnic *fnic)
|
||||
{
|
||||
switch (vnic_dev_get_intr_mode(fnic->vdev)) {
|
||||
case VNIC_DEV_INTR_MODE_MSIX:
|
||||
pci_disable_msix(fnic->pdev);
|
||||
break;
|
||||
case VNIC_DEV_INTR_MODE_MSI:
|
||||
pci_disable_msi(fnic->pdev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pci_free_irq_vectors(fnic->pdev);
|
||||
vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);
|
||||
}
|
||||
|
||||
|
|
|
@ -823,6 +823,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
|
|||
spinlock_t *io_lock;
|
||||
u64 cmd_trace;
|
||||
unsigned long start_time;
|
||||
unsigned long io_duration_time;
|
||||
|
||||
/* Decode the cmpl description to get the io_req id */
|
||||
fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
|
||||
|
@ -876,32 +877,28 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
|
|||
|
||||
/*
|
||||
* if SCSI-ML has already issued abort on this command,
|
||||
* ignore completion of the IO. The abts path will clean it up
|
||||
* set completion of the IO. The abts path will clean it up
|
||||
*/
|
||||
if (CMD_STATE(sc) == FNIC_IOREQ_ABTS_PENDING) {
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
|
||||
/*
|
||||
* set the FNIC_IO_DONE so that this doesn't get
|
||||
* flagged as 'out of order' if it was not aborted
|
||||
*/
|
||||
CMD_FLAGS(sc) |= FNIC_IO_DONE;
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABTS_PENDING;
|
||||
switch (hdr_status) {
|
||||
case FCPIO_SUCCESS:
|
||||
CMD_FLAGS(sc) |= FNIC_IO_DONE;
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"icmnd_cmpl ABTS pending hdr status = %s "
|
||||
"sc 0x%p scsi_status %x residual %d\n",
|
||||
fnic_fcpio_status_to_str(hdr_status), sc,
|
||||
icmnd_cmpl->scsi_status,
|
||||
icmnd_cmpl->residual);
|
||||
break;
|
||||
case FCPIO_ABORTED:
|
||||
spin_unlock_irqrestore(io_lock, flags);
|
||||
if(FCPIO_ABORTED == hdr_status)
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABORTED;
|
||||
break;
|
||||
default:
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"icmnd_cmpl abts pending "
|
||||
"hdr status = %s tag = 0x%x sc = 0x%p\n",
|
||||
fnic_fcpio_status_to_str(hdr_status),
|
||||
id, sc);
|
||||
break;
|
||||
}
|
||||
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"icmnd_cmpl abts pending "
|
||||
"hdr status = %s tag = 0x%x sc = 0x%p"
|
||||
"scsi_status = %x residual = %d\n",
|
||||
fnic_fcpio_status_to_str(hdr_status),
|
||||
id, sc,
|
||||
icmnd_cmpl->scsi_status,
|
||||
icmnd_cmpl->residual);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -919,6 +916,9 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
|
|||
if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER)
|
||||
xfer_len -= icmnd_cmpl->residual;
|
||||
|
||||
if (icmnd_cmpl->scsi_status == SAM_STAT_CHECK_CONDITION)
|
||||
atomic64_inc(&fnic_stats->misc_stats.check_condition);
|
||||
|
||||
if (icmnd_cmpl->scsi_status == SAM_STAT_TASK_SET_FULL)
|
||||
atomic64_inc(&fnic_stats->misc_stats.queue_fulls);
|
||||
break;
|
||||
|
@ -1017,6 +1017,28 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic,
|
|||
else
|
||||
atomic64_inc(&fnic_stats->io_stats.io_completions);
|
||||
|
||||
|
||||
io_duration_time = jiffies_to_msecs(jiffies) - jiffies_to_msecs(io_req->start_time);
|
||||
|
||||
if(io_duration_time <= 10)
|
||||
atomic64_inc(&fnic_stats->io_stats.io_btw_0_to_10_msec);
|
||||
else if(io_duration_time <= 100)
|
||||
atomic64_inc(&fnic_stats->io_stats.io_btw_10_to_100_msec);
|
||||
else if(io_duration_time <= 500)
|
||||
atomic64_inc(&fnic_stats->io_stats.io_btw_100_to_500_msec);
|
||||
else if(io_duration_time <= 5000)
|
||||
atomic64_inc(&fnic_stats->io_stats.io_btw_500_to_5000_msec);
|
||||
else if(io_duration_time <= 10000)
|
||||
atomic64_inc(&fnic_stats->io_stats.io_btw_5000_to_10000_msec);
|
||||
else if(io_duration_time <= 30000)
|
||||
atomic64_inc(&fnic_stats->io_stats.io_btw_10000_to_30000_msec);
|
||||
else {
|
||||
atomic64_inc(&fnic_stats->io_stats.io_greater_than_30000_msec);
|
||||
|
||||
if(io_duration_time > atomic64_read(&fnic_stats->io_stats.current_max_io_time))
|
||||
atomic64_set(&fnic_stats->io_stats.current_max_io_time, io_duration_time);
|
||||
}
|
||||
|
||||
/* Call SCSI completion function to complete the IO */
|
||||
if (sc->scsi_done)
|
||||
sc->scsi_done(sc);
|
||||
|
@ -1128,18 +1150,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
|
|||
}
|
||||
|
||||
CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE;
|
||||
CMD_ABTS_STATUS(sc) = hdr_status;
|
||||
|
||||
/* If the status is IO not found consider it as success */
|
||||
if (hdr_status == FCPIO_IO_NOT_FOUND)
|
||||
CMD_ABTS_STATUS(sc) = FCPIO_SUCCESS;
|
||||
else
|
||||
CMD_ABTS_STATUS(sc) = hdr_status;
|
||||
|
||||
atomic64_dec(&fnic_stats->io_stats.active_ios);
|
||||
if (atomic64_read(&fnic->io_cmpl_skip))
|
||||
atomic64_dec(&fnic->io_cmpl_skip);
|
||||
else
|
||||
atomic64_inc(&fnic_stats->io_stats.io_completions);
|
||||
|
||||
if (!(CMD_FLAGS(sc) & (FNIC_IO_ABORTED | FNIC_IO_DONE)))
|
||||
atomic64_inc(&misc_stats->no_icmnd_itmf_cmpls);
|
||||
|
@ -1181,6 +1196,11 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
|
|||
(((u64)CMD_FLAGS(sc) << 32) |
|
||||
CMD_STATE(sc)));
|
||||
sc->scsi_done(sc);
|
||||
atomic64_dec(&fnic_stats->io_stats.active_ios);
|
||||
if (atomic64_read(&fnic->io_cmpl_skip))
|
||||
atomic64_dec(&fnic->io_cmpl_skip);
|
||||
else
|
||||
atomic64_inc(&fnic_stats->io_stats.io_completions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1793,6 +1813,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
|
|||
struct terminate_stats *term_stats;
|
||||
enum fnic_ioreq_state old_ioreq_state;
|
||||
int tag;
|
||||
unsigned long abt_issued_time;
|
||||
DECLARE_COMPLETION_ONSTACK(tm_done);
|
||||
|
||||
/* Wait for rport to unblock */
|
||||
|
@ -1846,6 +1867,25 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
|
|||
spin_unlock_irqrestore(io_lock, flags);
|
||||
goto wait_pending;
|
||||
}
|
||||
|
||||
abt_issued_time = jiffies_to_msecs(jiffies) - jiffies_to_msecs(io_req->start_time);
|
||||
if (abt_issued_time <= 6000)
|
||||
atomic64_inc(&abts_stats->abort_issued_btw_0_to_6_sec);
|
||||
else if (abt_issued_time > 6000 && abt_issued_time <= 20000)
|
||||
atomic64_inc(&abts_stats->abort_issued_btw_6_to_20_sec);
|
||||
else if (abt_issued_time > 20000 && abt_issued_time <= 30000)
|
||||
atomic64_inc(&abts_stats->abort_issued_btw_20_to_30_sec);
|
||||
else if (abt_issued_time > 30000 && abt_issued_time <= 40000)
|
||||
atomic64_inc(&abts_stats->abort_issued_btw_30_to_40_sec);
|
||||
else if (abt_issued_time > 40000 && abt_issued_time <= 50000)
|
||||
atomic64_inc(&abts_stats->abort_issued_btw_40_to_50_sec);
|
||||
else if (abt_issued_time > 50000 && abt_issued_time <= 60000)
|
||||
atomic64_inc(&abts_stats->abort_issued_btw_50_to_60_sec);
|
||||
else
|
||||
atomic64_inc(&abts_stats->abort_issued_greater_than_60_sec);
|
||||
|
||||
FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
|
||||
"CBD Opcode: %02x Abort issued time: %lu msec\n", sc->cmnd[0], abt_issued_time);
|
||||
/*
|
||||
* Command is still pending, need to abort it
|
||||
* If the firmware completes the command after this point,
|
||||
|
@ -1970,6 +2010,11 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
|
|||
/* Call SCSI completion function to complete the IO */
|
||||
sc->result = (DID_ABORT << 16);
|
||||
sc->scsi_done(sc);
|
||||
atomic64_dec(&fnic_stats->io_stats.active_ios);
|
||||
if (atomic64_read(&fnic->io_cmpl_skip))
|
||||
atomic64_dec(&fnic->io_cmpl_skip);
|
||||
else
|
||||
atomic64_inc(&fnic_stats->io_stats.io_completions);
|
||||
}
|
||||
|
||||
fnic_abort_cmd_end:
|
||||
|
|
|
@ -26,6 +26,14 @@ struct io_path_stats {
|
|||
atomic64_t sc_null;
|
||||
atomic64_t io_not_found;
|
||||
atomic64_t num_ios;
|
||||
atomic64_t io_btw_0_to_10_msec;
|
||||
atomic64_t io_btw_10_to_100_msec;
|
||||
atomic64_t io_btw_100_to_500_msec;
|
||||
atomic64_t io_btw_500_to_5000_msec;
|
||||
atomic64_t io_btw_5000_to_10000_msec;
|
||||
atomic64_t io_btw_10000_to_30000_msec;
|
||||
atomic64_t io_greater_than_30000_msec;
|
||||
atomic64_t current_max_io_time;
|
||||
};
|
||||
|
||||
struct abort_stats {
|
||||
|
@ -34,6 +42,13 @@ struct abort_stats {
|
|||
atomic64_t abort_drv_timeouts;
|
||||
atomic64_t abort_fw_timeouts;
|
||||
atomic64_t abort_io_not_found;
|
||||
atomic64_t abort_issued_btw_0_to_6_sec;
|
||||
atomic64_t abort_issued_btw_6_to_20_sec;
|
||||
atomic64_t abort_issued_btw_20_to_30_sec;
|
||||
atomic64_t abort_issued_btw_30_to_40_sec;
|
||||
atomic64_t abort_issued_btw_40_to_50_sec;
|
||||
atomic64_t abort_issued_btw_50_to_60_sec;
|
||||
atomic64_t abort_issued_greater_than_60_sec;
|
||||
};
|
||||
|
||||
struct terminate_stats {
|
||||
|
@ -88,6 +103,7 @@ struct misc_stats {
|
|||
atomic64_t devrst_cpwq_alloc_failures;
|
||||
atomic64_t io_cpwq_alloc_failures;
|
||||
atomic64_t no_icmnd_itmf_cmpls;
|
||||
atomic64_t check_condition;
|
||||
atomic64_t queue_fulls;
|
||||
atomic64_t rport_not_ready;
|
||||
atomic64_t frame_errors;
|
||||
|
|
|
@ -229,7 +229,16 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
|
|||
"Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n"
|
||||
"Number of Memory alloc Failures: %lld\n"
|
||||
"Number of IOREQ Null: %lld\n"
|
||||
"Number of SCSI cmd pointer Null: %lld\n",
|
||||
"Number of SCSI cmd pointer Null: %lld\n"
|
||||
|
||||
"\nIO completion times: \n"
|
||||
" < 10 ms : %lld\n"
|
||||
" 10 ms - 100 ms : %lld\n"
|
||||
" 100 ms - 500 ms : %lld\n"
|
||||
" 500 ms - 5 sec: %lld\n"
|
||||
" 5 sec - 10 sec: %lld\n"
|
||||
" 10 sec - 30 sec: %lld\n"
|
||||
" > 30 sec: %lld\n",
|
||||
(u64)atomic64_read(&stats->io_stats.active_ios),
|
||||
(u64)atomic64_read(&stats->io_stats.max_active_ios),
|
||||
(u64)atomic64_read(&stats->io_stats.num_ios),
|
||||
|
@ -238,28 +247,58 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
|
|||
(u64)atomic64_read(&stats->io_stats.io_not_found),
|
||||
(u64)atomic64_read(&stats->io_stats.alloc_failures),
|
||||
(u64)atomic64_read(&stats->io_stats.ioreq_null),
|
||||
(u64)atomic64_read(&stats->io_stats.sc_null));
|
||||
(u64)atomic64_read(&stats->io_stats.sc_null),
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_0_to_10_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_10_to_100_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_100_to_500_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_500_to_5000_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_5000_to_10000_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec),
|
||||
(u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
|
||||
|
||||
len += snprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"\nCurrent Max IO time : %lld\n",
|
||||
(u64)atomic64_read(&stats->io_stats.current_max_io_time));
|
||||
|
||||
len += snprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"\n------------------------------------------\n"
|
||||
"\t\tAbort Statistics\n"
|
||||
"------------------------------------------\n");
|
||||
|
||||
len += snprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"Number of Aborts: %lld\n"
|
||||
"Number of Abort Failures: %lld\n"
|
||||
"Number of Abort Driver Timeouts: %lld\n"
|
||||
"Number of Abort FW Timeouts: %lld\n"
|
||||
"Number of Abort IO NOT Found: %lld\n",
|
||||
"Number of Abort IO NOT Found: %lld\n"
|
||||
|
||||
"Abord issued times: \n"
|
||||
" < 6 sec : %lld\n"
|
||||
" 6 sec - 20 sec : %lld\n"
|
||||
" 20 sec - 30 sec : %lld\n"
|
||||
" 30 sec - 40 sec : %lld\n"
|
||||
" 40 sec - 50 sec : %lld\n"
|
||||
" 50 sec - 60 sec : %lld\n"
|
||||
" > 60 sec: %lld\n",
|
||||
|
||||
(u64)atomic64_read(&stats->abts_stats.aborts),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_failures),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_io_not_found));
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_io_not_found),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_0_to_6_sec),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_6_to_20_sec),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_20_to_30_sec),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_30_to_40_sec),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_40_to_50_sec),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec),
|
||||
(u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec));
|
||||
|
||||
len += snprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"\n------------------------------------------\n"
|
||||
"\t\tTerminate Statistics\n"
|
||||
"------------------------------------------\n");
|
||||
|
||||
len += snprintf(debug->debug_buffer + len, buf_size - len,
|
||||
"Number of Terminates: %lld\n"
|
||||
"Maximum Terminates: %lld\n"
|
||||
|
@ -357,6 +396,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
|
|||
"Number of Copy WQ Alloc Failures for Device Reset: %lld\n"
|
||||
"Number of Copy WQ Alloc Failures for IOs: %lld\n"
|
||||
"Number of no icmnd itmf Completions: %lld\n"
|
||||
"Number of Check Conditions encountered: %lld\n"
|
||||
"Number of QUEUE Fulls: %lld\n"
|
||||
"Number of rport not ready: %lld\n"
|
||||
"Number of receive frame errors: %lld\n",
|
||||
|
@ -377,6 +417,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
|
|||
&stats->misc_stats.devrst_cpwq_alloc_failures),
|
||||
(u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures),
|
||||
(u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls),
|
||||
(u64)atomic64_read(&stats->misc_stats.check_condition),
|
||||
(u64)atomic64_read(&stats->misc_stats.queue_fulls),
|
||||
(u64)atomic64_read(&stats->misc_stats.rport_not_ready),
|
||||
(u64)atomic64_read(&stats->misc_stats.frame_errors));
|
||||
|
|
|
@ -4,5 +4,6 @@ config SCSI_HISI_SAS
|
|||
depends on ARM64 || COMPILE_TEST
|
||||
select SCSI_SAS_LIBSAS
|
||||
select BLK_DEV_INTEGRITY
|
||||
depends on ATA
|
||||
help
|
||||
This driver supports HiSilicon's SAS HBA
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define HISI_SAS_QUEUE_SLOTS 512
|
||||
#define HISI_SAS_MAX_ITCT_ENTRIES 2048
|
||||
#define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
|
||||
#define HISI_SAS_RESET_BIT 0
|
||||
|
||||
#define HISI_SAS_STATUS_BUF_SZ \
|
||||
(sizeof(struct hisi_sas_err_record) + 1024)
|
||||
|
@ -90,7 +91,6 @@ struct hisi_sas_port {
|
|||
struct asd_sas_port sas_port;
|
||||
u8 port_attached;
|
||||
u8 id; /* from hw */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct hisi_sas_cq {
|
||||
|
@ -113,7 +113,9 @@ struct hisi_sas_device {
|
|||
u64 attached_phy;
|
||||
u64 device_id;
|
||||
atomic64_t running_req;
|
||||
struct list_head list;
|
||||
u8 dev_status;
|
||||
int sata_idx;
|
||||
};
|
||||
|
||||
struct hisi_sas_slot {
|
||||
|
@ -136,6 +138,7 @@ struct hisi_sas_slot {
|
|||
struct hisi_sas_sge_page *sge_page;
|
||||
dma_addr_t sge_page_dma;
|
||||
struct work_struct abort_slot;
|
||||
struct timer_list internal_abort_timer;
|
||||
};
|
||||
|
||||
struct hisi_sas_tmf_task {
|
||||
|
@ -165,7 +168,8 @@ struct hisi_sas_hw {
|
|||
struct hisi_sas_slot *slot,
|
||||
int device_id, int abort_flag, int tag_to_abort);
|
||||
int (*slot_complete)(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot, int abort);
|
||||
struct hisi_sas_slot *slot);
|
||||
void (*phys_init)(struct hisi_hba *hisi_hba);
|
||||
void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
|
||||
void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no);
|
||||
void (*phy_hard_reset)(struct hisi_hba *hisi_hba, int phy_no);
|
||||
|
@ -175,6 +179,7 @@ struct hisi_sas_hw {
|
|||
void (*free_device)(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_device *dev);
|
||||
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
|
||||
int (*soft_reset)(struct hisi_hba *hisi_hba);
|
||||
int max_command_entries;
|
||||
int complete_hdr_size;
|
||||
};
|
||||
|
@ -193,7 +198,6 @@ struct hisi_hba {
|
|||
u8 sas_addr[SAS_ADDR_SIZE];
|
||||
|
||||
int n_phy;
|
||||
int scan_finished;
|
||||
spinlock_t lock;
|
||||
|
||||
struct timer_list timer;
|
||||
|
@ -201,6 +205,7 @@ struct hisi_hba {
|
|||
|
||||
int slot_index_count;
|
||||
unsigned long *slot_index_tags;
|
||||
unsigned long reject_stp_links_msk;
|
||||
|
||||
/* SCSI/SAS glue */
|
||||
struct sas_ha_struct sha;
|
||||
|
@ -233,7 +238,10 @@ struct hisi_hba {
|
|||
struct hisi_sas_breakpoint *sata_breakpoint;
|
||||
dma_addr_t sata_breakpoint_dma;
|
||||
struct hisi_sas_slot *slot_info;
|
||||
unsigned long flags;
|
||||
const struct hisi_sas_hw *hw; /* Low level hw interface */
|
||||
unsigned long sata_dev_bitmap[BITS_TO_LONGS(HISI_SAS_MAX_DEVICES)];
|
||||
struct work_struct rst_work;
|
||||
};
|
||||
|
||||
/* Generic HW DMA host memory structures */
|
||||
|
@ -346,6 +354,8 @@ union hisi_sas_command_table {
|
|||
struct hisi_sas_command_table_smp smp;
|
||||
struct hisi_sas_command_table_stp stp;
|
||||
};
|
||||
|
||||
extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
|
||||
extern int hisi_sas_probe(struct platform_device *pdev,
|
||||
const struct hisi_sas_hw *ops);
|
||||
extern int hisi_sas_remove(struct platform_device *pdev);
|
||||
|
@ -354,4 +364,7 @@ extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
|
|||
extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
|
||||
struct sas_task *task,
|
||||
struct hisi_sas_slot *slot);
|
||||
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
|
||||
extern void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
|
||||
u32 state);
|
||||
#endif
|
||||
|
|
|
@ -21,12 +21,19 @@ static int
|
|||
hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
||||
struct domain_device *device,
|
||||
int abort_flag, int tag);
|
||||
static int hisi_sas_softreset_ata_disk(struct domain_device *device);
|
||||
|
||||
static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
|
||||
{
|
||||
return device->port->ha->lldd_ha;
|
||||
}
|
||||
|
||||
struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port)
|
||||
{
|
||||
return container_of(sas_port, struct hisi_sas_port, sas_port);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(to_hisi_sas_port);
|
||||
|
||||
static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx)
|
||||
{
|
||||
void *bitmap = hisi_hba->slot_index_tags;
|
||||
|
@ -70,17 +77,22 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
|
|||
void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
|
||||
struct hisi_sas_slot *slot)
|
||||
{
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct domain_device *device = task->dev;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
|
||||
if (!slot->task)
|
||||
return;
|
||||
if (task) {
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct domain_device *device = task->dev;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
|
||||
if (!sas_protocol_ata(task->task_proto))
|
||||
if (slot->n_elem)
|
||||
dma_unmap_sg(dev, task->scatter, slot->n_elem,
|
||||
task->data_dir);
|
||||
if (!sas_protocol_ata(task->task_proto))
|
||||
if (slot->n_elem)
|
||||
dma_unmap_sg(dev, task->scatter, slot->n_elem,
|
||||
task->data_dir);
|
||||
|
||||
task->lldd_task = NULL;
|
||||
|
||||
if (sas_dev)
|
||||
atomic64_dec(&sas_dev->running_req);
|
||||
}
|
||||
|
||||
if (slot->command_table)
|
||||
dma_pool_free(hisi_hba->command_table_pool,
|
||||
|
@ -95,12 +107,10 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
|
|||
slot->sge_page_dma);
|
||||
|
||||
list_del_init(&slot->entry);
|
||||
task->lldd_task = NULL;
|
||||
slot->task = NULL;
|
||||
slot->port = NULL;
|
||||
hisi_sas_slot_index_free(hisi_hba, slot->idx);
|
||||
if (sas_dev)
|
||||
atomic64_dec(&sas_dev->running_req);
|
||||
|
||||
/* slot memory is fully zeroed when it is reused */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
|
||||
|
@ -178,10 +188,12 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
|
|||
struct hisi_sas_port *port;
|
||||
struct hisi_sas_slot *slot;
|
||||
struct hisi_sas_cmd_hdr *cmd_hdr_base;
|
||||
struct asd_sas_port *sas_port = device->port;
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
|
||||
unsigned long flags;
|
||||
|
||||
if (!device->port) {
|
||||
if (!sas_port) {
|
||||
struct task_status_struct *ts = &task->task_status;
|
||||
|
||||
ts->resp = SAS_TASK_UNDELIVERED;
|
||||
|
@ -192,7 +204,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
|
|||
*/
|
||||
if (device->dev_type != SAS_SATA_DEV)
|
||||
task->task_done(task);
|
||||
return 0;
|
||||
return SAS_PHY_DOWN;
|
||||
}
|
||||
|
||||
if (DEV_IS_GONE(sas_dev)) {
|
||||
|
@ -203,13 +215,13 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
|
|||
dev_info(dev, "task prep: device %016llx not ready\n",
|
||||
SAS_ADDR(device->sas_addr));
|
||||
|
||||
rc = SAS_PHY_DOWN;
|
||||
return rc;
|
||||
return SAS_PHY_DOWN;
|
||||
}
|
||||
port = device->port->lldd_port;
|
||||
|
||||
port = to_hisi_sas_port(sas_port);
|
||||
if (port && !port->port_attached) {
|
||||
dev_info(dev, "task prep: %s port%d not attach device\n",
|
||||
(sas_protocol_ata(task->task_proto)) ?
|
||||
(dev_is_sata(device)) ?
|
||||
"SATA/STP" : "SAS",
|
||||
device->port->id);
|
||||
|
||||
|
@ -299,10 +311,10 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
|
|||
goto err_out_command_table;
|
||||
}
|
||||
|
||||
list_add_tail(&slot->entry, &port->list);
|
||||
spin_lock(&task->task_state_lock);
|
||||
list_add_tail(&slot->entry, &sas_dev->list);
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock(&task->task_state_lock);
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
hisi_hba->slot_prep = slot;
|
||||
|
||||
|
@ -343,6 +355,9 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
|
|||
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
|
||||
if (unlikely(test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)))
|
||||
return -EINVAL;
|
||||
|
||||
/* protect task_prep and start_delivery sequence */
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
rc = hisi_sas_task_prep(task, hisi_hba, is_tmf, tmf, &pass);
|
||||
|
@ -412,6 +427,7 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
|
|||
sas_dev->dev_type = device->dev_type;
|
||||
sas_dev->hisi_hba = hisi_hba;
|
||||
sas_dev->sas_device = device;
|
||||
INIT_LIST_HEAD(&hisi_hba->devices[i].list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -482,12 +498,8 @@ static int hisi_sas_slave_configure(struct scsi_device *sdev)
|
|||
static void hisi_sas_scan_start(struct Scsi_Host *shost)
|
||||
{
|
||||
struct hisi_hba *hisi_hba = shost_priv(shost);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hisi_hba->n_phy; ++i)
|
||||
hisi_sas_bytes_dmaed(hisi_hba, i);
|
||||
|
||||
hisi_hba->scan_finished = 1;
|
||||
hisi_hba->hw->phys_init(hisi_hba);
|
||||
}
|
||||
|
||||
static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
||||
|
@ -495,7 +507,8 @@ static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
|||
struct hisi_hba *hisi_hba = shost_priv(shost);
|
||||
struct sas_ha_struct *sha = &hisi_hba->sha;
|
||||
|
||||
if (hisi_hba->scan_finished == 0)
|
||||
/* Wait for PHY up interrupt to occur */
|
||||
if (time < HZ)
|
||||
return 0;
|
||||
|
||||
sas_drain_work(sha);
|
||||
|
@ -545,7 +558,7 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
|
|||
struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
|
||||
struct hisi_sas_phy *phy = sas_phy->lldd_phy;
|
||||
struct asd_sas_port *sas_port = sas_phy->port;
|
||||
struct hisi_sas_port *port = &hisi_hba->port[phy->port_id];
|
||||
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
|
||||
unsigned long flags;
|
||||
|
||||
if (!sas_port)
|
||||
|
@ -559,50 +572,54 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
|
|||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
|
||||
static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, int phy_no,
|
||||
struct domain_device *device)
|
||||
static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, struct sas_task *task,
|
||||
struct hisi_sas_slot *slot)
|
||||
{
|
||||
struct hisi_sas_phy *phy;
|
||||
struct hisi_sas_port *port;
|
||||
struct hisi_sas_slot *slot, *slot2;
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
if (task) {
|
||||
unsigned long flags;
|
||||
struct task_status_struct *ts;
|
||||
|
||||
phy = &hisi_hba->phy[phy_no];
|
||||
port = phy->port;
|
||||
if (!port)
|
||||
return;
|
||||
ts = &task->task_status;
|
||||
|
||||
list_for_each_entry_safe(slot, slot2, &port->list, entry) {
|
||||
struct sas_task *task;
|
||||
|
||||
task = slot->task;
|
||||
if (device && task->dev != device)
|
||||
continue;
|
||||
|
||||
dev_info(dev, "Release slot [%d:%d], task [%p]:\n",
|
||||
slot->dlvry_queue, slot->dlvry_queue_slot, task);
|
||||
hisi_hba->hw->slot_complete(hisi_hba, slot, 1);
|
||||
ts->resp = SAS_TASK_COMPLETE;
|
||||
ts->stat = SAS_ABORTED_TASK;
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags &=
|
||||
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
|
||||
task->task_state_flags |= SAS_TASK_STATE_DONE;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
}
|
||||
|
||||
hisi_sas_slot_task_free(hisi_hba, task, slot);
|
||||
}
|
||||
|
||||
static void hisi_sas_port_notify_deformed(struct asd_sas_phy *sas_phy)
|
||||
{
|
||||
struct domain_device *device;
|
||||
struct hisi_sas_phy *phy = sas_phy->lldd_phy;
|
||||
struct asd_sas_port *sas_port = sas_phy->port;
|
||||
|
||||
list_for_each_entry(device, &sas_port->dev_list, dev_list_node)
|
||||
hisi_sas_do_release_task(phy->hisi_hba, sas_phy->id, device);
|
||||
}
|
||||
|
||||
/* hisi_hba.lock should be locked */
|
||||
static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
|
||||
struct domain_device *device)
|
||||
{
|
||||
struct asd_sas_port *port = device->port;
|
||||
struct asd_sas_phy *sas_phy;
|
||||
struct hisi_sas_slot *slot, *slot2;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
|
||||
list_for_each_entry(sas_phy, &port->phy_list, port_phy_el)
|
||||
hisi_sas_do_release_task(hisi_hba, sas_phy->id, device);
|
||||
list_for_each_entry_safe(slot, slot2, &sas_dev->list, entry)
|
||||
hisi_sas_do_release_task(hisi_hba, slot->task, slot);
|
||||
}
|
||||
|
||||
static void hisi_sas_release_tasks(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
struct hisi_sas_device *sas_dev;
|
||||
struct domain_device *device;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
|
||||
sas_dev = &hisi_hba->devices[i];
|
||||
device = sas_dev->sas_device;
|
||||
|
||||
if ((sas_dev->dev_type == SAS_PHY_UNUSED) ||
|
||||
!device)
|
||||
continue;
|
||||
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
}
|
||||
}
|
||||
|
||||
static void hisi_sas_dev_gone(struct domain_device *device)
|
||||
|
@ -644,8 +661,9 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
|
|||
break;
|
||||
|
||||
case PHY_FUNC_LINK_RESET:
|
||||
hisi_hba->hw->phy_disable(hisi_hba, phy_no);
|
||||
msleep(100);
|
||||
hisi_hba->hw->phy_enable(hisi_hba, phy_no);
|
||||
hisi_hba->hw->phy_hard_reset(hisi_hba, phy_no);
|
||||
break;
|
||||
|
||||
case PHY_FUNC_DISABLE:
|
||||
|
@ -698,7 +716,12 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
|
|||
task->dev = device;
|
||||
task->task_proto = device->tproto;
|
||||
|
||||
memcpy(&task->ssp_task, parameter, para_len);
|
||||
if (dev_is_sata(device)) {
|
||||
task->ata_task.device_control_reg_update = 1;
|
||||
memcpy(&task->ata_task.fis, parameter, para_len);
|
||||
} else {
|
||||
memcpy(&task->ssp_task, parameter, para_len);
|
||||
}
|
||||
task->task_done = hisi_sas_task_done;
|
||||
|
||||
task->slow_task->timer.data = (unsigned long) task;
|
||||
|
@ -720,15 +743,11 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
|
|||
/* Even TMF timed out, return direct. */
|
||||
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
|
||||
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
|
||||
dev_err(dev, "abort tmf: TMF task[%d] timeout\n",
|
||||
tmf->tag_of_task_to_be_managed);
|
||||
if (task->lldd_task) {
|
||||
struct hisi_sas_slot *slot =
|
||||
task->lldd_task;
|
||||
struct hisi_sas_slot *slot = task->lldd_task;
|
||||
|
||||
hisi_sas_slot_task_free(hisi_hba,
|
||||
task, slot);
|
||||
}
|
||||
dev_err(dev, "abort tmf: TMF task timeout\n");
|
||||
if (slot)
|
||||
slot->task = NULL;
|
||||
|
||||
goto ex_err;
|
||||
}
|
||||
|
@ -781,6 +800,63 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void hisi_sas_fill_ata_reset_cmd(struct ata_device *dev,
|
||||
bool reset, int pmp, u8 *fis)
|
||||
{
|
||||
struct ata_taskfile tf;
|
||||
|
||||
ata_tf_init(dev, &tf);
|
||||
if (reset)
|
||||
tf.ctl |= ATA_SRST;
|
||||
else
|
||||
tf.ctl &= ~ATA_SRST;
|
||||
tf.command = ATA_CMD_DEV_RESET;
|
||||
ata_tf_to_fis(&tf, pmp, 0, fis);
|
||||
}
|
||||
|
||||
static int hisi_sas_softreset_ata_disk(struct domain_device *device)
|
||||
{
|
||||
u8 fis[20] = {0};
|
||||
struct ata_port *ap = device->sata_dev.ap;
|
||||
struct ata_link *link;
|
||||
int rc = TMF_RESP_FUNC_FAILED;
|
||||
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
int s = sizeof(struct host_to_dev_fis);
|
||||
unsigned long flags;
|
||||
|
||||
ata_for_each_link(link, ap, EDGE) {
|
||||
int pmp = sata_srst_pmp(link);
|
||||
|
||||
hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
|
||||
rc = hisi_sas_exec_internal_tmf_task(device, fis, s, NULL);
|
||||
if (rc != TMF_RESP_FUNC_COMPLETE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE) {
|
||||
ata_for_each_link(link, ap, EDGE) {
|
||||
int pmp = sata_srst_pmp(link);
|
||||
|
||||
hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis);
|
||||
rc = hisi_sas_exec_internal_tmf_task(device, fis,
|
||||
s, NULL);
|
||||
if (rc != TMF_RESP_FUNC_COMPLETE)
|
||||
dev_err(dev, "ata disk de-reset failed\n");
|
||||
}
|
||||
} else {
|
||||
dev_err(dev, "ata disk reset failed\n");
|
||||
}
|
||||
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE) {
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
|
||||
u8 *lun, struct hisi_sas_tmf_task *tmf)
|
||||
{
|
||||
|
@ -795,6 +871,40 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
|
|||
sizeof(ssp_task), tmf);
|
||||
}
|
||||
|
||||
static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!hisi_hba->hw->soft_reset)
|
||||
return -1;
|
||||
|
||||
if (!test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct sas_ha_struct *sas_ha = &hisi_hba->sha;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(dev, "controller reset begins!\n");
|
||||
scsi_block_requests(hisi_hba->shost);
|
||||
rc = hisi_hba->hw->soft_reset(hisi_hba);
|
||||
if (rc) {
|
||||
dev_warn(dev, "controller reset failed (%d)\n", rc);
|
||||
goto out;
|
||||
}
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_tasks(hisi_hba);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
|
||||
sas_ha->notify_ha_event(sas_ha, HAE_RESET);
|
||||
dev_dbg(dev, "controller reset successful!\n");
|
||||
} else
|
||||
return -1;
|
||||
|
||||
out:
|
||||
scsi_unblock_requests(hisi_hba->shost);
|
||||
clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hisi_sas_abort_task(struct sas_task *task)
|
||||
{
|
||||
struct scsi_lun lun;
|
||||
|
@ -811,19 +921,17 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
|||
return TMF_RESP_FUNC_FAILED;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
rc = TMF_RESP_FUNC_COMPLETE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
sas_dev->dev_status = HISI_SAS_DEV_EH;
|
||||
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
|
||||
struct scsi_cmnd *cmnd = task->uldd_task;
|
||||
struct hisi_sas_slot *slot = task->lldd_task;
|
||||
u32 tag = slot->idx;
|
||||
int rc2;
|
||||
|
||||
int_to_scsilun(cmnd->device->lun, &lun);
|
||||
tmf_task.tmf = TMF_ABORT_TASK;
|
||||
|
@ -832,35 +940,41 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
|||
rc = hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun,
|
||||
&tmf_task);
|
||||
|
||||
/* if successful, clear the task and callback forwards.*/
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE) {
|
||||
rc2 = hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_CMD, tag);
|
||||
/*
|
||||
* If the TMF finds that the IO is not in the device and also
|
||||
* the internal abort does not succeed, then it is safe to
|
||||
* free the slot.
|
||||
* Note: if the internal abort succeeds then the slot
|
||||
* will have already been completed
|
||||
*/
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) {
|
||||
if (task->lldd_task) {
|
||||
struct hisi_sas_slot *slot;
|
||||
|
||||
slot = &hisi_hba->slot_info
|
||||
[tmf_task.tag_of_task_to_be_managed];
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_hba->hw->slot_complete(hisi_hba, slot, 1);
|
||||
hisi_sas_do_release_task(hisi_hba, task, slot);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_CMD, tag);
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
|
||||
task->task_proto & SAS_PROTOCOL_STP) {
|
||||
if (task->dev->dev_type == SAS_SATA_DEV) {
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_DEV, 0);
|
||||
rc = TMF_RESP_FUNC_COMPLETE;
|
||||
rc = hisi_sas_softreset_ata_disk(device);
|
||||
}
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
|
||||
/* SMP */
|
||||
struct hisi_sas_slot *slot = task->lldd_task;
|
||||
u32 tag = slot->idx;
|
||||
|
||||
hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_CMD, tag);
|
||||
rc = hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_CMD, tag);
|
||||
if (rc == TMF_RESP_FUNC_FAILED) {
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_do_release_task(hisi_hba, task, slot);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -915,37 +1029,66 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
|
|||
|
||||
rc = hisi_sas_debug_I_T_nexus_reset(device);
|
||||
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
|
||||
return 0;
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE) {
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
|
||||
{
|
||||
struct hisi_sas_tmf_task tmf_task;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
unsigned long flags;
|
||||
int rc = TMF_RESP_FUNC_FAILED;
|
||||
|
||||
tmf_task.tmf = TMF_LU_RESET;
|
||||
sas_dev->dev_status = HISI_SAS_DEV_EH;
|
||||
rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE) {
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
if (dev_is_sata(device)) {
|
||||
struct sas_phy *phy;
|
||||
|
||||
/* If failed, fall-through I_T_Nexus reset */
|
||||
dev_err(dev, "lu_reset: for device[%llx]:rc= %d\n",
|
||||
sas_dev->device_id, rc);
|
||||
/* Clear internal IO and then hardreset */
|
||||
rc = hisi_sas_internal_task_abort(hisi_hba, device,
|
||||
HISI_SAS_INT_ABT_DEV, 0);
|
||||
if (rc == TMF_RESP_FUNC_FAILED)
|
||||
goto out;
|
||||
|
||||
phy = sas_get_local_phy(device);
|
||||
|
||||
rc = sas_phy_reset(phy, 1);
|
||||
|
||||
if (rc == 0) {
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
sas_put_local_phy(phy);
|
||||
} else {
|
||||
struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET };
|
||||
|
||||
rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
|
||||
if (rc == TMF_RESP_FUNC_COMPLETE) {
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_release_task(hisi_hba, device);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (rc != TMF_RESP_FUNC_COMPLETE)
|
||||
dev_err(dev, "lu_reset: for device[%llx]:rc= %d\n",
|
||||
sas_dev->device_id, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha)
|
||||
{
|
||||
struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
|
||||
|
||||
return hisi_sas_controller_reset(hisi_hba);
|
||||
}
|
||||
|
||||
static int hisi_sas_query_task(struct sas_task *task)
|
||||
{
|
||||
struct scsi_lun lun;
|
||||
|
@ -990,13 +1133,18 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id,
|
|||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct hisi_sas_port *port;
|
||||
struct hisi_sas_slot *slot;
|
||||
struct asd_sas_port *sas_port = device->port;
|
||||
struct hisi_sas_cmd_hdr *cmd_hdr_base;
|
||||
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!device->port)
|
||||
return -1;
|
||||
|
||||
port = device->port->lldd_port;
|
||||
port = to_hisi_sas_port(sas_port);
|
||||
|
||||
/* simply get a slot and send abort command */
|
||||
rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx);
|
||||
|
@ -1027,14 +1175,11 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id,
|
|||
if (rc)
|
||||
goto err_out_tag;
|
||||
|
||||
/* Port structure is static for the HBA, so
|
||||
* even if the port is deformed it is ok
|
||||
* to reference.
|
||||
*/
|
||||
list_add_tail(&slot->entry, &port->list);
|
||||
spin_lock(&task->task_state_lock);
|
||||
|
||||
list_add_tail(&slot->entry, &sas_dev->list);
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock(&task->task_state_lock);
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
hisi_hba->slot_prep = slot;
|
||||
|
||||
|
@ -1085,7 +1230,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
|||
task->task_done = hisi_sas_task_done;
|
||||
task->slow_task->timer.data = (unsigned long)task;
|
||||
task->slow_task->timer.function = hisi_sas_tmf_timedout;
|
||||
task->slow_task->timer.expires = jiffies + 20*HZ;
|
||||
task->slow_task->timer.expires = jiffies + msecs_to_jiffies(110);
|
||||
add_timer(&task->slow_task->timer);
|
||||
|
||||
/* Lock as we are alloc'ing a slot, which cannot be interrupted */
|
||||
|
@ -1108,15 +1253,16 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
/* TMF timed out, return direct. */
|
||||
if (task->task_status.resp == SAS_TASK_COMPLETE &&
|
||||
task->task_status.stat == TMF_RESP_FUNC_SUCC) {
|
||||
res = TMF_RESP_FUNC_SUCC;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Internal abort timed out */
|
||||
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
|
||||
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
|
||||
dev_err(dev, "internal task abort: timeout.\n");
|
||||
if (task->lldd_task) {
|
||||
struct hisi_sas_slot *slot = task->lldd_task;
|
||||
|
||||
hisi_sas_slot_task_free(hisi_hba, task, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1137,11 +1283,6 @@ static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
|
|||
hisi_sas_port_notify_formed(sas_phy);
|
||||
}
|
||||
|
||||
static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy)
|
||||
{
|
||||
hisi_sas_port_notify_deformed(sas_phy);
|
||||
}
|
||||
|
||||
static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
|
||||
{
|
||||
phy->phy_attached = 0;
|
||||
|
@ -1181,6 +1322,37 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
|
||||
|
||||
void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
|
||||
u32 state)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = &hisi_hba->sha;
|
||||
int phy_no;
|
||||
|
||||
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
|
||||
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
struct asd_sas_port *sas_port = sas_phy->port;
|
||||
struct domain_device *dev;
|
||||
|
||||
if (sas_phy->enabled) {
|
||||
/* Report PHY state change to libsas */
|
||||
if (state & (1 << phy_no))
|
||||
continue;
|
||||
|
||||
if (old_state & (1 << phy_no))
|
||||
/* PHY down but was up before */
|
||||
hisi_sas_phy_down(hisi_hba, phy_no, 0);
|
||||
}
|
||||
if (!sas_port)
|
||||
continue;
|
||||
dev = sas_port->port_dev;
|
||||
|
||||
if (DEV_IS_EXPANDER(dev->dev_type))
|
||||
sas_ha->notify_phy_event(sas_phy, PORTE_BROADCAST_RCVD);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hisi_sas_rescan_topology);
|
||||
|
||||
static struct scsi_transport_template *hisi_sas_stt;
|
||||
|
||||
static struct scsi_host_template hisi_sas_sht = {
|
||||
|
@ -1215,10 +1387,41 @@ static struct sas_domain_function_template hisi_sas_transport_ops = {
|
|||
.lldd_I_T_nexus_reset = hisi_sas_I_T_nexus_reset,
|
||||
.lldd_lu_reset = hisi_sas_lu_reset,
|
||||
.lldd_query_task = hisi_sas_query_task,
|
||||
.lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha,
|
||||
.lldd_port_formed = hisi_sas_port_formed,
|
||||
.lldd_port_deformed = hisi_sas_port_deformed,
|
||||
};
|
||||
|
||||
void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
|
||||
|
||||
for (i = 0; i < hisi_hba->queue_count; i++) {
|
||||
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
|
||||
struct hisi_sas_dq *dq = &hisi_hba->dq[i];
|
||||
|
||||
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
|
||||
memset(hisi_hba->cmd_hdr[i], 0, s);
|
||||
dq->wr_point = 0;
|
||||
|
||||
s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
|
||||
memset(hisi_hba->complete_hdr[i], 0, s);
|
||||
cq->rd_point = 0;
|
||||
}
|
||||
|
||||
s = sizeof(struct hisi_sas_initial_fis) * hisi_hba->n_phy;
|
||||
memset(hisi_hba->initial_fis, 0, s);
|
||||
|
||||
s = max_command_entries * sizeof(struct hisi_sas_iost);
|
||||
memset(hisi_hba->iost, 0, s);
|
||||
|
||||
s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
|
||||
memset(hisi_hba->breakpoint, 0, s);
|
||||
|
||||
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
|
||||
memset(hisi_hba->sata_breakpoint, 0, s);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hisi_sas_init_mem);
|
||||
|
||||
static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
|
||||
{
|
||||
struct platform_device *pdev = hisi_hba->pdev;
|
||||
|
@ -1230,7 +1433,6 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
|
|||
hisi_sas_phy_init(hisi_hba, i);
|
||||
hisi_hba->port[i].port_attached = 0;
|
||||
hisi_hba->port[i].id = -1;
|
||||
INIT_LIST_HEAD(&hisi_hba->port[i].list);
|
||||
}
|
||||
|
||||
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
|
||||
|
@ -1257,7 +1459,6 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
|
|||
&hisi_hba->cmd_hdr_dma[i], GFP_KERNEL);
|
||||
if (!hisi_hba->cmd_hdr[i])
|
||||
goto err_out;
|
||||
memset(hisi_hba->cmd_hdr[i], 0, s);
|
||||
|
||||
/* Completion queue */
|
||||
s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
|
||||
|
@ -1265,7 +1466,6 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
|
|||
&hisi_hba->complete_hdr_dma[i], GFP_KERNEL);
|
||||
if (!hisi_hba->complete_hdr[i])
|
||||
goto err_out;
|
||||
memset(hisi_hba->complete_hdr[i], 0, s);
|
||||
}
|
||||
|
||||
s = HISI_SAS_STATUS_BUF_SZ;
|
||||
|
@ -1300,16 +1500,12 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
|
|||
if (!hisi_hba->iost)
|
||||
goto err_out;
|
||||
|
||||
memset(hisi_hba->iost, 0, s);
|
||||
|
||||
s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
|
||||
hisi_hba->breakpoint = dma_alloc_coherent(dev, s,
|
||||
&hisi_hba->breakpoint_dma, GFP_KERNEL);
|
||||
if (!hisi_hba->breakpoint)
|
||||
goto err_out;
|
||||
|
||||
memset(hisi_hba->breakpoint, 0, s);
|
||||
|
||||
hisi_hba->slot_index_count = max_command_entries;
|
||||
s = hisi_hba->slot_index_count / BITS_PER_BYTE;
|
||||
hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
|
||||
|
@ -1326,14 +1522,13 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
|
|||
&hisi_hba->initial_fis_dma, GFP_KERNEL);
|
||||
if (!hisi_hba->initial_fis)
|
||||
goto err_out;
|
||||
memset(hisi_hba->initial_fis, 0, s);
|
||||
|
||||
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
|
||||
hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
|
||||
&hisi_hba->sata_breakpoint_dma, GFP_KERNEL);
|
||||
if (!hisi_hba->sata_breakpoint)
|
||||
goto err_out;
|
||||
memset(hisi_hba->sata_breakpoint, 0, s);
|
||||
hisi_sas_init_mem(hisi_hba);
|
||||
|
||||
hisi_sas_slot_index_init(hisi_hba);
|
||||
|
||||
|
@ -1404,6 +1599,14 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
|
|||
destroy_workqueue(hisi_hba->wq);
|
||||
}
|
||||
|
||||
static void hisi_sas_rst_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct hisi_hba *hisi_hba =
|
||||
container_of(work, struct hisi_hba, rst_work);
|
||||
|
||||
hisi_sas_controller_reset(hisi_hba);
|
||||
}
|
||||
|
||||
static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
|
||||
const struct hisi_sas_hw *hw)
|
||||
{
|
||||
|
@ -1421,6 +1624,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
|
|||
}
|
||||
hisi_hba = shost_priv(shost);
|
||||
|
||||
INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
|
||||
hisi_hba->hw = hw;
|
||||
hisi_hba->pdev = pdev;
|
||||
hisi_hba->shost = shost;
|
||||
|
@ -1583,7 +1787,6 @@ int hisi_sas_remove(struct platform_device *pdev)
|
|||
struct hisi_hba *hisi_hba = sha->lldd_ha;
|
||||
struct Scsi_Host *shost = sha->core.shost;
|
||||
|
||||
scsi_remove_host(sha->core.shost);
|
||||
sas_unregister_ha(sha);
|
||||
sas_remove_host(sha->core.shost);
|
||||
|
||||
|
|
|
@ -508,6 +508,8 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
|
|||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
u64 qw0, device_id = sas_dev->device_id;
|
||||
struct hisi_sas_itct *itct = &hisi_hba->itct[device_id];
|
||||
struct asd_sas_port *sas_port = device->port;
|
||||
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
|
||||
|
||||
memset(itct, 0, sizeof(*itct));
|
||||
|
||||
|
@ -528,7 +530,7 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
|
|||
(1 << ITCT_HDR_AWT_CONTROL_OFF) |
|
||||
(device->max_linkrate << ITCT_HDR_MAX_CONN_RATE_OFF) |
|
||||
(1 << ITCT_HDR_VALID_LINK_NUM_OFF) |
|
||||
(device->port->id << ITCT_HDR_PORT_ID_OFF));
|
||||
(port->id << ITCT_HDR_PORT_ID_OFF));
|
||||
itct->qw0 = cpu_to_le64(qw0);
|
||||
|
||||
/* qw1 */
|
||||
|
@ -1275,7 +1277,7 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba,
|
|||
}
|
||||
|
||||
static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
|
||||
struct hisi_sas_slot *slot, int abort)
|
||||
struct hisi_sas_slot *slot)
|
||||
{
|
||||
struct sas_task *task = slot->task;
|
||||
struct hisi_sas_device *sas_dev;
|
||||
|
@ -1286,6 +1288,7 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
|
|||
struct hisi_sas_complete_v1_hdr *complete_queue =
|
||||
hisi_hba->complete_hdr[slot->cmplt_queue];
|
||||
struct hisi_sas_complete_v1_hdr *complete_hdr;
|
||||
unsigned long flags;
|
||||
u32 cmplt_hdr_data;
|
||||
|
||||
complete_hdr = &complete_queue[slot->cmplt_queue_slot];
|
||||
|
@ -1298,16 +1301,17 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
|
|||
device = task->dev;
|
||||
sas_dev = device->lldd_dev;
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags &=
|
||||
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
|
||||
task->task_state_flags |= SAS_TASK_STATE_DONE;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
memset(ts, 0, sizeof(*ts));
|
||||
ts->resp = SAS_TASK_COMPLETE;
|
||||
|
||||
if (unlikely(!sas_dev || abort)) {
|
||||
if (!sas_dev)
|
||||
dev_dbg(dev, "slot complete: port has not device\n");
|
||||
if (unlikely(!sas_dev)) {
|
||||
dev_dbg(dev, "slot complete: port has no device\n");
|
||||
ts->stat = SAS_PHY_DOWN;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1620,7 +1624,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
|
|||
*/
|
||||
slot->cmplt_queue_slot = rd_point;
|
||||
slot->cmplt_queue = queue;
|
||||
slot_complete_v1_hw(hisi_hba, slot, 0);
|
||||
slot_complete_v1_hw(hisi_hba, slot);
|
||||
|
||||
if (++rd_point >= HISI_SAS_QUEUE_SLOTS)
|
||||
rd_point = 0;
|
||||
|
@ -1845,8 +1849,6 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
phys_init_v1_hw(hisi_hba);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1860,6 +1862,7 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
|
|||
.get_free_slot = get_free_slot_v1_hw,
|
||||
.start_delivery = start_delivery_v1_hw,
|
||||
.slot_complete = slot_complete_v1_hw,
|
||||
.phys_init = phys_init_v1_hw,
|
||||
.phy_enable = enable_phy_v1_hw,
|
||||
.phy_disable = disable_phy_v1_hw,
|
||||
.phy_hard_reset = phy_hard_reset_v1_hw,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -60,7 +60,7 @@
|
|||
* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.'
|
||||
* with an optional trailing '-' followed by a byte value (0-255).
|
||||
*/
|
||||
#define HPSA_DRIVER_VERSION "3.4.16-0"
|
||||
#define HPSA_DRIVER_VERSION "3.4.18-0"
|
||||
#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
|
||||
#define HPSA "hpsa"
|
||||
|
||||
|
@ -108,10 +108,12 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
|
|||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103c, 0x1920},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1924},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103c, 0x1925},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1926},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1928},
|
||||
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1929},
|
||||
|
@ -171,10 +173,12 @@ static struct board_type products[] = {
|
|||
{0x3354103C, "Smart Array P420i", &SA5_access},
|
||||
{0x3355103C, "Smart Array P220i", &SA5_access},
|
||||
{0x3356103C, "Smart Array P721m", &SA5_access},
|
||||
{0x1920103C, "Smart Array P430i", &SA5_access},
|
||||
{0x1921103C, "Smart Array P830i", &SA5_access},
|
||||
{0x1922103C, "Smart Array P430", &SA5_access},
|
||||
{0x1923103C, "Smart Array P431", &SA5_access},
|
||||
{0x1924103C, "Smart Array P830", &SA5_access},
|
||||
{0x1925103C, "Smart Array P831", &SA5_access},
|
||||
{0x1926103C, "Smart Array P731m", &SA5_access},
|
||||
{0x1928103C, "Smart Array P230i", &SA5_access},
|
||||
{0x1929103C, "Smart Array P530", &SA5_access},
|
||||
|
|
|
@ -3910,12 +3910,6 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
|
|||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
|
||||
tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO);
|
||||
if (!tgt) {
|
||||
dev_err(vhost->dev, "Target allocation failure for scsi id %08llx\n",
|
||||
scsi_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(tgt, 0, sizeof(*tgt));
|
||||
tgt->scsi_id = scsi_id;
|
||||
tgt->new_scsi_id = scsi_id;
|
||||
|
|
|
@ -819,6 +819,29 @@ static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __ipr_sata_eh_done - done function for aborted SATA commands
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function is invoked for ops generated to SATA
|
||||
* devices which are being aborted.
|
||||
*
|
||||
* Return value:
|
||||
* none
|
||||
**/
|
||||
static void __ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ata_queued_cmd *qc = ipr_cmd->qc;
|
||||
struct ipr_sata_port *sata_port = qc->ap->private_data;
|
||||
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
sata_port->ioasa.status |= ATA_BUSY;
|
||||
ata_qc_complete(qc);
|
||||
if (ipr_cmd->eh_comp)
|
||||
complete(ipr_cmd->eh_comp);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_sata_eh_done - done function for aborted SATA commands
|
||||
* @ipr_cmd: ipr command struct
|
||||
|
@ -831,13 +854,35 @@ static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
|
|||
**/
|
||||
static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ata_queued_cmd *qc = ipr_cmd->qc;
|
||||
struct ipr_sata_port *sata_port = qc->ap->private_data;
|
||||
struct ipr_hrr_queue *hrrq = ipr_cmd->hrrq;
|
||||
unsigned long hrrq_flags;
|
||||
|
||||
qc->err_mask |= AC_ERR_OTHER;
|
||||
sata_port->ioasa.status |= ATA_BUSY;
|
||||
spin_lock_irqsave(&hrrq->_lock, hrrq_flags);
|
||||
__ipr_sata_eh_done(ipr_cmd);
|
||||
spin_unlock_irqrestore(&hrrq->_lock, hrrq_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* __ipr_scsi_eh_done - mid-layer done function for aborted ops
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function is invoked by the interrupt handler for
|
||||
* ops generated by the SCSI mid-layer which are being aborted.
|
||||
*
|
||||
* Return value:
|
||||
* none
|
||||
**/
|
||||
static void __ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
|
||||
|
||||
scsi_cmd->result |= (DID_ERROR << 16);
|
||||
|
||||
scsi_dma_unmap(ipr_cmd->scsi_cmd);
|
||||
scsi_cmd->scsi_done(scsi_cmd);
|
||||
if (ipr_cmd->eh_comp)
|
||||
complete(ipr_cmd->eh_comp);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
ata_qc_complete(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -852,15 +897,12 @@ static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
|
|||
**/
|
||||
static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
|
||||
unsigned long hrrq_flags;
|
||||
struct ipr_hrr_queue *hrrq = ipr_cmd->hrrq;
|
||||
|
||||
scsi_cmd->result |= (DID_ERROR << 16);
|
||||
|
||||
scsi_dma_unmap(ipr_cmd->scsi_cmd);
|
||||
scsi_cmd->scsi_done(scsi_cmd);
|
||||
if (ipr_cmd->eh_comp)
|
||||
complete(ipr_cmd->eh_comp);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
spin_lock_irqsave(&hrrq->_lock, hrrq_flags);
|
||||
__ipr_scsi_eh_done(ipr_cmd);
|
||||
spin_unlock_irqrestore(&hrrq->_lock, hrrq_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -890,9 +932,9 @@ static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg)
|
|||
cpu_to_be32(IPR_DRIVER_ILID);
|
||||
|
||||
if (ipr_cmd->scsi_cmd)
|
||||
ipr_cmd->done = ipr_scsi_eh_done;
|
||||
ipr_cmd->done = __ipr_scsi_eh_done;
|
||||
else if (ipr_cmd->qc)
|
||||
ipr_cmd->done = ipr_sata_eh_done;
|
||||
ipr_cmd->done = __ipr_sata_eh_done;
|
||||
|
||||
ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH,
|
||||
IPR_IOASC_IOA_WAS_RESET);
|
||||
|
@ -5005,6 +5047,42 @@ static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_cmnd_is_free - Check if a command is free or not
|
||||
* @ipr_cmd ipr command struct
|
||||
*
|
||||
* Returns:
|
||||
* true / false
|
||||
**/
|
||||
static bool ipr_cmnd_is_free(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_cmnd *loop_cmd;
|
||||
|
||||
list_for_each_entry(loop_cmd, &ipr_cmd->hrrq->hrrq_free_q, queue) {
|
||||
if (loop_cmd == ipr_cmd)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_match_res - Match function for specified resource entry
|
||||
* @ipr_cmd: ipr command struct
|
||||
* @resource: resource entry to match
|
||||
*
|
||||
* Returns:
|
||||
* 1 if command matches sdev / 0 if command does not match sdev
|
||||
**/
|
||||
static int ipr_match_res(struct ipr_cmnd *ipr_cmd, void *resource)
|
||||
{
|
||||
struct ipr_resource_entry *res = resource;
|
||||
|
||||
if (res && ipr_cmd->ioarcb.res_handle == res->res_handle)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_wait_for_ops - Wait for matching commands to complete
|
||||
* @ipr_cmd: ipr command struct
|
||||
|
@ -5018,7 +5096,7 @@ static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device,
|
|||
int (*match)(struct ipr_cmnd *, void *))
|
||||
{
|
||||
struct ipr_cmnd *ipr_cmd;
|
||||
int wait;
|
||||
int wait, i;
|
||||
unsigned long flags;
|
||||
struct ipr_hrr_queue *hrrq;
|
||||
signed long timeout = IPR_ABORT_TASK_TIMEOUT;
|
||||
|
@ -5030,10 +5108,13 @@ static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device,
|
|||
|
||||
for_each_hrrq(hrrq, ioa_cfg) {
|
||||
spin_lock_irqsave(hrrq->lock, flags);
|
||||
list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
|
||||
if (match(ipr_cmd, device)) {
|
||||
ipr_cmd->eh_comp = ∁
|
||||
wait++;
|
||||
for (i = hrrq->min_cmd_id; i <= hrrq->max_cmd_id; i++) {
|
||||
ipr_cmd = ioa_cfg->ipr_cmnd_list[i];
|
||||
if (!ipr_cmnd_is_free(ipr_cmd)) {
|
||||
if (match(ipr_cmd, device)) {
|
||||
ipr_cmd->eh_comp = ∁
|
||||
wait++;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(hrrq->lock, flags);
|
||||
|
@ -5047,10 +5128,13 @@ static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device,
|
|||
|
||||
for_each_hrrq(hrrq, ioa_cfg) {
|
||||
spin_lock_irqsave(hrrq->lock, flags);
|
||||
list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
|
||||
if (match(ipr_cmd, device)) {
|
||||
ipr_cmd->eh_comp = NULL;
|
||||
wait++;
|
||||
for (i = hrrq->min_cmd_id; i <= hrrq->max_cmd_id; i++) {
|
||||
ipr_cmd = ioa_cfg->ipr_cmnd_list[i];
|
||||
if (!ipr_cmnd_is_free(ipr_cmd)) {
|
||||
if (match(ipr_cmd, device)) {
|
||||
ipr_cmd->eh_comp = NULL;
|
||||
wait++;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(hrrq->lock, flags);
|
||||
|
@ -5179,7 +5263,7 @@ static int ipr_sata_reset(struct ata_link *link, unsigned int *classes,
|
|||
struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
|
||||
struct ipr_resource_entry *res;
|
||||
unsigned long lock_flags = 0;
|
||||
int rc = -ENXIO;
|
||||
int rc = -ENXIO, ret;
|
||||
|
||||
ENTER;
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
@ -5193,9 +5277,19 @@ static int ipr_sata_reset(struct ata_link *link, unsigned int *classes,
|
|||
if (res) {
|
||||
rc = ipr_device_reset(ioa_cfg, res);
|
||||
*classes = res->ata_class;
|
||||
}
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
||||
ret = ipr_wait_for_ops(ioa_cfg, res, ipr_match_res);
|
||||
if (ret != SUCCESS) {
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV);
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
||||
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
|
||||
}
|
||||
} else
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
LEAVE;
|
||||
return rc;
|
||||
}
|
||||
|
@ -5217,16 +5311,13 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
|
|||
struct ipr_ioa_cfg *ioa_cfg;
|
||||
struct ipr_resource_entry *res;
|
||||
struct ata_port *ap;
|
||||
int rc = 0;
|
||||
int rc = 0, i;
|
||||
struct ipr_hrr_queue *hrrq;
|
||||
|
||||
ENTER;
|
||||
ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
|
||||
res = scsi_cmd->device->hostdata;
|
||||
|
||||
if (!res)
|
||||
return FAILED;
|
||||
|
||||
/*
|
||||
* If we are currently going through reset/reload, return failed. This will force the
|
||||
* mid-layer to call ipr_eh_host_reset, which will then go to sleep and wait for the
|
||||
|
@ -5239,14 +5330,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
|
|||
|
||||
for_each_hrrq(hrrq, ioa_cfg) {
|
||||
spin_lock(&hrrq->_lock);
|
||||
list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
|
||||
for (i = hrrq->min_cmd_id; i <= hrrq->max_cmd_id; i++) {
|
||||
ipr_cmd = ioa_cfg->ipr_cmnd_list[i];
|
||||
|
||||
if (ipr_cmd->ioarcb.res_handle == res->res_handle) {
|
||||
if (ipr_cmd->scsi_cmd)
|
||||
ipr_cmd->done = ipr_scsi_eh_done;
|
||||
if (ipr_cmd->qc)
|
||||
ipr_cmd->done = ipr_sata_eh_done;
|
||||
if (ipr_cmd->qc &&
|
||||
!(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
|
||||
if (!ipr_cmd->qc)
|
||||
continue;
|
||||
if (ipr_cmnd_is_free(ipr_cmd))
|
||||
continue;
|
||||
|
||||
ipr_cmd->done = ipr_sata_eh_done;
|
||||
if (!(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
|
||||
ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
|
||||
ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
|
||||
}
|
||||
|
@ -5262,19 +5356,6 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd)
|
|||
spin_unlock_irq(scsi_cmd->device->host->host_lock);
|
||||
ata_std_error_handler(ap);
|
||||
spin_lock_irq(scsi_cmd->device->host->host_lock);
|
||||
|
||||
for_each_hrrq(hrrq, ioa_cfg) {
|
||||
spin_lock(&hrrq->_lock);
|
||||
list_for_each_entry(ipr_cmd,
|
||||
&hrrq->hrrq_pending_q, queue) {
|
||||
if (ipr_cmd->ioarcb.res_handle ==
|
||||
res->res_handle) {
|
||||
rc = -EIO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&hrrq->_lock);
|
||||
}
|
||||
} else
|
||||
rc = ipr_device_reset(ioa_cfg, res);
|
||||
res->resetting_device = 0;
|
||||
|
@ -5288,15 +5369,24 @@ static int ipr_eh_dev_reset(struct scsi_cmnd *cmd)
|
|||
{
|
||||
int rc;
|
||||
struct ipr_ioa_cfg *ioa_cfg;
|
||||
struct ipr_resource_entry *res;
|
||||
|
||||
ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
|
||||
res = cmd->device->hostdata;
|
||||
|
||||
if (!res)
|
||||
return FAILED;
|
||||
|
||||
spin_lock_irq(cmd->device->host->host_lock);
|
||||
rc = __ipr_eh_dev_reset(cmd);
|
||||
spin_unlock_irq(cmd->device->host->host_lock);
|
||||
|
||||
if (rc == SUCCESS)
|
||||
rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun);
|
||||
if (rc == SUCCESS) {
|
||||
if (ipr_is_gata(res) && res->sata_port)
|
||||
rc = ipr_wait_for_ops(ioa_cfg, res, ipr_match_res);
|
||||
else
|
||||
rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -5393,7 +5483,7 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
|
|||
struct ipr_resource_entry *res;
|
||||
struct ipr_cmd_pkt *cmd_pkt;
|
||||
u32 ioasc, int_reg;
|
||||
int op_found = 0;
|
||||
int i, op_found = 0;
|
||||
struct ipr_hrr_queue *hrrq;
|
||||
|
||||
ENTER;
|
||||
|
@ -5422,11 +5512,12 @@ static int ipr_cancel_op(struct scsi_cmnd *scsi_cmd)
|
|||
|
||||
for_each_hrrq(hrrq, ioa_cfg) {
|
||||
spin_lock(&hrrq->_lock);
|
||||
list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) {
|
||||
if (ipr_cmd->scsi_cmd == scsi_cmd) {
|
||||
ipr_cmd->done = ipr_scsi_eh_done;
|
||||
op_found = 1;
|
||||
break;
|
||||
for (i = hrrq->min_cmd_id; i <= hrrq->max_cmd_id; i++) {
|
||||
if (ioa_cfg->ipr_cmnd_list[i]->scsi_cmd == scsi_cmd) {
|
||||
if (!ipr_cmnd_is_free(ioa_cfg->ipr_cmnd_list[i])) {
|
||||
op_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&hrrq->_lock);
|
||||
|
@ -5917,7 +6008,7 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
|
|||
}
|
||||
|
||||
/**
|
||||
* ipr_erp_done - Process completion of ERP for a device
|
||||
* __ipr_erp_done - Process completion of ERP for a device
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function copies the sense buffer into the scsi_cmd
|
||||
|
@ -5926,7 +6017,7 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
|
|||
* Return value:
|
||||
* nothing
|
||||
**/
|
||||
static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
|
||||
static void __ipr_erp_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
|
||||
struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
|
||||
|
@ -5947,8 +6038,30 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
|
|||
res->in_erp = 0;
|
||||
}
|
||||
scsi_dma_unmap(ipr_cmd->scsi_cmd);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
scsi_cmd->scsi_done(scsi_cmd);
|
||||
if (ipr_cmd->eh_comp)
|
||||
complete(ipr_cmd->eh_comp);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_erp_done - Process completion of ERP for a device
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function copies the sense buffer into the scsi_cmd
|
||||
* struct and pushes the scsi_done function.
|
||||
*
|
||||
* Return value:
|
||||
* nothing
|
||||
**/
|
||||
static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_hrr_queue *hrrq = ipr_cmd->hrrq;
|
||||
unsigned long hrrq_flags;
|
||||
|
||||
spin_lock_irqsave(&hrrq->_lock, hrrq_flags);
|
||||
__ipr_erp_done(ipr_cmd);
|
||||
spin_unlock_irqrestore(&hrrq->_lock, hrrq_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5983,7 +6096,7 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
|
|||
}
|
||||
|
||||
/**
|
||||
* ipr_erp_request_sense - Send request sense to a device
|
||||
* __ipr_erp_request_sense - Send request sense to a device
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function sends a request sense to a device as a result
|
||||
|
@ -5992,13 +6105,13 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
|
|||
* Return value:
|
||||
* nothing
|
||||
**/
|
||||
static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
|
||||
static void __ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
|
||||
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
|
||||
|
||||
if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
|
||||
ipr_erp_done(ipr_cmd);
|
||||
__ipr_erp_done(ipr_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6018,6 +6131,26 @@ static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
|
|||
IPR_REQUEST_SENSE_TIMEOUT * 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_erp_request_sense - Send request sense to a device
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function sends a request sense to a device as a result
|
||||
* of a check condition.
|
||||
*
|
||||
* Return value:
|
||||
* nothing
|
||||
**/
|
||||
static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_hrr_queue *hrrq = ipr_cmd->hrrq;
|
||||
unsigned long hrrq_flags;
|
||||
|
||||
spin_lock_irqsave(&hrrq->_lock, hrrq_flags);
|
||||
__ipr_erp_request_sense(ipr_cmd);
|
||||
spin_unlock_irqrestore(&hrrq->_lock, hrrq_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_erp_cancel_all - Send cancel all to a device
|
||||
* @ipr_cmd: ipr command struct
|
||||
|
@ -6041,7 +6174,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd)
|
|||
ipr_reinit_ipr_cmnd_for_erp(ipr_cmd);
|
||||
|
||||
if (!scsi_cmd->device->simple_tags) {
|
||||
ipr_erp_request_sense(ipr_cmd);
|
||||
__ipr_erp_request_sense(ipr_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6261,7 +6394,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
|
|||
u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK;
|
||||
|
||||
if (!res) {
|
||||
ipr_scsi_eh_done(ipr_cmd);
|
||||
__ipr_scsi_eh_done(ipr_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6343,8 +6476,10 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
|
|||
}
|
||||
|
||||
scsi_dma_unmap(ipr_cmd->scsi_cmd);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
scsi_cmd->scsi_done(scsi_cmd);
|
||||
if (ipr_cmd->eh_comp)
|
||||
complete(ipr_cmd->eh_comp);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6370,8 +6505,10 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
|
|||
scsi_dma_unmap(scsi_cmd);
|
||||
|
||||
spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
scsi_cmd->scsi_done(scsi_cmd);
|
||||
if (ipr_cmd->eh_comp)
|
||||
complete(ipr_cmd->eh_comp);
|
||||
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
|
||||
spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags);
|
||||
} else {
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
/*
|
||||
* Literals
|
||||
*/
|
||||
#define IPR_DRIVER_VERSION "2.6.3"
|
||||
#define IPR_DRIVER_DATE "(October 17, 2015)"
|
||||
#define IPR_DRIVER_VERSION "2.6.4"
|
||||
#define IPR_DRIVER_DATE "(March 14, 2017)"
|
||||
|
||||
/*
|
||||
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
|
||||
|
|
|
@ -272,7 +272,6 @@ static void isci_unregister(struct isci_host *isci_host)
|
|||
return;
|
||||
|
||||
shost = to_shost(isci_host);
|
||||
scsi_remove_host(shost);
|
||||
sas_unregister_ha(&isci_host->sas_ha);
|
||||
|
||||
sas_remove_host(shost);
|
||||
|
|
|
@ -154,7 +154,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
|
|||
memset(fsp, 0, sizeof(*fsp));
|
||||
fsp->lp = lport;
|
||||
fsp->xfer_ddp = FC_XID_UNKNOWN;
|
||||
atomic_set(&fsp->ref_cnt, 1);
|
||||
refcount_set(&fsp->ref_cnt, 1);
|
||||
init_timer(&fsp->timer);
|
||||
fsp->timer.data = (unsigned long)fsp;
|
||||
INIT_LIST_HEAD(&fsp->list);
|
||||
|
@ -175,7 +175,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
|
|||
*/
|
||||
static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp)
|
||||
{
|
||||
if (atomic_dec_and_test(&fsp->ref_cnt)) {
|
||||
if (refcount_dec_and_test(&fsp->ref_cnt)) {
|
||||
struct fc_fcp_internal *si = fc_get_scsi_internal(fsp->lp);
|
||||
|
||||
mempool_free(fsp, si->scsi_pkt_pool);
|
||||
|
@ -188,7 +188,7 @@ static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp)
|
|||
*/
|
||||
static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp)
|
||||
{
|
||||
atomic_inc(&fsp->ref_cnt);
|
||||
refcount_inc(&fsp->ref_cnt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -887,8 +887,6 @@ static void fc_lport_recv_flogi_req(struct fc_lport *lport,
|
|||
static void fc_lport_recv_els_req(struct fc_lport *lport,
|
||||
struct fc_frame *fp)
|
||||
{
|
||||
void (*recv)(struct fc_lport *, struct fc_frame *);
|
||||
|
||||
mutex_lock(&lport->lp_mutex);
|
||||
|
||||
/*
|
||||
|
@ -902,31 +900,31 @@ static void fc_lport_recv_els_req(struct fc_lport *lport,
|
|||
/*
|
||||
* Check opcode.
|
||||
*/
|
||||
recv = fc_rport_recv_req;
|
||||
switch (fc_frame_payload_op(fp)) {
|
||||
case ELS_FLOGI:
|
||||
if (!lport->point_to_multipoint)
|
||||
recv = fc_lport_recv_flogi_req;
|
||||
fc_lport_recv_flogi_req(lport, fp);
|
||||
break;
|
||||
case ELS_LOGO:
|
||||
if (fc_frame_sid(fp) == FC_FID_FLOGI)
|
||||
recv = fc_lport_recv_logo_req;
|
||||
fc_lport_recv_logo_req(lport, fp);
|
||||
break;
|
||||
case ELS_RSCN:
|
||||
recv = lport->tt.disc_recv_req;
|
||||
lport->tt.disc_recv_req(lport, fp);
|
||||
break;
|
||||
case ELS_ECHO:
|
||||
recv = fc_lport_recv_echo_req;
|
||||
fc_lport_recv_echo_req(lport, fp);
|
||||
break;
|
||||
case ELS_RLIR:
|
||||
recv = fc_lport_recv_rlir_req;
|
||||
fc_lport_recv_rlir_req(lport, fp);
|
||||
break;
|
||||
case ELS_RNID:
|
||||
recv = fc_lport_recv_rnid_req;
|
||||
fc_lport_recv_rnid_req(lport, fp);
|
||||
break;
|
||||
default:
|
||||
fc_rport_recv_req(lport, fp);
|
||||
break;
|
||||
}
|
||||
|
||||
recv(lport, fp);
|
||||
}
|
||||
mutex_unlock(&lport->lp_mutex);
|
||||
}
|
||||
|
|
|
@ -517,13 +517,13 @@ static void iscsi_free_task(struct iscsi_task *task)
|
|||
|
||||
void __iscsi_get_task(struct iscsi_task *task)
|
||||
{
|
||||
atomic_inc(&task->refcount);
|
||||
refcount_inc(&task->refcount);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__iscsi_get_task);
|
||||
|
||||
void __iscsi_put_task(struct iscsi_task *task)
|
||||
{
|
||||
if (atomic_dec_and_test(&task->refcount))
|
||||
if (refcount_dec_and_test(&task->refcount))
|
||||
iscsi_free_task(task);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__iscsi_put_task);
|
||||
|
@ -749,7 +749,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
|||
* released by the lld when it has transmitted the task for
|
||||
* pdus we do not expect a response for.
|
||||
*/
|
||||
atomic_set(&task->refcount, 1);
|
||||
refcount_set(&task->refcount, 1);
|
||||
task->conn = conn;
|
||||
task->sc = NULL;
|
||||
INIT_LIST_HEAD(&task->running);
|
||||
|
@ -1638,7 +1638,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
|
|||
sc->SCp.phase = conn->session->age;
|
||||
sc->SCp.ptr = (char *) task;
|
||||
|
||||
atomic_set(&task->refcount, 1);
|
||||
refcount_set(&task->refcount, 1);
|
||||
task->state = ISCSI_TASK_PENDING;
|
||||
task->conn = conn;
|
||||
task->sc = sc;
|
||||
|
|
|
@ -566,13 +566,6 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
|
||||
|
||||
|
||||
void sas_domain_release_transport(struct scsi_transport_template *stt)
|
||||
{
|
||||
sas_release_transport(stt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sas_domain_release_transport);
|
||||
|
||||
/* ---------- SAS Class register/unregister ---------- */
|
||||
|
||||
static int __init sas_class_init(void)
|
||||
|
|
|
@ -491,9 +491,6 @@ int sas_eh_abort_handler(struct scsi_cmnd *cmd)
|
|||
struct Scsi_Host *host = cmd->device->host;
|
||||
struct sas_internal *i = to_sas_internal(host->transportt);
|
||||
|
||||
if (current != host->ehandler)
|
||||
return FAILED;
|
||||
|
||||
if (!i->dft->lldd_abort_task)
|
||||
return FAILED;
|
||||
|
||||
|
@ -616,8 +613,6 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
|||
SAS_DPRINTK("trying to find task 0x%p\n", task);
|
||||
res = sas_scsi_find_task(task);
|
||||
|
||||
cmd->eh_eflags = 0;
|
||||
|
||||
switch (res) {
|
||||
case TASK_IS_DONE:
|
||||
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
|
||||
|
|
|
@ -181,7 +181,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
|
|||
wwn_to_u64(vport->fc_nodename.u.wwn),
|
||||
phba->targetport->port_id);
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE,
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
"\nNVME Target: Statistics\n");
|
||||
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
|
||||
len += snprintf(buf+len, PAGE_SIZE-len,
|
||||
|
@ -326,7 +326,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
|
|||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE, "\nNVME Statistics\n");
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, "\nNVME Statistics\n");
|
||||
len += snprintf(buf+len, PAGE_SIZE-len,
|
||||
"LS: Xmt %016llx Cmpl %016llx\n",
|
||||
phba->fc4NvmeLsRequests,
|
||||
|
|
|
@ -55,6 +55,7 @@ struct mac_esp_priv {
|
|||
int error;
|
||||
};
|
||||
static struct esp *esp_chips[2];
|
||||
static DEFINE_SPINLOCK(esp_chips_lock);
|
||||
|
||||
#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
|
||||
platform_get_drvdata((struct platform_device *) \
|
||||
|
@ -562,15 +563,18 @@ static int esp_mac_probe(struct platform_device *dev)
|
|||
}
|
||||
|
||||
host->irq = IRQ_MAC_SCSI;
|
||||
esp_chips[dev->id] = esp;
|
||||
mb();
|
||||
if (esp_chips[!dev->id] == NULL) {
|
||||
err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
|
||||
if (err < 0) {
|
||||
esp_chips[dev->id] = NULL;
|
||||
goto fail_free_priv;
|
||||
}
|
||||
|
||||
/* The request_irq() call is intended to succeed for the first device
|
||||
* and fail for the second device.
|
||||
*/
|
||||
err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
|
||||
spin_lock(&esp_chips_lock);
|
||||
if (err < 0 && esp_chips[!dev->id] == NULL) {
|
||||
spin_unlock(&esp_chips_lock);
|
||||
goto fail_free_priv;
|
||||
}
|
||||
esp_chips[dev->id] = esp;
|
||||
spin_unlock(&esp_chips_lock);
|
||||
|
||||
err = scsi_esp_register(esp, &dev->dev);
|
||||
if (err)
|
||||
|
@ -579,8 +583,13 @@ static int esp_mac_probe(struct platform_device *dev)
|
|||
return 0;
|
||||
|
||||
fail_free_irq:
|
||||
if (esp_chips[!dev->id] == NULL)
|
||||
free_irq(host->irq, esp);
|
||||
spin_lock(&esp_chips_lock);
|
||||
esp_chips[dev->id] = NULL;
|
||||
if (esp_chips[!dev->id] == NULL) {
|
||||
spin_unlock(&esp_chips_lock);
|
||||
free_irq(host->irq, NULL);
|
||||
} else
|
||||
spin_unlock(&esp_chips_lock);
|
||||
fail_free_priv:
|
||||
kfree(mep);
|
||||
fail_free_command_block:
|
||||
|
@ -599,9 +608,13 @@ static int esp_mac_remove(struct platform_device *dev)
|
|||
|
||||
scsi_esp_unregister(esp);
|
||||
|
||||
spin_lock(&esp_chips_lock);
|
||||
esp_chips[dev->id] = NULL;
|
||||
if (!(esp_chips[0] || esp_chips[1]))
|
||||
if (esp_chips[!dev->id] == NULL) {
|
||||
spin_unlock(&esp_chips_lock);
|
||||
free_irq(irq, NULL);
|
||||
} else
|
||||
spin_unlock(&esp_chips_lock);
|
||||
|
||||
kfree(mep);
|
||||
|
||||
|
|
|
@ -1025,7 +1025,6 @@ _base_interrupt(int irq, void *bus_id)
|
|||
0 : ioc->reply_free_host_index + 1;
|
||||
ioc->reply_free[ioc->reply_free_host_index] =
|
||||
cpu_to_le32(reply);
|
||||
wmb();
|
||||
writel(ioc->reply_free_host_index,
|
||||
&ioc->chip->ReplyFreeHostIndex);
|
||||
}
|
||||
|
@ -1074,7 +1073,6 @@ _base_interrupt(int irq, void *bus_id)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
wmb();
|
||||
if (ioc->is_warpdrive) {
|
||||
writel(reply_q->reply_post_host_index,
|
||||
ioc->reply_post_host_index[msix_index]);
|
||||
|
|
|
@ -8283,7 +8283,6 @@ static void scsih_remove(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
sas_remove_host(shost);
|
||||
scsi_remove_host(shost);
|
||||
mpt3sas_base_detach(ioc);
|
||||
spin_lock(&gioc_lock);
|
||||
list_del(&ioc->list);
|
||||
|
|
|
@ -642,7 +642,6 @@ static void mvs_pci_remove(struct pci_dev *pdev)
|
|||
tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
|
||||
#endif
|
||||
|
||||
scsi_remove_host(mvi->shost);
|
||||
sas_unregister_ha(sha);
|
||||
sas_remove_host(mvi->shost);
|
||||
|
||||
|
|
|
@ -210,39 +210,27 @@ static int mvumi_make_sgl(struct mvumi_hba *mhba, struct scsi_cmnd *scmd,
|
|||
unsigned int sgnum = scsi_sg_count(scmd);
|
||||
dma_addr_t busaddr;
|
||||
|
||||
if (sgnum) {
|
||||
sg = scsi_sglist(scmd);
|
||||
*sg_count = pci_map_sg(mhba->pdev, sg, sgnum,
|
||||
(int) scmd->sc_data_direction);
|
||||
if (*sg_count > mhba->max_sge) {
|
||||
dev_err(&mhba->pdev->dev, "sg count[0x%x] is bigger "
|
||||
"than max sg[0x%x].\n",
|
||||
*sg_count, mhba->max_sge);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < *sg_count; i++) {
|
||||
busaddr = sg_dma_address(&sg[i]);
|
||||
m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(busaddr));
|
||||
m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(busaddr));
|
||||
m_sg->flags = 0;
|
||||
sgd_setsz(mhba, m_sg, cpu_to_le32(sg_dma_len(&sg[i])));
|
||||
if ((i + 1) == *sg_count)
|
||||
m_sg->flags |= 1U << mhba->eot_flag;
|
||||
|
||||
sgd_inc(mhba, m_sg);
|
||||
}
|
||||
} else {
|
||||
scmd->SCp.dma_handle = scsi_bufflen(scmd) ?
|
||||
pci_map_single(mhba->pdev, scsi_sglist(scmd),
|
||||
scsi_bufflen(scmd),
|
||||
(int) scmd->sc_data_direction)
|
||||
: 0;
|
||||
busaddr = scmd->SCp.dma_handle;
|
||||
sg = scsi_sglist(scmd);
|
||||
*sg_count = pci_map_sg(mhba->pdev, sg, sgnum,
|
||||
(int) scmd->sc_data_direction);
|
||||
if (*sg_count > mhba->max_sge) {
|
||||
dev_err(&mhba->pdev->dev,
|
||||
"sg count[0x%x] is bigger than max sg[0x%x].\n",
|
||||
*sg_count, mhba->max_sge);
|
||||
pci_unmap_sg(mhba->pdev, sg, sgnum,
|
||||
(int) scmd->sc_data_direction);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < *sg_count; i++) {
|
||||
busaddr = sg_dma_address(&sg[i]);
|
||||
m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(busaddr));
|
||||
m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(busaddr));
|
||||
m_sg->flags = 1U << mhba->eot_flag;
|
||||
sgd_setsz(mhba, m_sg, cpu_to_le32(scsi_bufflen(scmd)));
|
||||
*sg_count = 1;
|
||||
m_sg->flags = 0;
|
||||
sgd_setsz(mhba, m_sg, cpu_to_le32(sg_dma_len(&sg[i])));
|
||||
if ((i + 1) == *sg_count)
|
||||
m_sg->flags |= 1U << mhba->eot_flag;
|
||||
|
||||
sgd_inc(mhba, m_sg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1350,21 +1338,10 @@ static void mvumi_complete_cmd(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
|
|||
break;
|
||||
}
|
||||
|
||||
if (scsi_bufflen(scmd)) {
|
||||
if (scsi_sg_count(scmd)) {
|
||||
pci_unmap_sg(mhba->pdev,
|
||||
scsi_sglist(scmd),
|
||||
scsi_sg_count(scmd),
|
||||
(int) scmd->sc_data_direction);
|
||||
} else {
|
||||
pci_unmap_single(mhba->pdev,
|
||||
scmd->SCp.dma_handle,
|
||||
scsi_bufflen(scmd),
|
||||
(int) scmd->sc_data_direction);
|
||||
|
||||
scmd->SCp.dma_handle = 0;
|
||||
}
|
||||
}
|
||||
if (scsi_bufflen(scmd))
|
||||
pci_unmap_sg(mhba->pdev, scsi_sglist(scmd),
|
||||
scsi_sg_count(scmd),
|
||||
(int) scmd->sc_data_direction);
|
||||
cmd->scmd->scsi_done(scmd);
|
||||
mvumi_return_cmd(mhba, cmd);
|
||||
}
|
||||
|
@ -2171,19 +2148,9 @@ static enum blk_eh_timer_return mvumi_timed_out(struct scsi_cmnd *scmd)
|
|||
scmd->result = (DRIVER_INVALID << 24) | (DID_ABORT << 16);
|
||||
scmd->SCp.ptr = NULL;
|
||||
if (scsi_bufflen(scmd)) {
|
||||
if (scsi_sg_count(scmd)) {
|
||||
pci_unmap_sg(mhba->pdev,
|
||||
scsi_sglist(scmd),
|
||||
scsi_sg_count(scmd),
|
||||
(int)scmd->sc_data_direction);
|
||||
} else {
|
||||
pci_unmap_single(mhba->pdev,
|
||||
scmd->SCp.dma_handle,
|
||||
scsi_bufflen(scmd),
|
||||
(int)scmd->sc_data_direction);
|
||||
|
||||
scmd->SCp.dma_handle = 0;
|
||||
}
|
||||
pci_unmap_sg(mhba->pdev, scsi_sglist(scmd),
|
||||
scsi_sg_count(scmd),
|
||||
(int)scmd->sc_data_direction);
|
||||
}
|
||||
mvumi_return_cmd(mhba, cmd);
|
||||
spin_unlock_irqrestore(mhba->shost->host_lock, flags);
|
||||
|
|
|
@ -464,14 +464,15 @@ static int osd_probe(struct device *dev)
|
|||
/* hold one more reference to the scsi_device that will get released
|
||||
* in __release, in case a logout is happening while fs is mounted
|
||||
*/
|
||||
scsi_device_get(scsi_device);
|
||||
if (scsi_device_get(scsi_device))
|
||||
goto err_put_disk;
|
||||
osd_dev_init(&oud->od, scsi_device);
|
||||
|
||||
/* Detect the OSD Version */
|
||||
error = __detect_osd(oud);
|
||||
if (error) {
|
||||
OSD_ERR("osd detection failed, non-compatible OSD device\n");
|
||||
goto err_put_disk;
|
||||
goto err_put_sdev;
|
||||
}
|
||||
|
||||
/* init the char-device for communication with user-mode */
|
||||
|
@ -508,8 +509,9 @@ static int osd_probe(struct device *dev)
|
|||
|
||||
err_put_cdev:
|
||||
cdev_del(&oud->cdev);
|
||||
err_put_disk:
|
||||
err_put_sdev:
|
||||
scsi_device_put(scsi_device);
|
||||
err_put_disk:
|
||||
put_disk(disk);
|
||||
err_free_osd:
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
@ -524,10 +526,9 @@ static int osd_remove(struct device *dev)
|
|||
struct scsi_device *scsi_device = to_scsi_device(dev);
|
||||
struct osd_uld_device *oud = dev_get_drvdata(dev);
|
||||
|
||||
if (!oud || (oud->od.scsi_device != scsi_device)) {
|
||||
OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
|
||||
dev, oud, oud ? oud->od.scsi_device : NULL,
|
||||
scsi_device);
|
||||
if (oud->od.scsi_device != scsi_device) {
|
||||
OSD_ERR("Half cooked osd-device %p, || %p!=%p",
|
||||
dev, oud->od.scsi_device, scsi_device);
|
||||
}
|
||||
|
||||
device_unregister(&oud->class_dev);
|
||||
|
|
|
@ -1088,7 +1088,6 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
|
|||
struct pm8001_hba_info *pm8001_ha;
|
||||
int i, j;
|
||||
pm8001_ha = sha->lldd_ha;
|
||||
scsi_remove_host(pm8001_ha->shost);
|
||||
sas_unregister_ha(sha);
|
||||
sas_remove_host(pm8001_ha->shost);
|
||||
list_del(&pm8001_ha->list);
|
||||
|
|
|
@ -77,7 +77,7 @@ static atomic_t pmcraid_adapter_count = ATOMIC_INIT(0);
|
|||
*/
|
||||
static unsigned int pmcraid_major;
|
||||
static struct class *pmcraid_class;
|
||||
DECLARE_BITMAP(pmcraid_minor, PMCRAID_MAX_ADAPTERS);
|
||||
static DECLARE_BITMAP(pmcraid_minor, PMCRAID_MAX_ADAPTERS);
|
||||
|
||||
/*
|
||||
* Module parameters
|
||||
|
@ -175,7 +175,7 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev)
|
|||
if (fw_version <= PMCRAID_FW_VERSION_1)
|
||||
target = temp->cfg_entry.unique_flags1;
|
||||
else
|
||||
target = temp->cfg_entry.array_id & 0xFF;
|
||||
target = le16_to_cpu(temp->cfg_entry.array_id) & 0xFF;
|
||||
|
||||
if (target > PMCRAID_MAX_VSET_TARGETS)
|
||||
continue;
|
||||
|
@ -330,7 +330,7 @@ static void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index)
|
|||
ioarcb->request_flags0 = 0;
|
||||
ioarcb->request_flags1 = 0;
|
||||
ioarcb->cmd_timeout = 0;
|
||||
ioarcb->ioarcb_bus_addr &= (~0x1FULL);
|
||||
ioarcb->ioarcb_bus_addr &= cpu_to_le64(~0x1FULL);
|
||||
ioarcb->ioadl_bus_addr = 0;
|
||||
ioarcb->ioadl_length = 0;
|
||||
ioarcb->data_transfer_length = 0;
|
||||
|
@ -345,7 +345,7 @@ static void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index)
|
|||
cmd->scsi_cmd = NULL;
|
||||
cmd->release = 0;
|
||||
cmd->completion_req = 0;
|
||||
cmd->sense_buffer = 0;
|
||||
cmd->sense_buffer = NULL;
|
||||
cmd->sense_buffer_dma = 0;
|
||||
cmd->dma_handle = 0;
|
||||
init_timer(&cmd->timer);
|
||||
|
@ -898,8 +898,7 @@ static void _pmcraid_fire_command(struct pmcraid_cmd *cmd)
|
|||
|
||||
/* driver writes lower 32-bit value of IOARCB address only */
|
||||
mb();
|
||||
iowrite32(le32_to_cpu(cmd->ioa_cb->ioarcb.ioarcb_bus_addr),
|
||||
pinstance->ioarrin);
|
||||
iowrite32(le64_to_cpu(cmd->ioa_cb->ioarcb.ioarcb_bus_addr), pinstance->ioarrin);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1051,7 +1050,7 @@ static void pmcraid_get_fwversion(struct pmcraid_cmd *cmd)
|
|||
offsetof(struct pmcraid_ioarcb,
|
||||
add_data.u.ioadl[0]));
|
||||
ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc));
|
||||
ioarcb->ioarcb_bus_addr &= ~(0x1FULL);
|
||||
ioarcb->ioarcb_bus_addr &= cpu_to_le64(~(0x1FULL));
|
||||
|
||||
ioarcb->request_flags0 |= NO_LINK_DESCS;
|
||||
ioarcb->data_transfer_length = cpu_to_le32(data_size);
|
||||
|
@ -1077,7 +1076,7 @@ static void pmcraid_identify_hrrq(struct pmcraid_cmd *cmd)
|
|||
struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb;
|
||||
int index = cmd->hrrq_index;
|
||||
__be64 hrrq_addr = cpu_to_be64(pinstance->hrrq_start_bus_addr[index]);
|
||||
u32 hrrq_size = cpu_to_be32(sizeof(u32) * PMCRAID_MAX_CMD);
|
||||
__be32 hrrq_size = cpu_to_be32(sizeof(u32) * PMCRAID_MAX_CMD);
|
||||
void (*done_function)(struct pmcraid_cmd *);
|
||||
|
||||
pmcraid_reinit_cmdblk(cmd);
|
||||
|
@ -1202,7 +1201,7 @@ static struct pmcraid_cmd *pmcraid_init_hcam
|
|||
|
||||
ioadl[0].flags |= IOADL_FLAGS_READ_LAST;
|
||||
ioadl[0].data_len = cpu_to_le32(rcb_size);
|
||||
ioadl[0].address = cpu_to_le32(dma);
|
||||
ioadl[0].address = cpu_to_le64(dma);
|
||||
|
||||
cmd->cmd_done = cmd_done;
|
||||
return cmd;
|
||||
|
@ -1237,7 +1236,13 @@ static void pmcraid_prepare_cancel_cmd(
|
|||
)
|
||||
{
|
||||
struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb;
|
||||
__be64 ioarcb_addr = cmd_to_cancel->ioa_cb->ioarcb.ioarcb_bus_addr;
|
||||
__be64 ioarcb_addr;
|
||||
|
||||
/* IOARCB address of the command to be cancelled is given in
|
||||
* cdb[2]..cdb[9] is Big-Endian format. Note that length bits in
|
||||
* IOARCB address are not masked.
|
||||
*/
|
||||
ioarcb_addr = cpu_to_be64(le64_to_cpu(cmd_to_cancel->ioa_cb->ioarcb.ioarcb_bus_addr));
|
||||
|
||||
/* Get the resource handle to where the command to be aborted has been
|
||||
* sent.
|
||||
|
@ -1247,11 +1252,6 @@ static void pmcraid_prepare_cancel_cmd(
|
|||
memset(ioarcb->cdb, 0, PMCRAID_MAX_CDB_LEN);
|
||||
ioarcb->cdb[0] = PMCRAID_ABORT_CMD;
|
||||
|
||||
/* IOARCB address of the command to be cancelled is given in
|
||||
* cdb[2]..cdb[9] is Big-Endian format. Note that length bits in
|
||||
* IOARCB address are not masked.
|
||||
*/
|
||||
ioarcb_addr = cpu_to_be64(ioarcb_addr);
|
||||
memcpy(&(ioarcb->cdb[2]), &ioarcb_addr, sizeof(ioarcb_addr));
|
||||
}
|
||||
|
||||
|
@ -1493,7 +1493,7 @@ static int pmcraid_notify_ccn(struct pmcraid_instance *pinstance)
|
|||
{
|
||||
return pmcraid_notify_aen(pinstance,
|
||||
pinstance->ccn.msg,
|
||||
pinstance->ccn.hcam->data_len +
|
||||
le32_to_cpu(pinstance->ccn.hcam->data_len) +
|
||||
sizeof(struct pmcraid_hcam_hdr));
|
||||
}
|
||||
|
||||
|
@ -1508,7 +1508,7 @@ static int pmcraid_notify_ldn(struct pmcraid_instance *pinstance)
|
|||
{
|
||||
return pmcraid_notify_aen(pinstance,
|
||||
pinstance->ldn.msg,
|
||||
pinstance->ldn.hcam->data_len +
|
||||
le32_to_cpu(pinstance->ldn.hcam->data_len) +
|
||||
sizeof(struct pmcraid_hcam_hdr));
|
||||
}
|
||||
|
||||
|
@ -1556,10 +1556,10 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
|
|||
|
||||
pmcraid_info("CCN(%x): %x timestamp: %llx type: %x lost: %x flags: %x \
|
||||
res: %x:%x:%x:%x\n",
|
||||
pinstance->ccn.hcam->ilid,
|
||||
le32_to_cpu(pinstance->ccn.hcam->ilid),
|
||||
pinstance->ccn.hcam->op_code,
|
||||
((pinstance->ccn.hcam->timestamp1) |
|
||||
((pinstance->ccn.hcam->timestamp2 & 0xffffffffLL) << 32)),
|
||||
(le32_to_cpu(pinstance->ccn.hcam->timestamp1) |
|
||||
((le32_to_cpu(pinstance->ccn.hcam->timestamp2) & 0xffffffffLL) << 32)),
|
||||
pinstance->ccn.hcam->notification_type,
|
||||
pinstance->ccn.hcam->notification_lost,
|
||||
pinstance->ccn.hcam->flags,
|
||||
|
@ -1570,7 +1570,7 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
|
|||
RES_IS_VSET(*cfg_entry) ?
|
||||
(fw_version <= PMCRAID_FW_VERSION_1 ?
|
||||
cfg_entry->unique_flags1 :
|
||||
cfg_entry->array_id & 0xFF) :
|
||||
le16_to_cpu(cfg_entry->array_id) & 0xFF) :
|
||||
RES_TARGET(cfg_entry->resource_address),
|
||||
RES_LUN(cfg_entry->resource_address));
|
||||
|
||||
|
@ -1658,7 +1658,7 @@ static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
|
|||
if (fw_version <= PMCRAID_FW_VERSION_1)
|
||||
res->cfg_entry.unique_flags1 &= 0x7F;
|
||||
else
|
||||
res->cfg_entry.array_id &= 0xFF;
|
||||
res->cfg_entry.array_id &= cpu_to_le16(0xFF);
|
||||
res->change_detected = RES_CHANGE_DEL;
|
||||
res->cfg_entry.resource_handle =
|
||||
PMCRAID_INVALID_RES_HANDLE;
|
||||
|
@ -1716,8 +1716,8 @@ static void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd)
|
|||
/* log the error string */
|
||||
pmcraid_err("cmd [%x] for resource %x failed with %x(%s)\n",
|
||||
cmd->ioa_cb->ioarcb.cdb[0],
|
||||
cmd->ioa_cb->ioarcb.resource_handle,
|
||||
le32_to_cpu(ioasc), error_info->error_string);
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.resource_handle),
|
||||
ioasc, error_info->error_string);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2034,7 +2034,7 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance)
|
|||
cmd->ioa_cb->ioasa.ioasc =
|
||||
cpu_to_le32(PMCRAID_IOASC_IOA_WAS_RESET);
|
||||
cmd->ioa_cb->ioasa.ilid =
|
||||
cpu_to_be32(PMCRAID_DRIVER_ILID);
|
||||
cpu_to_le32(PMCRAID_DRIVER_ILID);
|
||||
|
||||
/* In case the command timer is still running */
|
||||
del_timer(&cmd->timer);
|
||||
|
@ -2373,46 +2373,43 @@ static int pmcraid_reset_reload(
|
|||
spin_lock_irqsave(pinstance->host->host_lock, lock_flags);
|
||||
|
||||
if (pinstance->ioa_state == IOA_STATE_DEAD) {
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock,
|
||||
lock_flags);
|
||||
pmcraid_info("reset_reload: IOA is dead\n");
|
||||
return reset;
|
||||
} else if (pinstance->ioa_state == target_state) {
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (pinstance->ioa_state == target_state) {
|
||||
reset = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
pmcraid_info("reset_reload: proceeding with reset\n");
|
||||
scsi_block_requests(pinstance->host);
|
||||
reset_cmd = pmcraid_get_free_cmd(pinstance);
|
||||
|
||||
if (reset_cmd == NULL) {
|
||||
pmcraid_err("no free cmnd for reset_reload\n");
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock,
|
||||
lock_flags);
|
||||
return reset;
|
||||
}
|
||||
|
||||
if (shutdown_type == SHUTDOWN_NORMAL)
|
||||
pinstance->ioa_bringdown = 1;
|
||||
|
||||
pinstance->ioa_shutdown_type = shutdown_type;
|
||||
pinstance->reset_cmd = reset_cmd;
|
||||
pinstance->force_ioa_reset = reset;
|
||||
pmcraid_info("reset_reload: initiating reset\n");
|
||||
pmcraid_ioa_reset(reset_cmd);
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags);
|
||||
pmcraid_info("reset_reload: waiting for reset to complete\n");
|
||||
wait_event(pinstance->reset_wait_q,
|
||||
!pinstance->ioa_reset_in_progress);
|
||||
|
||||
pmcraid_info("reset_reload: reset is complete !!\n");
|
||||
scsi_unblock_requests(pinstance->host);
|
||||
if (pinstance->ioa_state == target_state)
|
||||
reset = 0;
|
||||
pmcraid_info("reset_reload: proceeding with reset\n");
|
||||
scsi_block_requests(pinstance->host);
|
||||
reset_cmd = pmcraid_get_free_cmd(pinstance);
|
||||
if (reset_cmd == NULL) {
|
||||
pmcraid_err("no free cmnd for reset_reload\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (shutdown_type == SHUTDOWN_NORMAL)
|
||||
pinstance->ioa_bringdown = 1;
|
||||
|
||||
pinstance->ioa_shutdown_type = shutdown_type;
|
||||
pinstance->reset_cmd = reset_cmd;
|
||||
pinstance->force_ioa_reset = reset;
|
||||
pmcraid_info("reset_reload: initiating reset\n");
|
||||
pmcraid_ioa_reset(reset_cmd);
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags);
|
||||
pmcraid_info("reset_reload: waiting for reset to complete\n");
|
||||
wait_event(pinstance->reset_wait_q,
|
||||
!pinstance->ioa_reset_in_progress);
|
||||
|
||||
pmcraid_info("reset_reload: reset is complete !!\n");
|
||||
scsi_unblock_requests(pinstance->host);
|
||||
return pinstance->ioa_state != target_state;
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(pinstance->host->host_lock, lock_flags);
|
||||
return reset;
|
||||
}
|
||||
|
||||
|
@ -2529,7 +2526,7 @@ static void pmcraid_cancel_all(struct pmcraid_cmd *cmd, u32 sense)
|
|||
ioarcb->ioadl_bus_addr = 0;
|
||||
ioarcb->ioadl_length = 0;
|
||||
ioarcb->data_transfer_length = 0;
|
||||
ioarcb->ioarcb_bus_addr &= (~0x1FULL);
|
||||
ioarcb->ioarcb_bus_addr &= cpu_to_le64((~0x1FULL));
|
||||
|
||||
/* writing to IOARRIN must be protected by host_lock, as mid-layer
|
||||
* schedule queuecommand while we are doing this
|
||||
|
@ -2692,8 +2689,8 @@ static int pmcraid_error_handler(struct pmcraid_cmd *cmd)
|
|||
* mid-layer
|
||||
*/
|
||||
if (ioasa->auto_sense_length != 0) {
|
||||
short sense_len = ioasa->auto_sense_length;
|
||||
int data_size = min_t(u16, le16_to_cpu(sense_len),
|
||||
short sense_len = le16_to_cpu(ioasa->auto_sense_length);
|
||||
int data_size = min_t(u16, sense_len,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
|
||||
memcpy(scsi_cmd->sense_buffer,
|
||||
|
@ -2915,7 +2912,7 @@ static struct pmcraid_cmd *pmcraid_abort_cmd(struct pmcraid_cmd *cmd)
|
|||
|
||||
pmcraid_info("aborting command CDB[0]= %x with index = %d\n",
|
||||
cmd->ioa_cb->ioarcb.cdb[0],
|
||||
cmd->ioa_cb->ioarcb.response_handle >> 2);
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle) >> 2);
|
||||
|
||||
init_completion(&cancel_cmd->wait_for_completion);
|
||||
cancel_cmd->completion_req = 1;
|
||||
|
@ -3140,9 +3137,8 @@ pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount)
|
|||
int ioadl_count = 0;
|
||||
|
||||
if (ioarcb->add_cmd_param_length)
|
||||
ioadl_count = DIV_ROUND_UP(ioarcb->add_cmd_param_length, 16);
|
||||
ioarcb->ioadl_length =
|
||||
sizeof(struct pmcraid_ioadl_desc) * sgcount;
|
||||
ioadl_count = DIV_ROUND_UP(le16_to_cpu(ioarcb->add_cmd_param_length), 16);
|
||||
ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc) * sgcount);
|
||||
|
||||
if ((sgcount + ioadl_count) > (ARRAY_SIZE(ioarcb->add_data.u.ioadl))) {
|
||||
/* external ioadls start at offset 0x80 from control_block
|
||||
|
@ -3150,7 +3146,7 @@ pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount)
|
|||
* It is necessary to indicate to firmware that driver is
|
||||
* using ioadls to be treated as external to IOARCB.
|
||||
*/
|
||||
ioarcb->ioarcb_bus_addr &= ~(0x1FULL);
|
||||
ioarcb->ioarcb_bus_addr &= cpu_to_le64(~(0x1FULL));
|
||||
ioarcb->ioadl_bus_addr =
|
||||
cpu_to_le64((cmd->ioa_cb_bus_addr) +
|
||||
offsetof(struct pmcraid_ioarcb,
|
||||
|
@ -3164,7 +3160,7 @@ pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount)
|
|||
|
||||
ioadl = &ioarcb->add_data.u.ioadl[ioadl_count];
|
||||
ioarcb->ioarcb_bus_addr |=
|
||||
DIV_ROUND_CLOSEST(sgcount + ioadl_count, 8);
|
||||
cpu_to_le64(DIV_ROUND_CLOSEST(sgcount + ioadl_count, 8));
|
||||
}
|
||||
|
||||
return ioadl;
|
||||
|
@ -3325,7 +3321,7 @@ static struct pmcraid_sglist *pmcraid_alloc_sglist(int buflen)
|
|||
*/
|
||||
static int pmcraid_copy_sglist(
|
||||
struct pmcraid_sglist *sglist,
|
||||
unsigned long buffer,
|
||||
void __user *buffer,
|
||||
u32 len,
|
||||
int direction
|
||||
)
|
||||
|
@ -3346,11 +3342,9 @@ static int pmcraid_copy_sglist(
|
|||
|
||||
kaddr = kmap(page);
|
||||
if (direction == DMA_TO_DEVICE)
|
||||
rc = __copy_from_user(kaddr,
|
||||
(void *)buffer,
|
||||
bsize_elem);
|
||||
rc = copy_from_user(kaddr, buffer, bsize_elem);
|
||||
else
|
||||
rc = __copy_to_user((void *)buffer, kaddr, bsize_elem);
|
||||
rc = copy_to_user(buffer, kaddr, bsize_elem);
|
||||
|
||||
kunmap(page);
|
||||
|
||||
|
@ -3368,13 +3362,9 @@ static int pmcraid_copy_sglist(
|
|||
kaddr = kmap(page);
|
||||
|
||||
if (direction == DMA_TO_DEVICE)
|
||||
rc = __copy_from_user(kaddr,
|
||||
(void *)buffer,
|
||||
len % bsize_elem);
|
||||
rc = copy_from_user(kaddr, buffer, len % bsize_elem);
|
||||
else
|
||||
rc = __copy_to_user((void *)buffer,
|
||||
kaddr,
|
||||
len % bsize_elem);
|
||||
rc = copy_to_user(buffer, kaddr, len % bsize_elem);
|
||||
|
||||
kunmap(page);
|
||||
|
||||
|
@ -3496,7 +3486,7 @@ static int pmcraid_queuecommand_lck(
|
|||
RES_IS_VSET(res->cfg_entry) ?
|
||||
(fw_version <= PMCRAID_FW_VERSION_1 ?
|
||||
res->cfg_entry.unique_flags1 :
|
||||
res->cfg_entry.array_id & 0xFF) :
|
||||
le16_to_cpu(res->cfg_entry.array_id) & 0xFF) :
|
||||
RES_TARGET(res->cfg_entry.resource_address),
|
||||
RES_LUN(res->cfg_entry.resource_address));
|
||||
|
||||
|
@ -3652,17 +3642,17 @@ static long pmcraid_ioctl_passthrough(
|
|||
struct pmcraid_instance *pinstance,
|
||||
unsigned int ioctl_cmd,
|
||||
unsigned int buflen,
|
||||
unsigned long arg
|
||||
void __user *arg
|
||||
)
|
||||
{
|
||||
struct pmcraid_passthrough_ioctl_buffer *buffer;
|
||||
struct pmcraid_ioarcb *ioarcb;
|
||||
struct pmcraid_cmd *cmd;
|
||||
struct pmcraid_cmd *cancel_cmd;
|
||||
unsigned long request_buffer;
|
||||
void __user *request_buffer;
|
||||
unsigned long request_offset;
|
||||
unsigned long lock_flags;
|
||||
void *ioasa;
|
||||
void __user *ioasa;
|
||||
u32 ioasc;
|
||||
int request_size;
|
||||
int buffer_size;
|
||||
|
@ -3701,13 +3691,10 @@ static long pmcraid_ioctl_passthrough(
|
|||
|
||||
request_buffer = arg + request_offset;
|
||||
|
||||
rc = __copy_from_user(buffer,
|
||||
(struct pmcraid_passthrough_ioctl_buffer *) arg,
|
||||
rc = copy_from_user(buffer, arg,
|
||||
sizeof(struct pmcraid_passthrough_ioctl_buffer));
|
||||
|
||||
ioasa =
|
||||
(void *)(arg +
|
||||
offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa));
|
||||
ioasa = arg + offsetof(struct pmcraid_passthrough_ioctl_buffer, ioasa);
|
||||
|
||||
if (rc) {
|
||||
pmcraid_err("ioctl: can't copy passthrough buffer\n");
|
||||
|
@ -3715,7 +3702,7 @@ static long pmcraid_ioctl_passthrough(
|
|||
goto out_free_buffer;
|
||||
}
|
||||
|
||||
request_size = buffer->ioarcb.data_transfer_length;
|
||||
request_size = le32_to_cpu(buffer->ioarcb.data_transfer_length);
|
||||
|
||||
if (buffer->ioarcb.request_flags0 & TRANSFER_DIR_WRITE) {
|
||||
access = VERIFY_READ;
|
||||
|
@ -3725,20 +3712,14 @@ static long pmcraid_ioctl_passthrough(
|
|||
direction = DMA_FROM_DEVICE;
|
||||
}
|
||||
|
||||
if (request_size > 0) {
|
||||
rc = access_ok(access, arg, request_offset + request_size);
|
||||
|
||||
if (!rc) {
|
||||
rc = -EFAULT;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
} else if (request_size < 0) {
|
||||
if (request_size < 0) {
|
||||
rc = -EINVAL;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
|
||||
/* check if we have any additional command parameters */
|
||||
if (buffer->ioarcb.add_cmd_param_length > PMCRAID_ADD_CMD_PARAM_LEN) {
|
||||
if (le16_to_cpu(buffer->ioarcb.add_cmd_param_length)
|
||||
> PMCRAID_ADD_CMD_PARAM_LEN) {
|
||||
rc = -EINVAL;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
|
@ -3770,7 +3751,7 @@ static long pmcraid_ioctl_passthrough(
|
|||
buffer->ioarcb.add_cmd_param_offset;
|
||||
memcpy(ioarcb->add_data.u.add_cmd_params,
|
||||
buffer->ioarcb.add_data.u.add_cmd_params,
|
||||
buffer->ioarcb.add_cmd_param_length);
|
||||
le16_to_cpu(buffer->ioarcb.add_cmd_param_length));
|
||||
}
|
||||
|
||||
/* set hrrq number where the IOA should respond to. Note that all cmds
|
||||
|
@ -3840,10 +3821,10 @@ static long pmcraid_ioctl_passthrough(
|
|||
wait_for_completion(&cmd->wait_for_completion);
|
||||
} else if (!wait_for_completion_timeout(
|
||||
&cmd->wait_for_completion,
|
||||
msecs_to_jiffies(buffer->ioarcb.cmd_timeout * 1000))) {
|
||||
msecs_to_jiffies(le16_to_cpu(buffer->ioarcb.cmd_timeout) * 1000))) {
|
||||
|
||||
pmcraid_info("aborting cmd %d (CDB[0] = %x) due to timeout\n",
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle >> 2),
|
||||
le32_to_cpu(cmd->ioa_cb->ioarcb.response_handle) >> 2,
|
||||
cmd->ioa_cb->ioarcb.cdb[0]);
|
||||
|
||||
spin_lock_irqsave(pinstance->host->host_lock, lock_flags);
|
||||
|
@ -3852,7 +3833,7 @@ static long pmcraid_ioctl_passthrough(
|
|||
|
||||
if (cancel_cmd) {
|
||||
wait_for_completion(&cancel_cmd->wait_for_completion);
|
||||
ioasc = cancel_cmd->ioa_cb->ioasa.ioasc;
|
||||
ioasc = le32_to_cpu(cancel_cmd->ioa_cb->ioasa.ioasc);
|
||||
pmcraid_return_cmd(cancel_cmd);
|
||||
|
||||
/* if abort task couldn't find the command i.e it got
|
||||
|
@ -3941,11 +3922,6 @@ static long pmcraid_ioctl_driver(
|
|||
{
|
||||
int rc = -ENOSYS;
|
||||
|
||||
if (!access_ok(VERIFY_READ, user_buffer, _IOC_SIZE(cmd))) {
|
||||
pmcraid_err("ioctl_driver: access fault in request buffer\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case PMCRAID_IOCTL_RESET_ADAPTER:
|
||||
pmcraid_reset_bringup(pinstance);
|
||||
|
@ -3977,8 +3953,7 @@ static int pmcraid_check_ioctl_buffer(
|
|||
struct pmcraid_ioctl_header *hdr
|
||||
)
|
||||
{
|
||||
int rc = 0;
|
||||
int access = VERIFY_READ;
|
||||
int rc;
|
||||
|
||||
if (copy_from_user(hdr, arg, sizeof(struct pmcraid_ioctl_header))) {
|
||||
pmcraid_err("couldn't copy ioctl header from user buffer\n");
|
||||
|
@ -3994,19 +3969,6 @@ static int pmcraid_check_ioctl_buffer(
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check for appropriate buffer access */
|
||||
if ((_IOC_DIR(cmd) & _IOC_READ) == _IOC_READ)
|
||||
access = VERIFY_WRITE;
|
||||
|
||||
rc = access_ok(access,
|
||||
(arg + sizeof(struct pmcraid_ioctl_header)),
|
||||
hdr->buffer_length);
|
||||
if (!rc) {
|
||||
pmcraid_err("access failed for user buffer of size %d\n",
|
||||
hdr->buffer_length);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4021,6 +3983,7 @@ static long pmcraid_chr_ioctl(
|
|||
{
|
||||
struct pmcraid_instance *pinstance = NULL;
|
||||
struct pmcraid_ioctl_header *hdr = NULL;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int retval = -ENOTTY;
|
||||
|
||||
hdr = kmalloc(sizeof(struct pmcraid_ioctl_header), GFP_KERNEL);
|
||||
|
@ -4030,7 +3993,7 @@ static long pmcraid_chr_ioctl(
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
retval = pmcraid_check_ioctl_buffer(cmd, (void *)arg, hdr);
|
||||
retval = pmcraid_check_ioctl_buffer(cmd, argp, hdr);
|
||||
|
||||
if (retval) {
|
||||
pmcraid_info("chr_ioctl: header check failed\n");
|
||||
|
@ -4055,10 +4018,8 @@ static long pmcraid_chr_ioctl(
|
|||
if (cmd == PMCRAID_IOCTL_DOWNLOAD_MICROCODE)
|
||||
scsi_block_requests(pinstance->host);
|
||||
|
||||
retval = pmcraid_ioctl_passthrough(pinstance,
|
||||
cmd,
|
||||
hdr->buffer_length,
|
||||
arg);
|
||||
retval = pmcraid_ioctl_passthrough(pinstance, cmd,
|
||||
hdr->buffer_length, argp);
|
||||
|
||||
if (cmd == PMCRAID_IOCTL_DOWNLOAD_MICROCODE)
|
||||
scsi_unblock_requests(pinstance->host);
|
||||
|
@ -4066,10 +4027,8 @@ static long pmcraid_chr_ioctl(
|
|||
|
||||
case PMCRAID_DRIVER_IOCTL:
|
||||
arg += sizeof(struct pmcraid_ioctl_header);
|
||||
retval = pmcraid_ioctl_driver(pinstance,
|
||||
cmd,
|
||||
hdr->buffer_length,
|
||||
(void __user *)arg);
|
||||
retval = pmcraid_ioctl_driver(pinstance, cmd,
|
||||
hdr->buffer_length, argp);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -4470,7 +4429,7 @@ static void pmcraid_worker_function(struct work_struct *workp)
|
|||
if (fw_version <= PMCRAID_FW_VERSION_1)
|
||||
target = res->cfg_entry.unique_flags1;
|
||||
else
|
||||
target = res->cfg_entry.array_id & 0xFF;
|
||||
target = le16_to_cpu(res->cfg_entry.array_id) & 0xFF;
|
||||
lun = PMCRAID_VSET_LUN_ID;
|
||||
} else {
|
||||
bus = PMCRAID_PHYS_BUS_ID;
|
||||
|
@ -4509,7 +4468,7 @@ static void pmcraid_tasklet_function(unsigned long instance)
|
|||
unsigned long host_lock_flags;
|
||||
spinlock_t *lockp; /* hrrq buffer lock */
|
||||
int id;
|
||||
__le32 resp;
|
||||
u32 resp;
|
||||
|
||||
hrrq_vector = (struct pmcraid_isr_param *)instance;
|
||||
pinstance = hrrq_vector->drv_inst;
|
||||
|
@ -4833,7 +4792,7 @@ static int pmcraid_allocate_host_rrqs(struct pmcraid_instance *pinstance)
|
|||
buffer_size,
|
||||
&(pinstance->hrrq_start_bus_addr[i]));
|
||||
|
||||
if (pinstance->hrrq_start[i] == 0) {
|
||||
if (!pinstance->hrrq_start[i]) {
|
||||
pmcraid_err("pci_alloc failed for hrrq vector : %d\n",
|
||||
i);
|
||||
pmcraid_release_host_rrqs(pinstance, i);
|
||||
|
@ -5549,8 +5508,7 @@ static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd)
|
|||
struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb;
|
||||
__be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN);
|
||||
struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl;
|
||||
|
||||
__le64 timestamp;
|
||||
u64 timestamp;
|
||||
|
||||
timestamp = ktime_get_real_seconds() * 1000;
|
||||
|
||||
|
@ -5572,7 +5530,7 @@ static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd)
|
|||
offsetof(struct pmcraid_ioarcb,
|
||||
add_data.u.ioadl[0]));
|
||||
ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc));
|
||||
ioarcb->ioarcb_bus_addr &= ~(0x1FULL);
|
||||
ioarcb->ioarcb_bus_addr &= cpu_to_le64(~(0x1FULL));
|
||||
|
||||
ioarcb->request_flags0 |= NO_LINK_DESCS;
|
||||
ioarcb->request_flags0 |= TRANSFER_DIR_WRITE;
|
||||
|
@ -5631,7 +5589,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd)
|
|||
list_for_each_entry_safe(res, temp, &pinstance->used_res_q, queue)
|
||||
list_move_tail(&res->queue, &old_res);
|
||||
|
||||
for (i = 0; i < pinstance->cfg_table->num_entries; i++) {
|
||||
for (i = 0; i < le16_to_cpu(pinstance->cfg_table->num_entries); i++) {
|
||||
if (be16_to_cpu(pinstance->inq_data->fw_version) <=
|
||||
PMCRAID_FW_VERSION_1)
|
||||
cfgte = &pinstance->cfg_table->entries[i];
|
||||
|
@ -5686,7 +5644,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd)
|
|||
res->cfg_entry.resource_type,
|
||||
(fw_version <= PMCRAID_FW_VERSION_1 ?
|
||||
res->cfg_entry.unique_flags1 :
|
||||
res->cfg_entry.array_id & 0xFF),
|
||||
le16_to_cpu(res->cfg_entry.array_id) & 0xFF),
|
||||
le32_to_cpu(res->cfg_entry.resource_address));
|
||||
}
|
||||
}
|
||||
|
@ -5724,7 +5682,7 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd)
|
|||
struct pmcraid_ioarcb *ioarcb = &cmd->ioa_cb->ioarcb;
|
||||
struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl;
|
||||
struct pmcraid_instance *pinstance = cmd->drv_inst;
|
||||
int cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table));
|
||||
__be32 cfg_table_size = cpu_to_be32(sizeof(struct pmcraid_config_table));
|
||||
|
||||
if (be16_to_cpu(pinstance->inq_data->fw_version) <=
|
||||
PMCRAID_FW_VERSION_1)
|
||||
|
@ -5749,7 +5707,7 @@ static void pmcraid_querycfg(struct pmcraid_cmd *cmd)
|
|||
offsetof(struct pmcraid_ioarcb,
|
||||
add_data.u.ioadl[0]));
|
||||
ioarcb->ioadl_length = cpu_to_le32(sizeof(struct pmcraid_ioadl_desc));
|
||||
ioarcb->ioarcb_bus_addr &= ~(0x1FULL);
|
||||
ioarcb->ioarcb_bus_addr &= cpu_to_le64(~0x1FULL);
|
||||
|
||||
ioarcb->request_flags0 |= NO_LINK_DESCS;
|
||||
ioarcb->data_transfer_length =
|
||||
|
|
|
@ -554,7 +554,7 @@ struct pmcraid_inquiry_data {
|
|||
__u8 add_page_len;
|
||||
__u8 length;
|
||||
__u8 reserved2;
|
||||
__le16 fw_version;
|
||||
__be16 fw_version;
|
||||
__u8 reserved3[16];
|
||||
};
|
||||
|
||||
|
@ -697,13 +697,13 @@ struct pmcraid_instance {
|
|||
dma_addr_t hrrq_start_bus_addr[PMCRAID_NUM_MSIX_VECTORS];
|
||||
|
||||
/* Pointer to 1st entry of HRRQ */
|
||||
__be32 *hrrq_start[PMCRAID_NUM_MSIX_VECTORS];
|
||||
__le32 *hrrq_start[PMCRAID_NUM_MSIX_VECTORS];
|
||||
|
||||
/* Pointer to last entry of HRRQ */
|
||||
__be32 *hrrq_end[PMCRAID_NUM_MSIX_VECTORS];
|
||||
__le32 *hrrq_end[PMCRAID_NUM_MSIX_VECTORS];
|
||||
|
||||
/* Pointer to current pointer of hrrq */
|
||||
__be32 *hrrq_curr[PMCRAID_NUM_MSIX_VECTORS];
|
||||
__le32 *hrrq_curr[PMCRAID_NUM_MSIX_VECTORS];
|
||||
|
||||
/* Lock for HRRQ access */
|
||||
spinlock_t hrrq_lock[PMCRAID_NUM_MSIX_VECTORS];
|
||||
|
|
|
@ -449,7 +449,7 @@ const struct file_operations qedf_dbg_fops[] = {
|
|||
qedf_dbg_fileops(qedf, clear_stats),
|
||||
qedf_dbg_fileops_seq(qedf, offload_stats),
|
||||
/* This must be last */
|
||||
{ NULL, NULL },
|
||||
{ },
|
||||
};
|
||||
|
||||
#else /* CONFIG_DEBUG_FS */
|
||||
|
|
|
@ -240,5 +240,5 @@ const struct file_operations qedi_dbg_fops[] = {
|
|||
qedi_dbg_fileops_seq(qedi, gbl_ctx),
|
||||
qedi_dbg_fileops(qedi, do_not_recover),
|
||||
qedi_dbg_fileops_seq(qedi, io_trace),
|
||||
{ NULL, NULL },
|
||||
{ },
|
||||
};
|
||||
|
|
|
@ -1370,7 +1370,7 @@ static void qedi_cleanup_task(struct iscsi_task *task)
|
|||
{
|
||||
if (!task->sc || task->state == ISCSI_TASK_PENDING) {
|
||||
QEDI_INFO(NULL, QEDI_LOG_IO, "Returning ref_cnt=%d\n",
|
||||
atomic_read(&task->refcount));
|
||||
refcount_read(&task->refcount));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -695,7 +695,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
|
|||
case 0x2025e:
|
||||
if (!IS_P3P_TYPE(ha) || vha != base_vha) {
|
||||
ql_log(ql_log_info, vha, 0x7071,
|
||||
"FCoE ctx reset no supported.\n");
|
||||
"FCoE ctx reset not supported.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
|
|
@ -1822,7 +1822,7 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
|
|||
/* Check if operating mode is P2P */
|
||||
if (ha->operating_mode != P2P) {
|
||||
ql_log(ql_log_warn, vha, 0x70a4,
|
||||
"Host is operating mode is not P2p\n");
|
||||
"Host operating mode is not P2p\n");
|
||||
rval = EXT_STATUS_INVALID_CFG;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
|
|||
if (ct_rsp->header.response !=
|
||||
cpu_to_be16(CT_ACCEPT_RESPONSE)) {
|
||||
ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
|
||||
"%s failed rejected request on port_id: %02x%02x%02x Compeltion status 0x%x, response 0x%x\n",
|
||||
"%s failed rejected request on port_id: %02x%02x%02x Completion status 0x%x, response 0x%x\n",
|
||||
routine, vha->d_id.b.domain,
|
||||
vha->d_id.b.area, vha->d_id.b.al_pa,
|
||||
comp_status, ct_rsp->header.response);
|
||||
|
|
|
@ -2289,7 +2289,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)
|
|||
goto chip_diag_failed;
|
||||
|
||||
/* Check product ID of chip */
|
||||
ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product Id of chip.\n");
|
||||
ql_dbg(ql_dbg_init, vha, 0x007d, "Checking product ID of chip.\n");
|
||||
|
||||
mb[1] = RD_MAILBOX_REG(ha, reg, 1);
|
||||
mb[2] = RD_MAILBOX_REG(ha, reg, 2);
|
||||
|
|
|
@ -2100,14 +2100,14 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
|
|||
|
||||
case CS_DATA_OVERRUN:
|
||||
ql_dbg(ql_dbg_user, vha, 0x70b1,
|
||||
"Command completed with date overrun thread_id=%d\n",
|
||||
"Command completed with data overrun thread_id=%d\n",
|
||||
thread_id);
|
||||
rval = EXT_STATUS_DATA_OVERRUN;
|
||||
break;
|
||||
|
||||
case CS_DATA_UNDERRUN:
|
||||
ql_dbg(ql_dbg_user, vha, 0x70b2,
|
||||
"Command completed with date underrun thread_id=%d\n",
|
||||
"Command completed with data underrun thread_id=%d\n",
|
||||
thread_id);
|
||||
rval = EXT_STATUS_DATA_UNDERRUN;
|
||||
break;
|
||||
|
@ -2134,7 +2134,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
|
|||
|
||||
case CS_BIDIR_RD_UNDERRUN:
|
||||
ql_dbg(ql_dbg_user, vha, 0x70b6,
|
||||
"Command completed with read data data underrun "
|
||||
"Command completed with read data underrun "
|
||||
"thread_id=%d\n", thread_id);
|
||||
rval = EXT_STATUS_DATA_UNDERRUN;
|
||||
break;
|
||||
|
|
|
@ -423,7 +423,6 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
|
|||
kfree(req->outstanding_cmds);
|
||||
|
||||
kfree(req);
|
||||
req = NULL;
|
||||
}
|
||||
|
||||
static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
|
||||
|
@ -439,7 +438,6 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||
rsp->ring, rsp->dma);
|
||||
}
|
||||
kfree(rsp);
|
||||
rsp = NULL;
|
||||
}
|
||||
|
||||
static void qla2x00_free_queues(struct qla_hw_data *ha)
|
||||
|
@ -653,7 +651,6 @@ qla2x00_sp_free_dma(void *ptr)
|
|||
ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
|
||||
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
|
||||
mempool_free(ctx1, ha->ctx_mempool);
|
||||
ctx1 = NULL;
|
||||
}
|
||||
|
||||
CMD_SP(cmd) = NULL;
|
||||
|
@ -3256,7 +3253,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
}
|
||||
pci_release_selected_regions(ha->pdev, ha->bars);
|
||||
kfree(ha);
|
||||
ha = NULL;
|
||||
|
||||
probe_out:
|
||||
pci_disable_device(pdev);
|
||||
|
@ -3504,7 +3500,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
|||
|
||||
pci_release_selected_regions(ha->pdev, ha->bars);
|
||||
kfree(ha);
|
||||
ha = NULL;
|
||||
|
||||
pci_disable_pcie_error_reporting(pdev);
|
||||
|
||||
|
@ -3568,7 +3563,6 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
|
|||
list_del(&fcport->list);
|
||||
qla2x00_clear_loop_id(fcport);
|
||||
kfree(fcport);
|
||||
fcport = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -389,7 +389,7 @@ void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha)
|
|||
goto alloc_cleanup;
|
||||
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"Minidump Tempalate Size = 0x%x KB\n",
|
||||
"Minidump Template Size = 0x%x KB\n",
|
||||
ha->fw_dump_tmplt_size));
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"Total Minidump size = 0x%x KB\n", ha->fw_dump_size));
|
||||
|
|
|
@ -8664,7 +8664,6 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
init_completion(&ha->disable_acb_comp);
|
||||
init_completion(&ha->idc_comp);
|
||||
init_completion(&ha->link_up_comp);
|
||||
init_completion(&ha->disable_acb_comp);
|
||||
|
||||
spin_lock_init(&ha->hardware_lock);
|
||||
spin_lock_init(&ha->work_lock);
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
#include <trace/events/scsi.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
static void scsi_eh_done(struct scsi_cmnd *scmd);
|
||||
|
||||
/*
|
||||
|
@ -162,13 +164,7 @@ scmd_eh_abort_handler(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
if (!scsi_eh_scmd_add(scmd, 0)) {
|
||||
SCSI_LOG_ERROR_RECOVERY(3,
|
||||
scmd_printk(KERN_WARNING, scmd,
|
||||
"terminate aborted command\n"));
|
||||
set_host_byte(scmd, DID_TIME_OUT);
|
||||
scsi_finish_command(scmd);
|
||||
}
|
||||
scsi_eh_scmd_add(scmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,7 +184,6 @@ scsi_abort_command(struct scsi_cmnd *scmd)
|
|||
/*
|
||||
* Retry after abort failed, escalate to next level.
|
||||
*/
|
||||
scmd->eh_eflags &= ~SCSI_EH_ABORT_SCHEDULED;
|
||||
SCSI_LOG_ERROR_RECOVERY(3,
|
||||
scmd_printk(KERN_INFO, scmd,
|
||||
"previous abort failed\n"));
|
||||
|
@ -196,19 +191,7 @@ scsi_abort_command(struct scsi_cmnd *scmd)
|
|||
return FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not try a command abort if
|
||||
* SCSI EH has already started.
|
||||
*/
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (scsi_host_in_recovery(shost)) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
SCSI_LOG_ERROR_RECOVERY(3,
|
||||
scmd_printk(KERN_INFO, scmd,
|
||||
"not aborting, host in recovery\n"));
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (shost->eh_deadline != -1 && !shost->last_reset)
|
||||
shost->last_reset = jiffies;
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
@ -220,41 +203,48 @@ scsi_abort_command(struct scsi_cmnd *scmd)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_eh_reset - call into ->eh_action to reset internal counters
|
||||
* @scmd: scmd to run eh on.
|
||||
*
|
||||
* The scsi driver might be carrying internal state about the
|
||||
* devices, so we need to call into the driver to reset the
|
||||
* internal state once the error handler is started.
|
||||
*/
|
||||
static void scsi_eh_reset(struct scsi_cmnd *scmd)
|
||||
{
|
||||
if (!blk_rq_is_passthrough(scmd->request)) {
|
||||
struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
|
||||
if (sdrv->eh_reset)
|
||||
sdrv->eh_reset(scmd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_eh_scmd_add - add scsi cmd to error handling.
|
||||
* @scmd: scmd to run eh on.
|
||||
* @eh_flag: optional SCSI_EH flag.
|
||||
*
|
||||
* Return value:
|
||||
* 0 on failure.
|
||||
*/
|
||||
int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
|
||||
void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct Scsi_Host *shost = scmd->device->host;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (!shost->ehandler)
|
||||
return 0;
|
||||
WARN_ON_ONCE(!shost->ehandler);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (scsi_host_set_state(shost, SHOST_RECOVERY))
|
||||
if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
|
||||
goto out_unlock;
|
||||
|
||||
if (scsi_host_set_state(shost, SHOST_RECOVERY)) {
|
||||
ret = scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY);
|
||||
WARN_ON_ONCE(ret);
|
||||
}
|
||||
if (shost->eh_deadline != -1 && !shost->last_reset)
|
||||
shost->last_reset = jiffies;
|
||||
|
||||
ret = 1;
|
||||
if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED)
|
||||
eh_flag &= ~SCSI_EH_CANCEL_CMD;
|
||||
scmd->eh_eflags |= eh_flag;
|
||||
scsi_eh_reset(scmd);
|
||||
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
|
||||
shost->host_failed++;
|
||||
scsi_eh_wakeup(shost);
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -283,13 +273,10 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
|
|||
rtn = host->hostt->eh_timed_out(scmd);
|
||||
|
||||
if (rtn == BLK_EH_NOT_HANDLED) {
|
||||
if (!host->hostt->no_async_abort &&
|
||||
scsi_abort_command(scmd) == SUCCESS)
|
||||
return BLK_EH_NOT_HANDLED;
|
||||
|
||||
set_host_byte(scmd, DID_TIME_OUT);
|
||||
if (!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))
|
||||
rtn = BLK_EH_HANDLED;
|
||||
if (scsi_abort_command(scmd) != SUCCESS) {
|
||||
set_host_byte(scmd, DID_TIME_OUT);
|
||||
scsi_eh_scmd_add(scmd);
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
|
@ -341,7 +328,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
|
|||
list_for_each_entry(scmd, work_q, eh_entry) {
|
||||
if (scmd->device == sdev) {
|
||||
++total_failures;
|
||||
if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD)
|
||||
if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED)
|
||||
++cmd_cancel;
|
||||
else
|
||||
++cmd_failed;
|
||||
|
@ -931,6 +918,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
|
|||
ses->result = scmd->result;
|
||||
ses->underflow = scmd->underflow;
|
||||
ses->prot_op = scmd->prot_op;
|
||||
ses->eh_eflags = scmd->eh_eflags;
|
||||
|
||||
scmd->prot_op = SCSI_PROT_NORMAL;
|
||||
scmd->eh_eflags = 0;
|
||||
|
@ -994,6 +982,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
|
|||
scmd->result = ses->result;
|
||||
scmd->underflow = ses->underflow;
|
||||
scmd->prot_op = ses->prot_op;
|
||||
scmd->eh_eflags = ses->eh_eflags;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_eh_restore_cmnd);
|
||||
|
||||
|
@ -1126,7 +1115,6 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
|
|||
*/
|
||||
void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
|
||||
{
|
||||
scmd->eh_eflags = 0;
|
||||
list_move_tail(&scmd->eh_entry, done_q);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_eh_finish_cmd);
|
||||
|
@ -1163,8 +1151,7 @@ int scsi_eh_get_sense(struct list_head *work_q,
|
|||
* should not get sense.
|
||||
*/
|
||||
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
|
||||
if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) ||
|
||||
(scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ||
|
||||
if ((scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ||
|
||||
SCSI_SENSE_VALID(scmd))
|
||||
continue;
|
||||
|
||||
|
@ -1304,61 +1291,6 @@ static int scsi_eh_test_devices(struct list_head *cmd_list,
|
|||
return list_empty(work_q);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scsi_eh_abort_cmds - abort pending commands.
|
||||
* @work_q: &list_head for pending commands.
|
||||
* @done_q: &list_head for processed commands.
|
||||
*
|
||||
* Decription:
|
||||
* Try and see whether or not it makes sense to try and abort the
|
||||
* running command. This only works out to be the case if we have one
|
||||
* command that has timed out. If the command simply failed, it makes
|
||||
* no sense to try and abort the command, since as far as the shost
|
||||
* adapter is concerned, it isn't running.
|
||||
*/
|
||||
static int scsi_eh_abort_cmds(struct list_head *work_q,
|
||||
struct list_head *done_q)
|
||||
{
|
||||
struct scsi_cmnd *scmd, *next;
|
||||
LIST_HEAD(check_list);
|
||||
int rtn;
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
|
||||
if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD))
|
||||
continue;
|
||||
shost = scmd->device->host;
|
||||
if (scsi_host_eh_past_deadline(shost)) {
|
||||
list_splice_init(&check_list, work_q);
|
||||
SCSI_LOG_ERROR_RECOVERY(3,
|
||||
scmd_printk(KERN_INFO, scmd,
|
||||
"%s: skip aborting cmd, past eh deadline\n",
|
||||
current->comm));
|
||||
return list_empty(work_q);
|
||||
}
|
||||
SCSI_LOG_ERROR_RECOVERY(3,
|
||||
scmd_printk(KERN_INFO, scmd,
|
||||
"%s: aborting cmd\n", current->comm));
|
||||
rtn = scsi_try_to_abort_cmd(shost->hostt, scmd);
|
||||
if (rtn == FAILED) {
|
||||
SCSI_LOG_ERROR_RECOVERY(3,
|
||||
scmd_printk(KERN_INFO, scmd,
|
||||
"%s: aborting cmd failed\n",
|
||||
current->comm));
|
||||
list_splice_init(&check_list, work_q);
|
||||
return list_empty(work_q);
|
||||
}
|
||||
scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
|
||||
if (rtn == FAST_IO_FAIL)
|
||||
scsi_eh_finish_cmd(scmd, done_q);
|
||||
else
|
||||
list_move_tail(&scmd->eh_entry, &check_list);
|
||||
}
|
||||
|
||||
return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_eh_try_stu - Send START_UNIT to device.
|
||||
* @scmd: &scsi_cmnd to send START_UNIT
|
||||
|
@ -1701,11 +1633,6 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
|
|||
sdev_printk(KERN_INFO, scmd->device, "Device offlined - "
|
||||
"not ready after error recovery\n");
|
||||
scsi_device_set_state(scmd->device, SDEV_OFFLINE);
|
||||
if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) {
|
||||
/*
|
||||
* FIXME: Handle lost cmds.
|
||||
*/
|
||||
}
|
||||
scsi_eh_finish_cmd(scmd, done_q);
|
||||
}
|
||||
return;
|
||||
|
@ -2149,8 +2076,7 @@ static void scsi_unjam_host(struct Scsi_Host *shost)
|
|||
SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(shost, &eh_work_q));
|
||||
|
||||
if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q))
|
||||
if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q))
|
||||
scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);
|
||||
scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (shost->eh_deadline != -1)
|
||||
|
@ -2437,44 +2363,34 @@ EXPORT_SYMBOL(scsi_command_normalize_sense);
|
|||
* field will be placed if found.
|
||||
*
|
||||
* Return value:
|
||||
* 1 if information field found, 0 if not found.
|
||||
* true if information field found, false if not found.
|
||||
*/
|
||||
int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
|
||||
u64 * info_out)
|
||||
bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len,
|
||||
u64 *info_out)
|
||||
{
|
||||
int j;
|
||||
const u8 * ucp;
|
||||
u64 ull;
|
||||
|
||||
if (sb_len < 7)
|
||||
return 0;
|
||||
return false;
|
||||
switch (sense_buffer[0] & 0x7f) {
|
||||
case 0x70:
|
||||
case 0x71:
|
||||
if (sense_buffer[0] & 0x80) {
|
||||
*info_out = (sense_buffer[3] << 24) +
|
||||
(sense_buffer[4] << 16) +
|
||||
(sense_buffer[5] << 8) + sense_buffer[6];
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
*info_out = get_unaligned_be32(&sense_buffer[3]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
ucp = scsi_sense_desc_find(sense_buffer, sb_len,
|
||||
0 /* info desc */);
|
||||
if (ucp && (0xa == ucp[1])) {
|
||||
ull = 0;
|
||||
for (j = 0; j < 8; ++j) {
|
||||
if (j > 0)
|
||||
ull <<= 8;
|
||||
ull |= ucp[4 + j];
|
||||
}
|
||||
*info_out = ull;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
*info_out = get_unaligned_be64(&ucp[4]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_get_sense_info_fld);
|
||||
|
|
|
@ -1593,8 +1593,8 @@ static void scsi_softirq_done(struct request *rq)
|
|||
scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
|
||||
break;
|
||||
default:
|
||||
if (!scsi_eh_scmd_add(cmd, 0))
|
||||
scsi_finish_command(cmd);
|
||||
scsi_eh_scmd_add(cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ struct scsi_nl_hdr;
|
|||
/*
|
||||
* Scsi Error Handler Flags
|
||||
*/
|
||||
#define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */
|
||||
#define SCSI_EH_ABORT_SCHEDULED 0x0002 /* Abort has been scheduled */
|
||||
|
||||
#define SCSI_SENSE_VALID(scmd) \
|
||||
|
@ -72,7 +71,7 @@ extern enum blk_eh_timer_return scsi_times_out(struct request *req);
|
|||
extern int scsi_error_handler(void *host);
|
||||
extern int scsi_decide_disposition(struct scsi_cmnd *cmd);
|
||||
extern void scsi_eh_wakeup(struct Scsi_Host *shost);
|
||||
extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
|
||||
extern void scsi_eh_scmd_add(struct scsi_cmnd *);
|
||||
void scsi_eh_ready_devs(struct Scsi_Host *shost,
|
||||
struct list_head *work_q,
|
||||
struct list_head *done_q);
|
||||
|
|
|
@ -289,9 +289,10 @@ static const struct {
|
|||
u32 value;
|
||||
char *name;
|
||||
} fc_port_role_names[] = {
|
||||
{ FC_PORT_ROLE_FCP_TARGET, "FCP Target" },
|
||||
{ FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
|
||||
{ FC_PORT_ROLE_IP_PORT, "IP Port" },
|
||||
{ FC_PORT_ROLE_FCP_TARGET, "FCP Target" },
|
||||
{ FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
|
||||
{ FC_PORT_ROLE_IP_PORT, "IP Port" },
|
||||
{ FC_PORT_ROLE_FCP_DUMMY_INITIATOR, "FCP Dummy Initiator" },
|
||||
};
|
||||
fc_bitfield_name_search(port_roles, fc_port_role_names)
|
||||
|
||||
|
@ -850,7 +851,7 @@ static int fc_str_to_dev_loss(const char *buf, unsigned long *val)
|
|||
char *cp;
|
||||
|
||||
*val = simple_strtoul(buf, &cp, 0);
|
||||
if ((*cp && (*cp != '\n')) || (*val < 0))
|
||||
if (*cp && (*cp != '\n'))
|
||||
return -EINVAL;
|
||||
/*
|
||||
* Check for overflow; dev_loss_tmo is u32
|
||||
|
@ -2628,7 +2629,8 @@ fc_remote_port_create(struct Scsi_Host *shost, int channel,
|
|||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
||||
rport->number = fc_host->next_rport_number++;
|
||||
if (rport->roles & FC_PORT_ROLE_FCP_TARGET)
|
||||
if ((rport->roles & FC_PORT_ROLE_FCP_TARGET) ||
|
||||
(rport->roles & FC_PORT_ROLE_FCP_DUMMY_INITIATOR))
|
||||
rport->scsi_target_id = fc_host->next_target_id++;
|
||||
else
|
||||
rport->scsi_target_id = -1;
|
||||
|
|
|
@ -2158,7 +2158,6 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
|
|||
|
||||
void iscsi_remove_session(struct iscsi_cls_session *session)
|
||||
{
|
||||
struct Scsi_Host *shost = iscsi_session_to_shost(session);
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
|
@ -2185,7 +2184,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
|
|||
|
||||
scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
|
||||
/* flush running scans then delete devices */
|
||||
scsi_flush_work(shost);
|
||||
flush_work(&session->scan_work);
|
||||
__iscsi_unbind_session(&session->unbind_work);
|
||||
|
||||
/* hw iscsi may not have removed all connections from session */
|
||||
|
|
|
@ -370,12 +370,16 @@ EXPORT_SYMBOL(sas_remove_children);
|
|||
* sas_remove_host - tear down a Scsi_Host's SAS data structures
|
||||
* @shost: Scsi Host that is torn down
|
||||
*
|
||||
* Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
|
||||
* Must be called just before scsi_remove_host for SAS HBAs.
|
||||
* Removes all SAS PHYs and remote PHYs for a given Scsi_Host and remove the
|
||||
* Scsi_Host as well.
|
||||
*
|
||||
* Note: Do not call scsi_remove_host() on the Scsi_Host any more, as it is
|
||||
* already removed.
|
||||
*/
|
||||
void sas_remove_host(struct Scsi_Host *shost)
|
||||
{
|
||||
sas_remove_children(&shost->shost_gendev);
|
||||
scsi_remove_host(shost);
|
||||
}
|
||||
EXPORT_SYMBOL(sas_remove_host);
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ static void sd_rescan(struct device *);
|
|||
static int sd_init_command(struct scsi_cmnd *SCpnt);
|
||||
static void sd_uninit_command(struct scsi_cmnd *SCpnt);
|
||||
static int sd_done(struct scsi_cmnd *);
|
||||
static void sd_eh_reset(struct scsi_cmnd *);
|
||||
static int sd_eh_action(struct scsi_cmnd *, int);
|
||||
static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
|
||||
static void scsi_disk_release(struct device *cdev);
|
||||
|
@ -573,6 +574,7 @@ static struct scsi_driver sd_template = {
|
|||
.uninit_command = sd_uninit_command,
|
||||
.done = sd_done,
|
||||
.eh_action = sd_eh_action,
|
||||
.eh_reset = sd_eh_reset,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -888,8 +890,8 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
|
|||
* sd_setup_write_same_cmnd - write the same data to multiple blocks
|
||||
* @cmd: command to prepare
|
||||
*
|
||||
* Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
|
||||
* preference indicated by target device.
|
||||
* Will set up either WRITE SAME(10) or WRITE SAME(16) depending on
|
||||
* the preference indicated by the target device.
|
||||
**/
|
||||
static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
|
@ -908,7 +910,7 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
|
|||
BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
|
||||
|
||||
if (sd_is_zoned(sdkp)) {
|
||||
ret = sd_zbc_setup_write_cmnd(cmd);
|
||||
ret = sd_zbc_write_lock_zone(cmd);
|
||||
if (ret != BLKPREP_OK)
|
||||
return ret;
|
||||
}
|
||||
|
@ -980,7 +982,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
|
|||
unsigned char protect;
|
||||
|
||||
if (zoned_write) {
|
||||
ret = sd_zbc_setup_write_cmnd(SCpnt);
|
||||
ret = sd_zbc_write_lock_zone(SCpnt);
|
||||
if (ret != BLKPREP_OK)
|
||||
return ret;
|
||||
}
|
||||
|
@ -1207,7 +1209,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
|
|||
ret = BLKPREP_OK;
|
||||
out:
|
||||
if (zoned_write && ret != BLKPREP_OK)
|
||||
sd_zbc_cancel_write_cmnd(SCpnt);
|
||||
sd_zbc_write_unlock_zone(SCpnt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1264,8 +1266,8 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
|
|||
|
||||
/**
|
||||
* sd_open - open a scsi disk device
|
||||
* @inode: only i_rdev member may be used
|
||||
* @filp: only f_mode and f_flags may be used
|
||||
* @bdev: Block device of the scsi disk to open
|
||||
* @mode: FMODE_* mask
|
||||
*
|
||||
* Returns 0 if successful. Returns a negated errno value in case
|
||||
* of error.
|
||||
|
@ -1341,8 +1343,8 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
|
|||
/**
|
||||
* sd_release - invoked when the (last) close(2) is called on this
|
||||
* scsi disk.
|
||||
* @inode: only i_rdev member may be used
|
||||
* @filp: only f_mode and f_flags may be used
|
||||
* @disk: disk to release
|
||||
* @mode: FMODE_* mask
|
||||
*
|
||||
* Returns 0.
|
||||
*
|
||||
|
@ -1398,8 +1400,8 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|||
|
||||
/**
|
||||
* sd_ioctl - process an ioctl
|
||||
* @inode: only i_rdev/i_bdev members may be used
|
||||
* @filp: only f_mode and f_flags may be used
|
||||
* @bdev: target block device
|
||||
* @mode: FMODE_* mask
|
||||
* @cmd: ioctl command number
|
||||
* @arg: this is third argument given to ioctl(2) system call.
|
||||
* Often contains a pointer.
|
||||
|
@ -1761,6 +1763,26 @@ static const struct block_device_operations sd_fops = {
|
|||
.pr_ops = &sd_pr_ops,
|
||||
};
|
||||
|
||||
/**
|
||||
* sd_eh_reset - reset error handling callback
|
||||
* @scmd: sd-issued command that has failed
|
||||
*
|
||||
* This function is called by the SCSI midlayer before starting
|
||||
* SCSI EH. When counting medium access failures we have to be
|
||||
* careful to register it only only once per device and SCSI EH run;
|
||||
* there might be several timed out commands which will cause the
|
||||
* 'max_medium_access_timeouts' counter to trigger after the first
|
||||
* SCSI EH run already and set the device to offline.
|
||||
* So this function resets the internal counter before starting SCSI EH.
|
||||
**/
|
||||
static void sd_eh_reset(struct scsi_cmnd *scmd)
|
||||
{
|
||||
struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk);
|
||||
|
||||
/* New SCSI EH run, reset gate variable */
|
||||
sdkp->ignore_medium_access_errors = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* sd_eh_action - error handling callback
|
||||
* @scmd: sd-issued command that has failed
|
||||
|
@ -1790,7 +1812,10 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
|
|||
* process of recovering or has it suffered an internal failure
|
||||
* that prevents access to the storage medium.
|
||||
*/
|
||||
sdkp->medium_access_timed_out++;
|
||||
if (!sdkp->ignore_medium_access_errors) {
|
||||
sdkp->medium_access_timed_out++;
|
||||
sdkp->ignore_medium_access_errors = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device keeps failing read/write commands but TEST UNIT
|
||||
|
@ -1802,7 +1827,7 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
|
|||
"Medium access timeout failure. Offlining disk!\n");
|
||||
scsi_device_set_state(scmd->device, SDEV_OFFLINE);
|
||||
|
||||
return FAILED;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return eh_disp;
|
||||
|
@ -1810,41 +1835,44 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
|
|||
|
||||
static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
|
||||
{
|
||||
u64 start_lba = blk_rq_pos(scmd->request);
|
||||
u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
|
||||
u64 factor = scmd->device->sector_size / 512;
|
||||
u64 bad_lba;
|
||||
int info_valid;
|
||||
struct request *req = scmd->request;
|
||||
struct scsi_device *sdev = scmd->device;
|
||||
unsigned int transferred, good_bytes;
|
||||
u64 start_lba, end_lba, bad_lba;
|
||||
|
||||
/*
|
||||
* Some commands have a payload smaller than the device logical
|
||||
* block size (e.g. INQUIRY on a 4K disk).
|
||||
*/
|
||||
if (scsi_bufflen(scmd) <= sdev->sector_size)
|
||||
return 0;
|
||||
|
||||
/* Check if we have a 'bad_lba' information */
|
||||
if (!scsi_get_sense_info_fld(scmd->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
&bad_lba))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the bad lba was reported incorrectly, we have no idea where
|
||||
* the error is.
|
||||
*/
|
||||
start_lba = sectors_to_logical(sdev, blk_rq_pos(req));
|
||||
end_lba = start_lba + bytes_to_logical(sdev, scsi_bufflen(scmd));
|
||||
if (bad_lba < start_lba || bad_lba >= end_lba)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* resid is optional but mostly filled in. When it's unused,
|
||||
* its value is zero, so we assume the whole buffer transferred
|
||||
*/
|
||||
unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
|
||||
unsigned int good_bytes;
|
||||
transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
|
||||
|
||||
info_valid = scsi_get_sense_info_fld(scmd->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
&bad_lba);
|
||||
if (!info_valid)
|
||||
return 0;
|
||||
|
||||
if (scsi_bufflen(scmd) <= scmd->device->sector_size)
|
||||
return 0;
|
||||
|
||||
/* be careful ... don't want any overflows */
|
||||
do_div(start_lba, factor);
|
||||
do_div(end_lba, factor);
|
||||
|
||||
/* The bad lba was reported incorrectly, we have no idea where
|
||||
* the error is.
|
||||
/* This computation should always be done in terms of the
|
||||
* resolution of the device's medium.
|
||||
*/
|
||||
if (bad_lba < start_lba || bad_lba >= end_lba)
|
||||
return 0;
|
||||
good_bytes = logical_to_bytes(sdev, bad_lba - start_lba);
|
||||
|
||||
/* This computation should always be done in terms of
|
||||
* the resolution of the device's medium.
|
||||
*/
|
||||
good_bytes = (bad_lba - start_lba) * scmd->device->sector_size;
|
||||
return min(good_bytes, transferred);
|
||||
}
|
||||
|
||||
|
@ -1866,8 +1894,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
|
|||
struct request *req = SCpnt->request;
|
||||
int sense_valid = 0;
|
||||
int sense_deferred = 0;
|
||||
unsigned char op = SCpnt->cmnd[0];
|
||||
unsigned char unmap = SCpnt->cmnd[1] & 8;
|
||||
|
||||
switch (req_op(req)) {
|
||||
case REQ_OP_DISCARD:
|
||||
|
@ -1941,26 +1967,27 @@ static int sd_done(struct scsi_cmnd *SCpnt)
|
|||
good_bytes = sd_completed_bytes(SCpnt);
|
||||
break;
|
||||
case ILLEGAL_REQUEST:
|
||||
if (sshdr.asc == 0x10) /* DIX: Host detected corruption */
|
||||
switch (sshdr.asc) {
|
||||
case 0x10: /* DIX: Host detected corruption */
|
||||
good_bytes = sd_completed_bytes(SCpnt);
|
||||
/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
|
||||
if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
|
||||
switch (op) {
|
||||
break;
|
||||
case 0x20: /* INVALID COMMAND OPCODE */
|
||||
case 0x24: /* INVALID FIELD IN CDB */
|
||||
switch (SCpnt->cmnd[0]) {
|
||||
case UNMAP:
|
||||
sd_config_discard(sdkp, SD_LBP_DISABLE);
|
||||
break;
|
||||
case WRITE_SAME_16:
|
||||
case WRITE_SAME:
|
||||
if (unmap)
|
||||
if (SCpnt->cmnd[1] & 8) { /* UNMAP */
|
||||
sd_config_discard(sdkp, SD_LBP_DISABLE);
|
||||
else {
|
||||
} else {
|
||||
sdkp->device->no_write_same = 1;
|
||||
sd_config_write_same(sdkp);
|
||||
|
||||
good_bytes = 0;
|
||||
req->__data_len = blk_rq_bytes(req);
|
||||
req->rq_flags |= RQF_QUIET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2798,7 +2825,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
|
|||
|
||||
/**
|
||||
* sd_read_block_limits - Query disk device for preferred I/O sizes.
|
||||
* @disk: disk to query
|
||||
* @sdkp: disk to query
|
||||
*/
|
||||
static void sd_read_block_limits(struct scsi_disk *sdkp)
|
||||
{
|
||||
|
@ -2864,7 +2891,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
|
|||
|
||||
/**
|
||||
* sd_read_block_characteristics - Query block dev. characteristics
|
||||
* @disk: disk to query
|
||||
* @sdkp: disk to query
|
||||
*/
|
||||
static void sd_read_block_characteristics(struct scsi_disk *sdkp)
|
||||
{
|
||||
|
@ -2912,7 +2939,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
|
|||
|
||||
/**
|
||||
* sd_read_block_provisioning - Query provisioning VPD page
|
||||
* @disk: disk to query
|
||||
* @sdkp: disk to query
|
||||
*/
|
||||
static void sd_read_block_provisioning(struct scsi_disk *sdkp)
|
||||
{
|
||||
|
|
|
@ -114,6 +114,7 @@ struct scsi_disk {
|
|||
unsigned rc_basis: 2;
|
||||
unsigned zoned: 2;
|
||||
unsigned urswrz : 1;
|
||||
unsigned ignore_medium_access_errors : 1;
|
||||
};
|
||||
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
|
||||
|
||||
|
@ -176,6 +177,11 @@ static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t b
|
|||
return blocks * sdev->sector_size;
|
||||
}
|
||||
|
||||
static inline sector_t bytes_to_logical(struct scsi_device *sdev, unsigned int bytes)
|
||||
{
|
||||
return bytes >> ilog2(sdev->sector_size);
|
||||
}
|
||||
|
||||
static inline sector_t sectors_to_logical(struct scsi_device *sdev, sector_t sector)
|
||||
{
|
||||
return sector >> (ilog2(sdev->sector_size) - 9);
|
||||
|
@ -274,8 +280,8 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp)
|
|||
extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
|
||||
extern void sd_zbc_remove(struct scsi_disk *sdkp);
|
||||
extern void sd_zbc_print_zones(struct scsi_disk *sdkp);
|
||||
extern int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd);
|
||||
extern void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd);
|
||||
extern int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd);
|
||||
extern void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd);
|
||||
extern int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd);
|
||||
extern int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd);
|
||||
extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
|
||||
|
@ -293,13 +299,13 @@ static inline void sd_zbc_remove(struct scsi_disk *sdkp) {}
|
|||
|
||||
static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {}
|
||||
|
||||
static inline int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd)
|
||||
static inline int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd)
|
||||
{
|
||||
/* Let the drive fail requests */
|
||||
return BLKPREP_OK;
|
||||
}
|
||||
|
||||
static inline void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd) {}
|
||||
static inline void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd) {}
|
||||
|
||||
static inline int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
|
|
|
@ -237,7 +237,6 @@ int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd)
|
|||
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
|
||||
sector_t sector = blk_rq_pos(rq);
|
||||
sector_t block = sectors_to_logical(sdkp->device, sector);
|
||||
unsigned int zno = block >> sdkp->zone_shift;
|
||||
|
||||
if (!sd_is_zoned(sdkp))
|
||||
/* Not a zoned device */
|
||||
|
@ -250,11 +249,6 @@ int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd)
|
|||
/* Unaligned request */
|
||||
return BLKPREP_KILL;
|
||||
|
||||
/* Do not allow concurrent reset and writes */
|
||||
if (sdkp->zones_wlock &&
|
||||
test_and_set_bit(zno, sdkp->zones_wlock))
|
||||
return BLKPREP_DEFER;
|
||||
|
||||
cmd->cmd_len = 16;
|
||||
memset(cmd->cmnd, 0, cmd->cmd_len);
|
||||
cmd->cmnd[0] = ZBC_OUT;
|
||||
|
@ -269,7 +263,7 @@ int sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd)
|
|||
return BLKPREP_OK;
|
||||
}
|
||||
|
||||
int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd)
|
||||
int sd_zbc_write_lock_zone(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct request *rq = cmd->request;
|
||||
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
|
||||
|
@ -303,8 +297,9 @@ int sd_zbc_setup_write_cmnd(struct scsi_cmnd *cmd)
|
|||
return BLKPREP_OK;
|
||||
}
|
||||
|
||||
static void sd_zbc_unlock_zone(struct request *rq)
|
||||
void sd_zbc_write_unlock_zone(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct request *rq = cmd->request;
|
||||
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
|
||||
|
||||
if (sdkp->zones_wlock) {
|
||||
|
@ -315,11 +310,6 @@ static void sd_zbc_unlock_zone(struct request *rq)
|
|||
}
|
||||
}
|
||||
|
||||
void sd_zbc_cancel_write_cmnd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
sd_zbc_unlock_zone(cmd->request);
|
||||
}
|
||||
|
||||
void sd_zbc_complete(struct scsi_cmnd *cmd,
|
||||
unsigned int good_bytes,
|
||||
struct scsi_sense_hdr *sshdr)
|
||||
|
@ -328,39 +318,35 @@ void sd_zbc_complete(struct scsi_cmnd *cmd,
|
|||
struct request *rq = cmd->request;
|
||||
|
||||
switch (req_op(rq)) {
|
||||
case REQ_OP_ZONE_RESET:
|
||||
|
||||
if (result &&
|
||||
sshdr->sense_key == ILLEGAL_REQUEST &&
|
||||
sshdr->asc == 0x24)
|
||||
/*
|
||||
* INVALID FIELD IN CDB error: reset of a conventional
|
||||
* zone was attempted. Nothing to worry about, so be
|
||||
* quiet about the error.
|
||||
*/
|
||||
rq->rq_flags |= RQF_QUIET;
|
||||
break;
|
||||
|
||||
case REQ_OP_WRITE:
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
case REQ_OP_WRITE_SAME:
|
||||
case REQ_OP_ZONE_RESET:
|
||||
|
||||
/* Unlock the zone */
|
||||
sd_zbc_unlock_zone(rq);
|
||||
sd_zbc_write_unlock_zone(cmd);
|
||||
|
||||
if (!result ||
|
||||
sshdr->sense_key != ILLEGAL_REQUEST)
|
||||
break;
|
||||
|
||||
switch (sshdr->asc) {
|
||||
case 0x24:
|
||||
/*
|
||||
* INVALID FIELD IN CDB error: For a zone reset,
|
||||
* this means that a reset of a conventional
|
||||
* zone was attempted. Nothing to worry about in
|
||||
* this case, so be quiet about the error.
|
||||
*/
|
||||
if (req_op(rq) == REQ_OP_ZONE_RESET)
|
||||
rq->rq_flags |= RQF_QUIET;
|
||||
break;
|
||||
case 0x21:
|
||||
if (result &&
|
||||
sshdr->sense_key == ILLEGAL_REQUEST &&
|
||||
sshdr->asc == 0x21)
|
||||
/*
|
||||
* INVALID ADDRESS FOR WRITE error: It is unlikely that
|
||||
* retrying write requests failed with any kind of
|
||||
* alignement error will result in success. So don't.
|
||||
*/
|
||||
cmd->allowed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REQ_OP_ZONE_REPORT:
|
||||
|
@ -565,8 +551,7 @@ static int sd_zbc_setup(struct scsi_disk *sdkp)
|
|||
int sd_zbc_read_zones(struct scsi_disk *sdkp,
|
||||
unsigned char *buf)
|
||||
{
|
||||
sector_t capacity;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (!sd_is_zoned(sdkp))
|
||||
/*
|
||||
|
@ -598,7 +583,6 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp,
|
|||
ret = sd_zbc_check_capacity(sdkp, buf);
|
||||
if (ret)
|
||||
goto err;
|
||||
capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
|
||||
|
||||
/*
|
||||
* Check zone size: only devices with a constant zone size (except
|
||||
|
|
|
@ -548,7 +548,6 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
|
|||
ecomp = &edev->component[components++];
|
||||
|
||||
if (!IS_ERR(ecomp)) {
|
||||
ses_get_power_status(edev, ecomp);
|
||||
if (addl_desc_ptr)
|
||||
ses_process_descriptor(
|
||||
ecomp,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue