Index: iprutils/iprlib.h
===================================================================
--- iprutils.orig/iprlib.h
+++ iprutils/iprlib.h
@@ -49,6 +49,7 @@
 #include <bits/sockaddr.h>
 #include <linux/netlink.h>
 #include <time.h>
+#include <sys/param.h>
 
 typedef uint8_t u8;
 typedef uint16_t u16;
@@ -1413,6 +1414,7 @@ struct ipr_ioa {
 #define IPR_SIS32		0x00
 #define IPR_SIS64		0x01
 	u8 support_4k:1;
+   int can_queue;
 	enum ipr_tcq_mode tcq_mode;
 	u16 pci_vendor;
 	u16 pci_device;
@@ -2636,6 +2638,8 @@ u32 get_ioa_ucode_version(char *);
 int ipr_improper_device_type(struct ipr_dev *);
 int ipr_get_fw_version(struct ipr_dev *, u8 release_level[4]);
 int ipr_get_live_dump(struct ipr_ioa *);
+int ipr_max_queue_depth(struct ipr_ioa *ioa, int num_devs, int num_ssd_devs);
+void ipr_count_devices_in_vset(struct ipr_dev *, int *num_devs, int *ssd_num_devs);
 
 static inline u32 ipr_get_dev_res_handle(struct ipr_ioa *ioa, struct ipr_dev_record *dev_rcd)
 {
Index: iprutils/iprlib.c
===================================================================
--- iprutils.orig/iprlib.c
+++ iprutils/iprlib.c
@@ -2067,6 +2067,7 @@ void tool_init(int save_state)
 	DIR *dirfd, *host_dirfd;
 	struct dirent *dent, *host_dent;
 	ssize_t len;
+   char queue_str[256];
 
 	save_old_config();
 
@@ -2124,6 +2125,11 @@ void tool_init(int save_state)
 				sscanf(fw_str, "%d", &fw_type);
 			if (ipr_debug)
 				syslog(LOG_INFO, "tool_init: fw_type attr = %d.\n", fw_type);
+
+           len = sysfs_read_attr(scsipath, "can_queue", queue_str, 256);
+           if (len < 0)
+               ioa_dbg(ipr_ioa, "Failed to read can_queue attribute");
+           sscanf(queue_str, "%d", &ipr_ioa->can_queue);
 			break;
 		}
 		closedir(host_dirfd);
@@ -6632,10 +6638,14 @@ static void ipr_save_dev_attr(struct ipr
 			     char *value, int update)
 {
 	char category[16];
+   struct ipr_dev *alt_dev = dev->alt_path;
+
 	sprintf(category,"[%s %d:%d:%d]", IPR_CATEGORY_DISK,
 		dev->scsi_dev_data->channel, dev->scsi_dev_data->id,
 		dev->scsi_dev_data->lun);
 	ipr_save_attr(dev->ioa, category, field, value, update);
+   if (alt_dev)
+       ipr_save_attr(alt_dev->ioa, category, field, value, update);
 }
 
 /**
@@ -7167,6 +7177,11 @@ int ipr_set_dev_attr(struct ipr_dev *dev
 		} else {
 			if (ipr_write_dev_attr(dev, "queue_depth", temp))
 				return -EIO;
+
+           if (dev->alt_path && ipr_write_dev_attr(dev->alt_path,
+                               "queue_depth",
+                               temp))
+               return -EIO;
 		}
 		if (save)
 			ipr_save_dev_attr(dev, IPR_QUEUE_DEPTH, temp, 1);
@@ -8818,6 +8833,44 @@ static int setup_page0x0a(struct ipr_dev
 	return rc;
 }
 
+void ipr_count_devices_in_vset(struct ipr_dev *dev, int *num_devs,
+                  int *ssd_num_devs)
+{
+   struct ipr_dev *vset, *temp;
+   int devs_cnt = 0, ssd_devs_cnt = 0;
+
+   if (ipr_is_volume_set(dev)) {
+       for_each_dev_in_vset(dev, temp) {
+           devs_cnt++;
+           if (temp->block_dev_class & IPR_SSD)
+               ssd_devs_cnt++;
+           fprintf(stdout, "%s\n", temp->gen_name);
+       }
+   } else {
+       devs_cnt++;
+       if (dev->block_dev_class & IPR_SSD)
+           ssd_devs_cnt++;
+   }
+
+   *num_devs = devs_cnt;
+   *ssd_num_devs = ssd_devs_cnt;
+
+}
+
+int ipr_max_queue_depth(struct ipr_ioa *ioa, int num_devs, int num_ssd_devs)
+{
+   int max_qdepth;
+
+   if (num_ssd_devs == num_devs)
+       max_qdepth = MIN(num_devs * 64, ioa->can_queue);
+   else if (num_ssd_devs)
+       max_qdepth = MIN(num_devs * 32, ioa->can_queue);
+   else
+       max_qdepth = MIN(num_devs * 16, ioa->can_queue);
+
+   return MAX(max_qdepth, 128);
+}
+
 /**
  * init_vset_dev - 
  * @dev:		ipr dev struct
@@ -8835,7 +8888,7 @@ static void init_vset_dev(struct ipr_dev
 	struct ipr_query_res_state res_state;
 	char q_depth[100];
 	char cur_depth[100], saved_depth[100];
-	int depth, rc;
+   int depth, rc, num_devs, ssd_num_devs;
 
 	memset(&res_state, 0, sizeof(res_state));
 
@@ -8843,9 +8896,10 @@ static void init_vset_dev(struct ipr_dev
 		return;
 
 	if (!ipr_query_resource_state(dev, &res_state)) {
-		depth = res_state.vset.num_devices_in_vset * 4;
+       ipr_count_devices_in_vset(dev, &num_devs, &ssd_num_devs);
+       depth = ipr_max_queue_depth(dev->ioa, num_devs, ssd_num_devs);
+
 		snprintf(q_depth, sizeof(q_depth), "%d", depth);
-		q_depth[sizeof(q_depth)-1] = '\0';
 		if (ipr_read_dev_attr(dev, "queue_depth", cur_depth, 100))
 			return;
 		rc = ipr_get_saved_dev_attr(dev, IPR_QUEUE_DEPTH, saved_depth);
Index: iprutils/iprconfig.c
===================================================================
--- iprutils.orig/iprconfig.c
+++ iprutils/iprconfig.c
@@ -3501,7 +3501,7 @@ int configure_raid_parameters(i_containe
 	int *userptr = NULL;
 	int *retptr;
 	int max_x,max_y,start_y,start_x;
-	int qdepth, new_qdepth;
+   int qdepth, new_qdepth, max_qdepth;
 
 	getmaxyx(stdscr,max_y,max_x);
 	getbegyx(stdscr,start_y,start_x);
@@ -3523,6 +3523,7 @@ int configure_raid_parameters(i_containe
 		}
 	}
 
+   max_qdepth = ipr_max_queue_depth(ioa, selected_count, ssd_num);
 	if (ioa->sis64)
 		qdepth = selected_count * 16;
 	else
@@ -3626,7 +3627,7 @@ int configure_raid_parameters(i_containe
 	mvaddstr(6, 1, _("c=Change Setting"));
 	mvaddstr(8, 0,  "Protection Level . . . . . . . . . . . . :");
 	mvaddstr(9, 0,  "Stripe Size  . . . . . . . . . . . . . . :");
-	mvprintw(10, 0, "Queue Depth (default = %3d). . . . . . . :", qdepth);
+   mvprintw(10, 0, "Queue Depth (default = %3d)(max = %3d) . :", qdepth, max_qdepth);
 	mvaddstr(max_y - 4, 0, _("Press Enter to Continue"));
 	mvaddstr(max_y - 2, 0, EXIT_KEY_LABEL CANCEL_KEY_LABEL);
 
@@ -3759,10 +3760,8 @@ int configure_raid_parameters(i_containe
 				if (rc == CANCEL_FLAG)
 					continue;
 
-				if (new_qdepth > 128)
-					qdepth = 128;
-				else
-					qdepth = new_qdepth;
+               qdepth = (new_qdepth < max_qdepth)? new_qdepth:max_qdepth;
+
 				continue;
 			} else
 				continue;
@@ -10658,8 +10657,6 @@ static int disk_config_menu(struct disk_
 
 	if (disk_config_attr->option == 1) { /* queue depth*/
 		rc = display_input(start_row, &disk_config_attr->queue_depth);
-		if (disk_config_attr->queue_depth > 128)
-			disk_config_attr->queue_depth = 128;
 	} else if (disk_config_attr->option == 3) {  /* tag command queue.*/
 		num_menu_items = 2;
 		menu_item = malloc(sizeof(ITEM **) * (num_menu_items + 1));
@@ -10757,7 +10754,7 @@ int change_disk_config(i_container * i_c
 	struct ipr_dev *dev;
 	char qdepth_str[4];
 	char format_timeout_str[5];
-	char buffer[128];
+   char buffer[200];
 	i_container *temp_i_con;
 	int found = 0;
 	char *input;
@@ -10771,6 +10768,7 @@ int change_disk_config(i_container * i_c
 	int tcq_warning = 0;
 	int tcq_blocked = 0;
 	int tcq_enabled = 0;
+   int num_devs, ssd_num_devs, max_qdepth;
 
 	rc = RC_SUCCESS;
 
@@ -10832,10 +10830,18 @@ int change_disk_config(i_container * i_c
 		tcq_warning = tcq_blocked = 0;
 
 	if (!tcq_blocked || ipr_is_gscsi(dev)) {
-		body = add_line_to_body(body,_("Queue Depth"), "%3");
+       ipr_count_devices_in_vset(dev, &num_devs, &ssd_num_devs);
+       max_qdepth = ipr_max_queue_depth(dev->ioa, num_devs, ssd_num_devs);
+       sprintf(buffer, "Queue Depth (max = %03d)", max_qdepth);
+       body = add_line_to_body(body, buffer, "%3");
+
 		disk_config_attr[0].option = 1;
+
+       if (disk_attr.queue_depth > max_qdepth)
+           disk_attr.queue_depth = max_qdepth;
+
 		disk_config_attr[0].queue_depth = disk_attr.queue_depth;
-		sprintf(qdepth_str,"%d",disk_config_attr[0].queue_depth);
+       sprintf(qdepth_str, "%d", disk_config_attr[0].queue_depth);
 		i_con = add_i_con(i_con, qdepth_str, &disk_config_attr[0]);
 	}
 
@@ -10879,7 +10885,10 @@ int change_disk_config(i_container * i_c
 
 				if (config_attr->option == 1) {
 					sprintf(temp_i_con->field_data,"%d", config_attr->queue_depth);
-					disk_attr.queue_depth = config_attr->queue_depth;
+                   if (config_attr->queue_depth > max_qdepth)
+                       disk_attr.queue_depth = max_qdepth;
+                   else
+                       disk_attr.queue_depth = config_attr->queue_depth;
 				}
 				else if (config_attr->option == 2) {
 					sprintf(temp_i_con->field_data,"%d hr", config_attr->format_timeout);
@@ -13348,12 +13357,12 @@ static int format_for_raid(char **args,
  **/
 static int raid_create(char **args, int num_args)
 {
-	int i, num_devs = 0, rc;
+	int i, num_devs = 0, ssd_num_devs = 0, rc;
 	int non_4k_count = 0, is_4k_count = 0;
 	int next_raid_level, next_stripe_size, next_qdepth, next_label;
 	char *raid_level = IPR_DEFAULT_RAID_LVL;
 	char label[8];
-	int stripe_size, qdepth, zeroed_devs;
+   int stripe_size, qdepth, zeroed_devs, max_qdepth;
 	struct ipr_dev *dev;
 	struct sysfs_dev *sdev;
 	struct ipr_ioa *ioa = NULL;
@@ -13399,6 +13408,8 @@ static int raid_create(char **args, int
 
 			strcpy(label, args[i]);
 		} else if ((dev = find_dev(args[i]))) {
+           if (dev->block_dev_class & IPR_SSD)
+               ssd_num_devs++;
 			num_devs++;
 			if (zeroed_devs)
 				ipr_add_zeroed_dev(dev);
@@ -13456,6 +13467,9 @@ static int raid_create(char **args, int
 	if (!stripe_size)
 		stripe_size = ntohs(cap->recommended_stripe_size);
 
+   max_qdepth = ipr_max_queue_depth(dev->ioa, num_devs, ssd_num_devs);
+   if (qdepth > max_qdepth)
+       qdepth = max_qdepth;
 	if (!qdepth) {
 		if (ioa->sis64)
 			qdepth = num_devs * 16;
@@ -14672,6 +14686,7 @@ static int set_qdepth(char **args, int n
 	int rc;
 	struct ipr_disk_attr attr;
 	struct ipr_dev *dev = find_dev(args[0]);
+   int num_devs, ssd_num_devs, max_qdepth;
 
 	if (!dev) {
 		fprintf(stderr, "Cannot find %s\n", args[0]);
@@ -14688,10 +14703,14 @@ static int set_qdepth(char **args, int n
 	if (rc)
 		return rc;
 
+   ipr_count_devices_in_vset(dev, &num_devs, &ssd_num_devs);
+   max_qdepth = ipr_max_queue_depth(dev->ioa, num_devs, ssd_num_devs);
+
 	attr.queue_depth = strtoul(args[1], NULL, 10);
 
-	if (attr.queue_depth > 255) {
-		fprintf(stderr, "Invalid queue depth %s\n", args[1]);
+   if (attr.queue_depth > max_qdepth) {
+       fprintf(stderr, "Invalid queue depth, max queue depth is %d\n",
+           max_qdepth);
 		return -EINVAL;
 	}
 
