aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c125
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h17
2 files changed, 141 insertions, 1 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 6d998e050338..b0d6991cb6f3 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -1520,6 +1520,8 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
1520 return 0; 1520 return 0;
1521} 1521}
1522 1522
1523static void megasas_aen_polling(struct work_struct *work);
1524
1523/** 1525/**
1524 * megasas_service_aen - Processes an event notification 1526 * megasas_service_aen - Processes an event notification
1525 * @instance: Adapter soft state 1527 * @instance: Adapter soft state
@@ -1551,6 +1553,20 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
1551 1553
1552 instance->aen_cmd = NULL; 1554 instance->aen_cmd = NULL;
1553 megasas_return_cmd(instance, cmd); 1555 megasas_return_cmd(instance, cmd);
1556
1557 if (instance->unload == 0) {
1558 struct megasas_aen_event *ev;
1559 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
1560 if (!ev) {
1561 printk(KERN_ERR "megasas_service_aen: out of memory\n");
1562 } else {
1563 ev->instance = instance;
1564 instance->ev = ev;
1565 INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
1566 schedule_delayed_work(
1567 (struct delayed_work *)&ev->hotplug_work, 0);
1568 }
1569 }
1554} 1570}
1555 1571
1556/* 1572/*
@@ -2075,6 +2091,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
2075 } 2091 }
2076 2092
2077 cmd->frame->io.context = cmd->index; 2093 cmd->frame->io.context = cmd->index;
2094 cmd->frame->io.pad_0 = 0;
2078 } 2095 }
2079 2096
2080 return 0; 2097 return 0;
@@ -2271,7 +2288,6 @@ megasas_get_pd_list(struct megasas_instance *instance)
2271 return ret; 2288 return ret;
2272} 2289}
2273 2290
2274
2275/** 2291/**
2276 * megasas_get_controller_info - Returns FW's controller structure 2292 * megasas_get_controller_info - Returns FW's controller structure
2277 * @instance: Adapter soft state 2293 * @instance: Adapter soft state
@@ -2986,6 +3002,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2986 *instance->consumer = 0; 3002 *instance->consumer = 0;
2987 megasas_poll_wait_aen = 0; 3003 megasas_poll_wait_aen = 0;
2988 instance->flag_ieee = 0; 3004 instance->flag_ieee = 0;
3005 instance->ev = NULL;
2989 3006
2990 instance->evt_detail = pci_alloc_consistent(pdev, 3007 instance->evt_detail = pci_alloc_consistent(pdev,
2991 sizeof(struct 3008 sizeof(struct
@@ -3209,6 +3226,16 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
3209 3226
3210 megasas_flush_cache(instance); 3227 megasas_flush_cache(instance);
3211 megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); 3228 megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
3229
3230 /* cancel the delayed work if this work still in queue */
3231 if (instance->ev != NULL) {
3232 struct megasas_aen_event *ev = instance->ev;
3233 cancel_delayed_work(
3234 (struct delayed_work *)&ev->hotplug_work);
3235 flush_scheduled_work();
3236 instance->ev = NULL;
3237 }
3238
3212 tasklet_kill(&instance->isr_tasklet); 3239 tasklet_kill(&instance->isr_tasklet);
3213 3240
3214 pci_set_drvdata(instance->pdev, instance); 3241 pci_set_drvdata(instance->pdev, instance);
@@ -3349,6 +3376,16 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
3349 scsi_remove_host(instance->host); 3376 scsi_remove_host(instance->host);
3350 megasas_flush_cache(instance); 3377 megasas_flush_cache(instance);
3351 megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); 3378 megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
3379
3380 /* cancel the delayed work if this work still in queue*/
3381 if (instance->ev != NULL) {
3382 struct megasas_aen_event *ev = instance->ev;
3383 cancel_delayed_work(
3384 (struct delayed_work *)&ev->hotplug_work);
3385 flush_scheduled_work();
3386 instance->ev = NULL;
3387 }
3388
3352 tasklet_kill(&instance->isr_tasklet); 3389 tasklet_kill(&instance->isr_tasklet);
3353 3390
3354 /* 3391 /*
@@ -3913,6 +3950,92 @@ out:
3913 return retval; 3950 return retval;
3914} 3951}
3915 3952
3953static void
3954megasas_aen_polling(struct work_struct *work)
3955{
3956 struct megasas_aen_event *ev =
3957 container_of(work, struct megasas_aen_event, hotplug_work);
3958 struct megasas_instance *instance = ev->instance;
3959 union megasas_evt_class_locale class_locale;
3960 struct Scsi_Host *host;
3961 struct scsi_device *sdev1;
3962 u16 pd_index = 0;
3963 int i, j, doscan = 0;
3964 u32 seq_num;
3965 int error;
3966
3967 if (!instance) {
3968 printk(KERN_ERR "invalid instance!\n");
3969 kfree(ev);
3970 return;
3971 }
3972 instance->ev = NULL;
3973 host = instance->host;
3974 if (instance->evt_detail) {
3975
3976 switch (instance->evt_detail->code) {
3977 case MR_EVT_PD_INSERTED:
3978 case MR_EVT_PD_REMOVED:
3979 case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
3980 doscan = 1;
3981 break;
3982 default:
3983 doscan = 0;
3984 break;
3985 }
3986 } else {
3987 printk(KERN_ERR "invalid evt_detail!\n");
3988 kfree(ev);
3989 return;
3990 }
3991
3992 if (doscan) {
3993 printk(KERN_INFO "scanning ...\n");
3994 megasas_get_pd_list(instance);
3995 for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
3996 for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
3997 pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
3998 sdev1 = scsi_device_lookup(host, i, j, 0);
3999 if (instance->pd_list[pd_index].driveState ==
4000 MR_PD_STATE_SYSTEM) {
4001 if (!sdev1) {
4002 scsi_add_device(host, i, j, 0);
4003 }
4004 if (sdev1)
4005 scsi_device_put(sdev1);
4006 } else {
4007 if (sdev1) {
4008 scsi_remove_device(sdev1);
4009 scsi_device_put(sdev1);
4010 }
4011 }
4012 }
4013 }
4014 }
4015
4016 if ( instance->aen_cmd != NULL ) {
4017 kfree(ev);
4018 return ;
4019 }
4020
4021 seq_num = instance->evt_detail->seq_num + 1;
4022
4023 /* Register AEN with FW for latest sequence number plus 1 */
4024 class_locale.members.reserved = 0;
4025 class_locale.members.locale = MR_EVT_LOCALE_ALL;
4026 class_locale.members.class = MR_EVT_CLASS_DEBUG;
4027 mutex_lock(&instance->aen_mutex);
4028 error = megasas_register_aen(instance, seq_num,
4029 class_locale.word);
4030 mutex_unlock(&instance->aen_mutex);
4031
4032 if (error)
4033 printk(KERN_ERR "register aen failed error %x\n", error);
4034
4035 kfree(ev);
4036}
4037
4038
3916static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, 4039static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO,
3917 megasas_sysfs_show_poll_mode_io, 4040 megasas_sysfs_show_poll_mode_io,
3918 megasas_sysfs_set_poll_mode_io); 4041 megasas_sysfs_set_poll_mode_io);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 13ac37e80075..cd1c008f9ab8 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -285,6 +285,17 @@ enum MR_PD_QUERY_TYPE {
285 MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, 285 MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5,
286}; 286};
287 287
288#define MR_EVT_CFG_CLEARED 0x0004
289#define MR_EVT_LD_STATE_CHANGE 0x0051
290#define MR_EVT_PD_INSERTED 0x005b
291#define MR_EVT_PD_REMOVED 0x0070
292#define MR_EVT_LD_CREATED 0x008a
293#define MR_EVT_LD_DELETED 0x008b
294#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
295#define MR_EVT_LD_OFFLINE 0x00fc
296#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
297#define MAX_LOGICAL_DRIVES 64
298
288enum MR_PD_STATE { 299enum MR_PD_STATE {
289 MR_PD_STATE_UNCONFIGURED_GOOD = 0x00, 300 MR_PD_STATE_UNCONFIGURED_GOOD = 0x00,
290 MR_PD_STATE_UNCONFIGURED_BAD = 0x01, 301 MR_PD_STATE_UNCONFIGURED_BAD = 0x01,
@@ -1157,6 +1168,11 @@ struct megasas_evt_detail {
1157 1168
1158} __attribute__ ((packed)); 1169} __attribute__ ((packed));
1159 1170
1171struct megasas_aen_event {
1172 struct work_struct hotplug_work;
1173 struct megasas_instance *instance;
1174};
1175
1160struct megasas_instance { 1176struct megasas_instance {
1161 1177
1162 u32 *producer; 1178 u32 *producer;
@@ -1176,6 +1192,7 @@ struct megasas_instance {
1176 u16 max_num_sge; 1192 u16 max_num_sge;
1177 u16 max_fw_cmds; 1193 u16 max_fw_cmds;
1178 u32 max_sectors_per_req; 1194 u32 max_sectors_per_req;
1195 struct megasas_aen_event *ev;
1179 1196
1180 struct megasas_cmd **cmd_list; 1197 struct megasas_cmd **cmd_list;
1181 struct list_head cmd_pool; 1198 struct list_head cmd_pool;