aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/message/fusion/mptbase.h1
-rw-r--r--drivers/message/fusion/mptsas.c207
-rw-r--r--drivers/message/fusion/mptscsih.c21
-rw-r--r--drivers/message/fusion/mptscsih.h1
4 files changed, 230 insertions, 0 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 4f3d4c34bcd8..1c8514dc31ca 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -758,6 +758,7 @@ typedef struct _MPT_ADAPTER
758 struct scsi_cmnd **ScsiLookup; 758 struct scsi_cmnd **ScsiLookup;
759 spinlock_t scsi_lookup_lock; 759 spinlock_t scsi_lookup_lock;
760 u64 dma_mask; 760 u64 dma_mask;
761 u32 broadcast_aen_busy;
761 char reset_work_q_name[MPT_KOBJ_NAME_LEN]; 762 char reset_work_q_name[MPT_KOBJ_NAME_LEN];
762 struct workqueue_struct *reset_work_q; 763 struct workqueue_struct *reset_work_q;
763 struct delayed_work fault_reset_work; 764 struct delayed_work fault_reset_work;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 10a12d846e85..88a1a6d3bc04 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -121,6 +121,7 @@ static void mptsas_expander_delete(MPT_ADAPTER *ioc,
121static void mptsas_send_expander_event(struct fw_event_work *fw_event); 121static void mptsas_send_expander_event(struct fw_event_work *fw_event);
122static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); 122static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
123static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc); 123static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
124static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
124static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event); 125static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
125static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id); 126static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
126 127
@@ -287,6 +288,21 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
287 spin_unlock_irqrestore(&ioc->fw_event_lock, flags); 288 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
288} 289}
289 290
291/* requeue a sas firmware event */
292static void
293mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
294 unsigned long delay)
295{
296 unsigned long flags;
297 spin_lock_irqsave(&ioc->fw_event_lock, flags);
298 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
299 "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
300 fw_event->retries++;
301 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
302 msecs_to_jiffies(delay));
303 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
304}
305
290/* free memory assoicated to a sas firmware event */ 306/* free memory assoicated to a sas firmware event */
291static void 307static void
292mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event) 308mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
@@ -1606,6 +1622,9 @@ mptsas_firmware_event_work(struct work_struct *work)
1606 MPI_SAS_OP_CLEAR_NOT_PRESENT); 1622 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1607 mptsas_free_fw_event(ioc, fw_event); 1623 mptsas_free_fw_event(ioc, fw_event);
1608 break; 1624 break;
1625 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1626 mptsas_broadcast_primative_work(fw_event);
1627 break;
1609 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: 1628 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1610 mptsas_send_expander_event(fw_event); 1629 mptsas_send_expander_event(fw_event);
1611 break; 1630 break;
@@ -4325,6 +4344,182 @@ mptsas_send_raid_event(struct fw_event_work *fw_event)
4325 mptsas_free_fw_event(ioc, fw_event); 4344 mptsas_free_fw_event(ioc, fw_event);
4326} 4345}
4327 4346
4347/**
4348 * mptsas_issue_tm - send mptsas internal tm request
4349 * @ioc: Pointer to MPT_ADAPTER structure
4350 * @type: Task Management type
4351 * @channel: channel number for task management
4352 * @id: Logical Target ID for reset (if appropriate)
4353 * @lun: Logical unit for reset (if appropriate)
4354 * @task_context: Context for the task to be aborted
4355 * @timeout: timeout for task management control
4356 *
4357 * return 0 on success and -1 on failure:
4358 *
4359 */
4360static int
4361mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4362 int task_context, ulong timeout, u8 *issue_reset)
4363{
4364 MPT_FRAME_HDR *mf;
4365 SCSITaskMgmt_t *pScsiTm;
4366 int retval;
4367 unsigned long timeleft;
4368
4369 *issue_reset = 0;
4370 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4371 if (mf == NULL) {
4372 retval = -1; /* return failure */
4373 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4374 "msg frames!!\n", ioc->name));
4375 goto out;
4376 }
4377
4378 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4379 "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4380 "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4381 type, timeout, channel, id, (unsigned long long)lun,
4382 task_context));
4383
4384 pScsiTm = (SCSITaskMgmt_t *) mf;
4385 memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4386 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4387 pScsiTm->TaskType = type;
4388 pScsiTm->MsgFlags = 0;
4389 pScsiTm->TargetID = id;
4390 pScsiTm->Bus = channel;
4391 pScsiTm->ChainOffset = 0;
4392 pScsiTm->Reserved = 0;
4393 pScsiTm->Reserved1 = 0;
4394 pScsiTm->TaskMsgContext = task_context;
4395 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4396
4397 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4398 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4399 retval = 0;
4400 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4401
4402 /* Now wait for the command to complete */
4403 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4404 timeout*HZ);
4405 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4406 retval = -1; /* return failure */
4407 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4408 "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4409 mpt_free_msg_frame(ioc, mf);
4410 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4411 goto out;
4412 *issue_reset = 1;
4413 goto out;
4414 }
4415
4416 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4417 retval = -1; /* return failure */
4418 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4419 "TaskMgmt request: failed with no reply\n", ioc->name));
4420 goto out;
4421 }
4422
4423 out:
4424 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4425 return retval;
4426}
4427
4428/**
4429 * mptsas_broadcast_primative_work - Handle broadcast primitives
4430 * @work: work queue payload containing info describing the event
4431 *
4432 * this will be handled in workqueue context.
4433 */
4434static void
4435mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
4436{
4437 MPT_ADAPTER *ioc = fw_event->ioc;
4438 MPT_FRAME_HDR *mf;
4439 VirtDevice *vdevice;
4440 int ii;
4441 struct scsi_cmnd *sc;
4442 SCSITaskMgmtReply_t *pScsiTmReply;
4443 u8 issue_reset;
4444 int task_context;
4445 u8 channel, id;
4446 int lun;
4447 u32 termination_count;
4448 u32 query_count;
4449
4450 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4451 "%s - enter\n", ioc->name, __func__));
4452
4453 mutex_lock(&ioc->taskmgmt_cmds.mutex);
4454 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4455 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4456 mptsas_requeue_fw_event(ioc, fw_event, 1000);
4457 return;
4458 }
4459
4460 issue_reset = 0;
4461 termination_count = 0;
4462 query_count = 0;
4463 mpt_findImVolumes(ioc);
4464 pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4465
4466 for (ii = 0; ii < ioc->req_depth; ii++) {
4467 if (ioc->fw_events_off)
4468 goto out;
4469 sc = mptscsih_get_scsi_lookup(ioc, ii);
4470 if (!sc)
4471 continue;
4472 mf = MPT_INDEX_2_MFPTR(ioc, ii);
4473 if (!mf)
4474 continue;
4475 task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4476 vdevice = sc->device->hostdata;
4477 if (!vdevice || !vdevice->vtarget)
4478 continue;
4479 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4480 continue; /* skip hidden raid components */
4481 if (vdevice->vtarget->raidVolume)
4482 continue; /* skip hidden raid components */
4483 channel = vdevice->vtarget->channel;
4484 id = vdevice->vtarget->id;
4485 lun = vdevice->lun;
4486 if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4487 channel, id, (u64)lun, task_context, 30, &issue_reset))
4488 goto out;
4489 query_count++;
4490 termination_count +=
4491 le32_to_cpu(pScsiTmReply->TerminationCount);
4492 if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4493 (pScsiTmReply->ResponseCode ==
4494 MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4495 pScsiTmReply->ResponseCode ==
4496 MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4497 continue;
4498 if (mptsas_issue_tm(ioc,
4499 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4500 channel, id, (u64)lun, 0, 30, &issue_reset))
4501 goto out;
4502 termination_count +=
4503 le32_to_cpu(pScsiTmReply->TerminationCount);
4504 }
4505
4506 out:
4507 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4508 "%s - exit, query_count = %d termination_count = %d\n",
4509 ioc->name, __func__, query_count, termination_count));
4510
4511 ioc->broadcast_aen_busy = 0;
4512 mpt_clear_taskmgmt_in_progress_flag(ioc);
4513 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4514
4515 if (issue_reset) {
4516 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
4517 ioc->name, __func__);
4518 mpt_HardResetHandler(ioc, CAN_SLEEP);
4519 }
4520 mptsas_free_fw_event(ioc, fw_event);
4521}
4522
4328/* 4523/*
4329 * mptsas_send_ir2_event - handle exposing hidden disk when 4524 * mptsas_send_ir2_event - handle exposing hidden disk when
4330 * an inactive raid volume is added 4525 * an inactive raid volume is added
@@ -4388,6 +4583,18 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4388 4583
4389 delay = msecs_to_jiffies(1); 4584 delay = msecs_to_jiffies(1);
4390 switch (event) { 4585 switch (event) {
4586 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
4587 {
4588 EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
4589 (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
4590 if (broadcast_event_data->Primitive !=
4591 MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
4592 return 0;
4593 if (ioc->broadcast_aen_busy)
4594 return 0;
4595 ioc->broadcast_aen_busy = 1;
4596 break;
4597 }
4391 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: 4598 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
4392 { 4599 {
4393 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data = 4600 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index cf1aba18a09f..96681203d4a9 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -80,6 +80,7 @@ MODULE_VERSION(my_VERSION);
80/* 80/*
81 * Other private/forward protos... 81 * Other private/forward protos...
82 */ 82 */
83struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
83static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); 84static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
84static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); 85static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
85static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); 86static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
@@ -2419,6 +2420,26 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
2419 } 2420 }
2420} 2421}
2421 2422
2423/**
2424 * mptscsih_get_scsi_lookup - retrieves scmd entry
2425 * @ioc: Pointer to MPT_ADAPTER structure
2426 * @i: index into the array
2427 *
2428 * Returns the scsi_cmd pointer
2429 */
2430struct scsi_cmnd *
2431mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
2432{
2433 unsigned long flags;
2434 struct scsi_cmnd *scmd;
2435
2436 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2437 scmd = ioc->ScsiLookup[i];
2438 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2439
2440 return scmd;
2441}
2442EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
2422 2443
2423/** 2444/**
2424 * mptscsih_getclear_scsi_lookup 2445 * mptscsih_getclear_scsi_lookup
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 572739565f6a..eb3f677528ac 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -133,4 +133,5 @@ extern void mptscsih_timer_expired(unsigned long data);
133extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); 133extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
134extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); 134extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
135extern struct device_attribute *mptscsih_host_attrs[]; 135extern struct device_attribute *mptscsih_host_attrs[];
136extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
136extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); 137extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);