diff options
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_ctl.c')
| -rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_ctl.c | 87 | 
1 files changed, 83 insertions, 4 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 05b6c6a073c3..d92ca140d298 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -3533,11 +3533,31 @@ diag_trigger_master_store(struct device *cdev,  {  	struct Scsi_Host *shost = class_to_shost(cdev);  	struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); +	struct SL_WH_MASTER_TRIGGER_T *master_tg;  	unsigned long flags;  	ssize_t rc; +	bool set = 1; -	spin_lock_irqsave(&ioc->diag_trigger_lock, flags);  	rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count); + +	if (ioc->supports_trigger_pages) { +		master_tg = kzalloc(sizeof(struct SL_WH_MASTER_TRIGGER_T), +		    GFP_KERNEL); +		if (!master_tg) +			return -ENOMEM; + +		memcpy(master_tg, buf, rc); +		if (!master_tg->MasterData) +			set = 0; +		if (mpt3sas_config_update_driver_trigger_pg1(ioc, master_tg, +		    set)) { +			kfree(master_tg); +			return -EFAULT; +		} +		kfree(master_tg); +	} + +	spin_lock_irqsave(&ioc->diag_trigger_lock, flags);  	memset(&ioc->diag_trigger_master, 0,  	    sizeof(struct SL_WH_MASTER_TRIGGER_T));  	memcpy(&ioc->diag_trigger_master, buf, rc); @@ -3589,11 +3609,31 @@ diag_trigger_event_store(struct device *cdev,  {  	struct Scsi_Host *shost = class_to_shost(cdev);  	struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); +	struct SL_WH_EVENT_TRIGGERS_T *event_tg;  	unsigned long flags;  	ssize_t sz; +	bool set = 1; -	spin_lock_irqsave(&ioc->diag_trigger_lock, flags);  	sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count); +	if (ioc->supports_trigger_pages) { +		event_tg = kzalloc(sizeof(struct SL_WH_EVENT_TRIGGERS_T), +		    GFP_KERNEL); +		if (!event_tg) +			return -ENOMEM; + +		memcpy(event_tg, buf, sz); +		if (!event_tg->ValidEntries) +			set = 0; +		if (mpt3sas_config_update_driver_trigger_pg2(ioc, event_tg, +		    set)) { +			kfree(event_tg); +			return -EFAULT; +		} +		kfree(event_tg); +	} + +	spin_lock_irqsave(&ioc->diag_trigger_lock, flags); +  	memset(&ioc->diag_trigger_event, 0,  	    sizeof(struct SL_WH_EVENT_TRIGGERS_T));  	memcpy(&ioc->diag_trigger_event, buf, sz); @@ -3644,11 +3684,31 @@ diag_trigger_scsi_store(struct device *cdev,  {  	struct Scsi_Host *shost = class_to_shost(cdev);  	struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); +	struct SL_WH_SCSI_TRIGGERS_T *scsi_tg;  	unsigned long flags;  	ssize_t sz; +	bool set = 1; + +	sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count); +	if (ioc->supports_trigger_pages) { +		scsi_tg = kzalloc(sizeof(struct SL_WH_SCSI_TRIGGERS_T), +		    GFP_KERNEL); +		if (!scsi_tg) +			return -ENOMEM; + +		memcpy(scsi_tg, buf, sz); +		if (!scsi_tg->ValidEntries) +			set = 0; +		if (mpt3sas_config_update_driver_trigger_pg3(ioc, scsi_tg, +		    set)) { +			kfree(scsi_tg); +			return -EFAULT; +		} +		kfree(scsi_tg); +	}  	spin_lock_irqsave(&ioc->diag_trigger_lock, flags); -	sz = min(sizeof(ioc->diag_trigger_scsi), count); +  	memset(&ioc->diag_trigger_scsi, 0, sizeof(ioc->diag_trigger_scsi));  	memcpy(&ioc->diag_trigger_scsi, buf, sz);  	if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES) @@ -3698,11 +3758,30 @@ diag_trigger_mpi_store(struct device *cdev,  {  	struct Scsi_Host *shost = class_to_shost(cdev);  	struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); +	struct SL_WH_MPI_TRIGGERS_T *mpi_tg;  	unsigned long flags;  	ssize_t sz; +	bool set = 1; -	spin_lock_irqsave(&ioc->diag_trigger_lock, flags);  	sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count); +	if (ioc->supports_trigger_pages) { +		mpi_tg = kzalloc(sizeof(struct SL_WH_MPI_TRIGGERS_T), +		    GFP_KERNEL); +		if (!mpi_tg) +			return -ENOMEM; + +		memcpy(mpi_tg, buf, sz); +		if (!mpi_tg->ValidEntries) +			set = 0; +		if (mpt3sas_config_update_driver_trigger_pg4(ioc, mpi_tg, +		    set)) { +			kfree(mpi_tg); +			return -EFAULT; +		} +		kfree(mpi_tg); +	} + +	spin_lock_irqsave(&ioc->diag_trigger_lock, flags);  	memset(&ioc->diag_trigger_mpi, 0,  	    sizeof(ioc->diag_trigger_mpi));  	memcpy(&ioc->diag_trigger_mpi, buf, sz);  |