aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid/megaraid_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c264
1 files changed, 261 insertions, 3 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 708ea3157b60..409648f5845f 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 * 11 *
12 * FILE : megaraid_sas.c 12 * FILE : megaraid_sas.c
13 * Version : v00.00.04.12-rc1 13 * Version : v00.00.04.17.1-rc1
14 * 14 *
15 * Authors: 15 * Authors:
16 * (email-id : megaraidlinux@lsi.com) 16 * (email-id : megaraidlinux@lsi.com)
@@ -843,6 +843,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
843 pthru->lun = scp->device->lun; 843 pthru->lun = scp->device->lun;
844 pthru->cdb_len = scp->cmd_len; 844 pthru->cdb_len = scp->cmd_len;
845 pthru->timeout = 0; 845 pthru->timeout = 0;
846 pthru->pad_0 = 0;
846 pthru->flags = flags; 847 pthru->flags = flags;
847 pthru->data_xfer_len = scsi_bufflen(scp); 848 pthru->data_xfer_len = scsi_bufflen(scp);
848 849
@@ -874,6 +875,12 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
874 pthru->sge_count = megasas_make_sgl32(instance, scp, 875 pthru->sge_count = megasas_make_sgl32(instance, scp,
875 &pthru->sgl); 876 &pthru->sgl);
876 877
878 if (pthru->sge_count > instance->max_num_sge) {
879 printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n",
880 pthru->sge_count);
881 return 0;
882 }
883
877 /* 884 /*
878 * Sense info specific 885 * Sense info specific
879 */ 886 */
@@ -1000,6 +1007,12 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
1000 } else 1007 } else
1001 ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); 1008 ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
1002 1009
1010 if (ldio->sge_count > instance->max_num_sge) {
1011 printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n",
1012 ldio->sge_count);
1013 return 0;
1014 }
1015
1003 /* 1016 /*
1004 * Sense info specific 1017 * Sense info specific
1005 */ 1018 */
@@ -2250,6 +2263,7 @@ megasas_get_pd_list(struct megasas_instance *instance)
2250 dcmd->sge_count = 1; 2263 dcmd->sge_count = 1;
2251 dcmd->flags = MFI_FRAME_DIR_READ; 2264 dcmd->flags = MFI_FRAME_DIR_READ;
2252 dcmd->timeout = 0; 2265 dcmd->timeout = 0;
2266 dcmd->pad_0 = 0;
2253 dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); 2267 dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
2254 dcmd->opcode = MR_DCMD_PD_LIST_QUERY; 2268 dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
2255 dcmd->sgl.sge32[0].phys_addr = ci_h; 2269 dcmd->sgl.sge32[0].phys_addr = ci_h;
@@ -2294,6 +2308,86 @@ megasas_get_pd_list(struct megasas_instance *instance)
2294 return ret; 2308 return ret;
2295} 2309}
2296 2310
2311/*
2312 * megasas_get_ld_list_info - Returns FW's ld_list structure
2313 * @instance: Adapter soft state
2314 * @ld_list: ld_list structure
2315 *
2316 * Issues an internal command (DCMD) to get the FW's controller PD
2317 * list structure. This information is mainly used to find out SYSTEM
2318 * supported by the FW.
2319 */
2320static int
2321megasas_get_ld_list(struct megasas_instance *instance)
2322{
2323 int ret = 0, ld_index = 0, ids = 0;
2324 struct megasas_cmd *cmd;
2325 struct megasas_dcmd_frame *dcmd;
2326 struct MR_LD_LIST *ci;
2327 dma_addr_t ci_h = 0;
2328
2329 cmd = megasas_get_cmd(instance);
2330
2331 if (!cmd) {
2332 printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n");
2333 return -ENOMEM;
2334 }
2335
2336 dcmd = &cmd->frame->dcmd;
2337
2338 ci = pci_alloc_consistent(instance->pdev,
2339 sizeof(struct MR_LD_LIST),
2340 &ci_h);
2341
2342 if (!ci) {
2343 printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n");
2344 megasas_return_cmd(instance, cmd);
2345 return -ENOMEM;
2346 }
2347
2348 memset(ci, 0, sizeof(*ci));
2349 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
2350
2351 dcmd->cmd = MFI_CMD_DCMD;
2352 dcmd->cmd_status = 0xFF;
2353 dcmd->sge_count = 1;
2354 dcmd->flags = MFI_FRAME_DIR_READ;
2355 dcmd->timeout = 0;
2356 dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
2357 dcmd->opcode = MR_DCMD_LD_GET_LIST;
2358 dcmd->sgl.sge32[0].phys_addr = ci_h;
2359 dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
2360 dcmd->pad_0 = 0;
2361
2362 if (!megasas_issue_polled(instance, cmd)) {
2363 ret = 0;
2364 } else {
2365 ret = -1;
2366 }
2367
2368 /* the following function will get the instance PD LIST */
2369
2370 if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) {
2371 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
2372
2373 for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
2374 if (ci->ldList[ld_index].state != 0) {
2375 ids = ci->ldList[ld_index].ref.targetId;
2376 instance->ld_ids[ids] =
2377 ci->ldList[ld_index].ref.targetId;
2378 }
2379 }
2380 }
2381
2382 pci_free_consistent(instance->pdev,
2383 sizeof(struct MR_LD_LIST),
2384 ci,
2385 ci_h);
2386
2387 megasas_return_cmd(instance, cmd);
2388 return ret;
2389}
2390
2297/** 2391/**
2298 * megasas_get_controller_info - Returns FW's controller structure 2392 * megasas_get_controller_info - Returns FW's controller structure
2299 * @instance: Adapter soft state 2393 * @instance: Adapter soft state
@@ -2339,6 +2433,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
2339 dcmd->sge_count = 1; 2433 dcmd->sge_count = 1;
2340 dcmd->flags = MFI_FRAME_DIR_READ; 2434 dcmd->flags = MFI_FRAME_DIR_READ;
2341 dcmd->timeout = 0; 2435 dcmd->timeout = 0;
2436 dcmd->pad_0 = 0;
2342 dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); 2437 dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
2343 dcmd->opcode = MR_DCMD_CTRL_GET_INFO; 2438 dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
2344 dcmd->sgl.sge32[0].phys_addr = ci_h; 2439 dcmd->sgl.sge32[0].phys_addr = ci_h;
@@ -2590,6 +2685,9 @@ static int megasas_init_mfi(struct megasas_instance *instance)
2590 (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); 2685 (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
2591 megasas_get_pd_list(instance); 2686 megasas_get_pd_list(instance);
2592 2687
2688 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
2689 megasas_get_ld_list(instance);
2690
2593 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); 2691 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
2594 2692
2595 /* 2693 /*
@@ -2714,6 +2812,7 @@ megasas_get_seq_num(struct megasas_instance *instance,
2714 dcmd->sge_count = 1; 2812 dcmd->sge_count = 1;
2715 dcmd->flags = MFI_FRAME_DIR_READ; 2813 dcmd->flags = MFI_FRAME_DIR_READ;
2716 dcmd->timeout = 0; 2814 dcmd->timeout = 0;
2815 dcmd->pad_0 = 0;
2717 dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); 2816 dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
2718 dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; 2817 dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
2719 dcmd->sgl.sge32[0].phys_addr = el_info_h; 2818 dcmd->sgl.sge32[0].phys_addr = el_info_h;
@@ -2828,6 +2927,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
2828 dcmd->sge_count = 1; 2927 dcmd->sge_count = 1;
2829 dcmd->flags = MFI_FRAME_DIR_READ; 2928 dcmd->flags = MFI_FRAME_DIR_READ;
2830 dcmd->timeout = 0; 2929 dcmd->timeout = 0;
2930 dcmd->pad_0 = 0;
2831 dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); 2931 dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
2832 dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; 2932 dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
2833 dcmd->mbox.w[0] = seq_num; 2933 dcmd->mbox.w[0] = seq_num;
@@ -3166,6 +3266,7 @@ static void megasas_flush_cache(struct megasas_instance *instance)
3166 dcmd->sge_count = 0; 3266 dcmd->sge_count = 0;
3167 dcmd->flags = MFI_FRAME_DIR_NONE; 3267 dcmd->flags = MFI_FRAME_DIR_NONE;
3168 dcmd->timeout = 0; 3268 dcmd->timeout = 0;
3269 dcmd->pad_0 = 0;
3169 dcmd->data_xfer_len = 0; 3270 dcmd->data_xfer_len = 0;
3170 dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; 3271 dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
3171 dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; 3272 dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
@@ -3205,6 +3306,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
3205 dcmd->sge_count = 0; 3306 dcmd->sge_count = 0;
3206 dcmd->flags = MFI_FRAME_DIR_NONE; 3307 dcmd->flags = MFI_FRAME_DIR_NONE;
3207 dcmd->timeout = 0; 3308 dcmd->timeout = 0;
3309 dcmd->pad_0 = 0;
3208 dcmd->data_xfer_len = 0; 3310 dcmd->data_xfer_len = 0;
3209 dcmd->opcode = opcode; 3311 dcmd->opcode = opcode;
3210 3312
@@ -3781,6 +3883,7 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
3781 compat_alloc_user_space(sizeof(struct megasas_iocpacket)); 3883 compat_alloc_user_space(sizeof(struct megasas_iocpacket));
3782 int i; 3884 int i;
3783 int error = 0; 3885 int error = 0;
3886 compat_uptr_t ptr;
3784 3887
3785 if (clear_user(ioc, sizeof(*ioc))) 3888 if (clear_user(ioc, sizeof(*ioc)))
3786 return -EFAULT; 3889 return -EFAULT;
@@ -3793,9 +3896,22 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
3793 copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) 3896 copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
3794 return -EFAULT; 3897 return -EFAULT;
3795 3898
3796 for (i = 0; i < MAX_IOCTL_SGE; i++) { 3899 /*
3797 compat_uptr_t ptr; 3900 * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
3901 * sense_len is not null, so prepare the 64bit value under
3902 * the same condition.
3903 */
3904 if (ioc->sense_len) {
3905 void __user **sense_ioc_ptr =
3906 (void __user **)(ioc->frame.raw + ioc->sense_off);
3907 compat_uptr_t *sense_cioc_ptr =
3908 (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
3909 if (get_user(ptr, sense_cioc_ptr) ||
3910 put_user(compat_ptr(ptr), sense_ioc_ptr))
3911 return -EFAULT;
3912 }
3798 3913
3914 for (i = 0; i < MAX_IOCTL_SGE; i++) {
3799 if (get_user(ptr, &cioc->sgl[i].iov_base) || 3915 if (get_user(ptr, &cioc->sgl[i].iov_base) ||
3800 put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || 3916 put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
3801 copy_in_user(&ioc->sgl[i].iov_len, 3917 copy_in_user(&ioc->sgl[i].iov_len,
@@ -3970,6 +4086,7 @@ megasas_aen_polling(struct work_struct *work)
3970 struct Scsi_Host *host; 4086 struct Scsi_Host *host;
3971 struct scsi_device *sdev1; 4087 struct scsi_device *sdev1;
3972 u16 pd_index = 0; 4088 u16 pd_index = 0;
4089 u16 ld_index = 0;
3973 int i, j, doscan = 0; 4090 int i, j, doscan = 0;
3974 u32 seq_num; 4091 u32 seq_num;
3975 int error; 4092 int error;
@@ -3985,8 +4102,124 @@ megasas_aen_polling(struct work_struct *work)
3985 4102
3986 switch (instance->evt_detail->code) { 4103 switch (instance->evt_detail->code) {
3987 case MR_EVT_PD_INSERTED: 4104 case MR_EVT_PD_INSERTED:
4105 if (megasas_get_pd_list(instance) == 0) {
4106 for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
4107 for (j = 0;
4108 j < MEGASAS_MAX_DEV_PER_CHANNEL;
4109 j++) {
4110
4111 pd_index =
4112 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4113
4114 sdev1 =
4115 scsi_device_lookup(host, i, j, 0);
4116
4117 if (instance->pd_list[pd_index].driveState
4118 == MR_PD_STATE_SYSTEM) {
4119 if (!sdev1) {
4120 scsi_add_device(host, i, j, 0);
4121 }
4122
4123 if (sdev1)
4124 scsi_device_put(sdev1);
4125 }
4126 }
4127 }
4128 }
4129 doscan = 0;
4130 break;
4131
3988 case MR_EVT_PD_REMOVED: 4132 case MR_EVT_PD_REMOVED:
4133 if (megasas_get_pd_list(instance) == 0) {
4134 megasas_get_pd_list(instance);
4135 for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
4136 for (j = 0;
4137 j < MEGASAS_MAX_DEV_PER_CHANNEL;
4138 j++) {
4139
4140 pd_index =
4141 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4142
4143 sdev1 =
4144 scsi_device_lookup(host, i, j, 0);
4145
4146 if (instance->pd_list[pd_index].driveState
4147 == MR_PD_STATE_SYSTEM) {
4148 if (sdev1) {
4149 scsi_device_put(sdev1);
4150 }
4151 } else {
4152 if (sdev1) {
4153 scsi_remove_device(sdev1);
4154 scsi_device_put(sdev1);
4155 }
4156 }
4157 }
4158 }
4159 }
4160 doscan = 0;
4161 break;
4162
4163 case MR_EVT_LD_OFFLINE:
4164 case MR_EVT_LD_DELETED:
4165 megasas_get_ld_list(instance);
4166 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
4167 for (j = 0;
4168 j < MEGASAS_MAX_DEV_PER_CHANNEL;
4169 j++) {
4170
4171 ld_index =
4172 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4173
4174 sdev1 = scsi_device_lookup(host,
4175 i + MEGASAS_MAX_LD_CHANNELS,
4176 j,
4177 0);
4178
4179 if (instance->ld_ids[ld_index] != 0xff) {
4180 if (sdev1) {
4181 scsi_device_put(sdev1);
4182 }
4183 } else {
4184 if (sdev1) {
4185 scsi_remove_device(sdev1);
4186 scsi_device_put(sdev1);
4187 }
4188 }
4189 }
4190 }
4191 doscan = 0;
4192 break;
4193 case MR_EVT_LD_CREATED:
4194 megasas_get_ld_list(instance);
4195 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
4196 for (j = 0;
4197 j < MEGASAS_MAX_DEV_PER_CHANNEL;
4198 j++) {
4199 ld_index =
4200 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4201
4202 sdev1 = scsi_device_lookup(host,
4203 i+MEGASAS_MAX_LD_CHANNELS,
4204 j, 0);
4205
4206 if (instance->ld_ids[ld_index] !=
4207 0xff) {
4208 if (!sdev1) {
4209 scsi_add_device(host,
4210 i + 2,
4211 j, 0);
4212 }
4213 }
4214 if (sdev1) {
4215 scsi_device_put(sdev1);
4216 }
4217 }
4218 }
4219 doscan = 0;
4220 break;
3989 case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: 4221 case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
4222 case MR_EVT_FOREIGN_CFG_IMPORTED:
3990 doscan = 1; 4223 doscan = 1;
3991 break; 4224 break;
3992 default: 4225 default:
@@ -4021,6 +4254,31 @@ megasas_aen_polling(struct work_struct *work)
4021 } 4254 }
4022 } 4255 }
4023 } 4256 }
4257
4258 megasas_get_ld_list(instance);
4259 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
4260 for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
4261 ld_index =
4262 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4263
4264 sdev1 = scsi_device_lookup(host,
4265 i+MEGASAS_MAX_LD_CHANNELS, j, 0);
4266 if (instance->ld_ids[ld_index] != 0xff) {
4267 if (!sdev1) {
4268 scsi_add_device(host,
4269 i+2,
4270 j, 0);
4271 } else {
4272 scsi_device_put(sdev1);
4273 }
4274 } else {
4275 if (sdev1) {
4276 scsi_remove_device(sdev1);
4277 scsi_device_put(sdev1);
4278 }
4279 }
4280 }
4281 }
4024 } 4282 }
4025 4283
4026 if ( instance->aen_cmd != NULL ) { 4284 if ( instance->aen_cmd != NULL ) {