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:
Linus Torvalds 2017-05-04 12:19:44 -07:00
commit 8d5e72dfdf
119 changed files with 4320 additions and 2769 deletions

View File

@ -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

View File

@ -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.

View File

@ -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/

View File

@ -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:

View File

@ -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);
}

View File

@ -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;

View File

@ -1548,11 +1548,19 @@ out_mptspi_probe:
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,

View File

@ -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");
}

View File

@ -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);

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;
}
/*

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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) \

View File

@ -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);

View File

@ -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_) \

View File

@ -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);
}

View File

@ -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_

View File

@ -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 @@ drop_pdu:
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 @@ err:
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 @@ cleanup_port:
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 @@ free_port:
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);

View File

@ -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;
};
/**

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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)
{

View File

@ -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__ */

View File

@ -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)
{

View File

@ -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 */
};

View File

@ -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;
}

View File

@ -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"

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 @@ retry_recover:
}
/* 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;

View File

@ -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 */

View File

@ -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))

View File

@ -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 */

View File

@ -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);
/*

View File

@ -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");

View File

@ -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;

View File

@ -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:

View File

@ -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);
}

View File

@ -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:

View File

@ -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;

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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 @@ ex_err:
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);

View File

@ -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

View File

@ -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},

View File

@ -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;

View File

@ -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 = &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 = &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);

View File

@ -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

View File

@ -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);

View File

@ -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);
}
/**

View File

@ -887,8 +887,6 @@ out:
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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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__,

View File

@ -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,

View File

@ -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);

View File

@ -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]);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 =

View File

@ -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];

View File

@ -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 */

View File

@ -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 },
{ },
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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 @@ iospace_config_failed:
}
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;
}
}

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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 @@ out:
* 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 @@ error_out:
/**
* 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)
{

View File

@ -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)
{

View File

@ -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

View File

@ -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