Commit f38c43a0 authored by Sreekanth Reddy's avatar Sreekanth Reddy Committed by Martin K. Petersen

scsi: mpt3sas: Detect tampered Aero and Sea adapters

The driver will throw an error message when a tampered type controller
is detected. The intent is to avoid interacting with any firmware
which is not secured/signed by Broadcom. Any tampering on firmware
component will be detected by hardware and it will be communicated to
the driver to avoid any further interaction with that component.

[mkp: switched back to dev_err]

Link: https://lore.kernel.org/r/20200814130426.2741171-1-sreekanth.reddy@broadcom.comSigned-off-by: default avatarSreekanth Reddy <sreekanth.reddy@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 62aa501d
......@@ -10091,6 +10091,34 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
mutex_unlock(&ioc->scsih_cmds.mutex);
}
/**
* _scsih_get_shost_and_ioc - get shost and ioc
* and verify whether they are NULL or not
* @pdev: PCI device struct
* @shost: address of scsi host pointer
* @ioc: address of HBA adapter pointer
*
* Return zero if *shost and *ioc are not NULL otherwise return error number.
*/
static int
_scsih_get_shost_and_ioc(struct pci_dev *pdev,
struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
{
*shost = pci_get_drvdata(pdev);
if (*shost == NULL) {
dev_err(&pdev->dev, "pdev's driver data is null\n");
return -ENXIO;
}
*ioc = shost_priv(*shost);
if (*ioc == NULL) {
dev_err(&pdev->dev, "shost's private data is null\n");
return -ENXIO;
}
return 0;
}
/**
* scsih_remove - detach and remove add host
* @pdev: PCI device struct
......@@ -10099,8 +10127,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
*/
static void scsih_remove(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
......@@ -10109,6 +10137,9 @@ static void scsih_remove(struct pci_dev *pdev)
unsigned long flags;
Mpi2ConfigReply_t mpi_reply;
if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
return;
ioc->remove_host = 1;
if (!pci_device_is_present(pdev))
......@@ -10188,12 +10219,15 @@ static void scsih_remove(struct pci_dev *pdev)
static void
scsih_shutdown(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
struct workqueue_struct *wq;
unsigned long flags;
Mpi2ConfigReply_t mpi_reply;
if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
return;
ioc->remove_host = 1;
if (!pci_device_is_present(pdev))
......@@ -10763,6 +10797,10 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
case MPI26_MFGPAGE_DEVID_HARD_SEC_3916:
case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
case MPI26_MFGPAGE_DEVID_HARD_SEC_3816:
case MPI26_MFGPAGE_DEVID_INVALID0_3916:
case MPI26_MFGPAGE_DEVID_INVALID1_3916:
case MPI26_MFGPAGE_DEVID_INVALID0_3816:
case MPI26_MFGPAGE_DEVID_INVALID1_3816:
return MPI26_VERSION;
}
return 0;
......@@ -10852,6 +10890,20 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
case MPI26_ATLAS_PCIe_SWITCH_DEVID:
ioc->is_gen35_ioc = 1;
break;
case MPI26_MFGPAGE_DEVID_INVALID0_3816:
case MPI26_MFGPAGE_DEVID_INVALID0_3916:
dev_err(&pdev->dev,
"HBA with DeviceId 0x%04x, sub VendorId 0x%04x, sub DeviceId 0x%04x is Invalid",
pdev->device, pdev->subsystem_vendor,
pdev->subsystem_device);
return 1;
case MPI26_MFGPAGE_DEVID_INVALID1_3816:
case MPI26_MFGPAGE_DEVID_INVALID1_3916:
dev_err(&pdev->dev,
"HBA with DeviceId 0x%04x, sub VendorId 0x%04x, sub DeviceId 0x%04x is Tampered",
pdev->device, pdev->subsystem_vendor,
pdev->subsystem_device);
return 1;
case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
case MPI26_MFGPAGE_DEVID_CFG_SEC_3916:
dev_info(&pdev->dev,
......@@ -11043,9 +11095,14 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static int
scsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
pci_power_t device_state;
int rc;
rc = _scsih_get_shost_and_ioc(pdev, &shost, &ioc);
if (rc)
return rc;
mpt3sas_base_stop_watchdog(ioc);
flush_scheduled_work();
......@@ -11070,11 +11127,15 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t state)
static int
scsih_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
pci_power_t device_state = pdev->current_state;
int r;
r = _scsih_get_shost_and_ioc(pdev, &shost, &ioc);
if (r)
return r;
ioc_info(ioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
pdev, pci_name(pdev), device_state);
......@@ -11105,8 +11166,11 @@ scsih_resume(struct pci_dev *pdev)
static pci_ers_result_t
scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
return PCI_ERS_RESULT_DISCONNECT;
ioc_info(ioc, "PCI error: detected callback, state(%d)!!\n", state);
......@@ -11141,10 +11205,13 @@ scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
static pci_ers_result_t
scsih_pci_slot_reset(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
int rc;
if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
return PCI_ERS_RESULT_DISCONNECT;
ioc_info(ioc, "PCI error: slot reset callback!!\n");
ioc->pci_error_recovery = 0;
......@@ -11177,8 +11244,11 @@ scsih_pci_slot_reset(struct pci_dev *pdev)
static void
scsih_pci_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
return;
ioc_info(ioc, "PCI error: resume callback!!\n");
......@@ -11193,8 +11263,11 @@ scsih_pci_resume(struct pci_dev *pdev)
static pci_ers_result_t
scsih_pci_mmio_enabled(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct Scsi_Host *shost;
struct MPT3SAS_ADAPTER *ioc;
if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
return PCI_ERS_RESULT_DISCONNECT;
ioc_info(ioc, "PCI error: mmio enabled callback!!\n");
......@@ -11342,6 +11415,14 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3916,
PCI_ANY_ID, PCI_ANY_ID },
/*
* Aero SI –> 0x00E0 Invalid, 0x00E3 Tampered
*/
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID0_3916,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID1_3916,
PCI_ANY_ID, PCI_ANY_ID },
/* Atlas PCIe Switch Management Port */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_ATLAS_PCIe_SWITCH_DEVID,
PCI_ANY_ID, PCI_ANY_ID },
......@@ -11354,6 +11435,14 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3816,
PCI_ANY_ID, PCI_ANY_ID },
/*
* Sea SI –> 0x00E4 Invalid, 0x00E7 Tampered
*/
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID0_3816,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID1_3816,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment