@@ -257,6 +257,11 @@ do { \
sdev_printk(KERN_INFO, sdev, RDAC_NAME ": " f "\n", ## arg); \
} while (0);
+/* number of bytes needed to represent luns involved
+ * in mode select in bit string format
+ */
+#define LUN_FAILOVER_BYTES 32
+
static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
@@ -295,7 +300,8 @@ static struct request *get_rdac_req(stru
}
static struct request *rdac_failover_get(struct scsi_device *sdev,
- struct rdac_dh_data *h, struct list_head *list)
+ struct rdac_dh_data *h, struct list_head *list,
+ unsigned int *num_luns)
{
struct request *rq;
struct rdac_mode_common *common;
@@ -331,7 +337,10 @@ static struct request *rdac_failover_get
common->rdac_options = RDAC_FORCED_QUIESENCE;
list_for_each_entry(qdata, list, entry) {
- lun_table[qdata->h->lun] = 0x81;
+ if (lun_table[qdata->h->lun] != 0x81) {
+ lun_table[qdata->h->lun] = 0x81;
+ (*num_luns)++;
+ }
}
/* get request for block layer packet command */
@@ -582,6 +591,77 @@ done:
return err;
}
+/* encode luns involved in mode select into 256 bits string.
+ * decode logic for lun number set in each byte is as follows:
+ * lun number = number of bits before the current byte +
+ * position index [0-7] of the set bit in the current byte from R->L -
+ */
+static void lun_table_bitstring(unsigned char *lun_table,
+ unsigned int lun_table_length, unsigned char *lun_str)
+{
+ u8 lun_bit_table[LUN_FAILOVER_BYTES] = {0};
+ u8 pos = 0, ret, byte;
+ unsigned int lun;
+
+ BUG_ON(lun_str == NULL);
+
+ for (lun = 0; lun < lun_table_length; ++lun) {
+ if (lun_table[lun] == 0x81)
+ lun_bit_table[lun/8] |= (1 << (lun % 8));
+ }
+ for (byte = 0; byte < LUN_FAILOVER_BYTES; ++byte) {
+ ret = snprintf(lun_str+pos, 3, "%02x",
+ lun_bit_table[byte]);
+ pos = pos+ret;
+ }
+ lun_str[pos] = '\0';
+ return ;
+}
+
+/* get lun id's in mode select in either bit encoded
+ * or plain string format based on number of luns batched
+ */
+static void lun_table_string(unsigned char *lun_table,
+ unsigned int lun_table_length,
+ unsigned char *lun_str, unsigned int num_luns)
+{
+ u8 ret;
+ unsigned int lun, pos = 0;
+
+ BUG_ON(lun_str == NULL);
+
+ /* prefer encoded bit string for large number or luns */
+ if (num_luns > 16) {
+ lun_table_bitstring(lun_table, lun_table_length, lun_str);
+ } else {
+ for (lun = 0; lun < lun_table_length; ++lun) {
+ if (lun_table[lun] == 0x81) {
+ ret = snprintf(lun_str+pos, 4, "%d", lun);
+ lun_str[pos+ret] = ',';
+ pos = pos+ret+1;
+ }
+ }
+ lun_str[pos-1] = '\0';
+ }
+ return ;
+}
+
+/* get mode select lun table string for debug pusposes */
+static void get_ms_lunstring(struct rdac_controller *ctlr,
+ unsigned char *lun_str, unsigned int num_luns)
+{
+ if (likely(ctlr->use_ms10)) {
+ struct rdac_pg_expanded *rdac_pg = &ctlr->mode_select.expanded;
+ lun_table_string(&rdac_pg->lun_table[0],
+ 256, lun_str, num_luns);
+ } else {
+ struct rdac_pg_legacy *rdac_pg = &ctlr->mode_select.legacy;
+ lun_table_string(&rdac_pg->lun_table[0],
+ MODE6_MAX_LUN, lun_str, num_luns);
+ }
+ return ;
+}
+
static void send_mode_select(struct work_struct *work)
{
struct rdac_controller *ctlr =
@@ -592,6 +672,8 @@ static void send_mode_select(struct work
struct request_queue *q = sdev->request_queue;
int err, retry_cnt = RDAC_RETRY_COUNT;
struct rdac_queue_data *tmp, *qdata;
+ unsigned int num_luns = 0;
+ unsigned char lun_str[LUN_FAILOVER_BYTES * 2 + 1] = {0};
LIST_HEAD(list);
spin_lock(&ctlr->ms_lock);
@@ -602,14 +684,19 @@ static void send_mode_select(struct work
retry:
err = SCSI_DH_RES_TEMP_UNAVAIL;
- rq = rdac_failover_get(sdev, h, &list);
+ rq = rdac_failover_get(sdev, h, &list, &num_luns);
if (!rq)
goto done;
+ /* get lun debug string only once */
+ if (retry_cnt == RDAC_RETRY_COUNT)
+ get_ms_lunstring(ctlr, lun_str, num_luns);
+
RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
- "%s MODE_SELECT command",
+ "%s MODE_SELECT command for %d lun(s) [%s]",
(char *) h->ctlr->array_name, h->ctlr->index,
- (retry_cnt == RDAC_RETRY_COUNT) ? "queueing" : "retrying");
+ (retry_cnt == RDAC_RETRY_COUNT) ? "queueing" :
+ "retrying", num_luns, lun_str);
err = blk_execute_rq(q, NULL, rq, 1);
blk_put_request(rq);
@@ -621,8 +708,9 @@ retry:
if (err == SCSI_DH_OK) {
h->state = RDAC_STATE_ACTIVE;
RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
- "MODE_SELECT completed",
- (char *) h->ctlr->array_name, h->ctlr->index);
+ "MODE_SELECT completed for %d lun(s) [%s]",
+ (char *) h->ctlr->array_name, h->ctlr->index,
+ num_luns, lun_str);
}
done: