} u;
};
+static u32 base_mod64(u64 dividend, u32 divisor)
+{
+ u32 remainder;
+
+ if (!divisor)
+ pr_err("mpt3sas: DIVISOR is zero, in div fn\n");
+ remainder = do_div(dividend, divisor);
+ return remainder;
+}
+
/**
* _base_process_reply_queue - Process reply descriptors from reply
* descriptor post queue.
if (!_base_is_controller_msix_enabled(ioc))
return;
+ ioc->msix_load_balance = false;
+ if (ioc->reply_queue_count < num_online_cpus()) {
+ ioc->msix_load_balance = true;
+ return;
+ }
memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
static inline u8
_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
{
+ /* Enables reply_queue load balancing */
+ if (ioc->msix_load_balance)
+ return ioc->reply_queue_count ?
+ base_mod64(atomic64_add_return(1,
+ &ioc->total_io_cnt), ioc->reply_queue_count) : 0;
+
return ioc->cpu_msix_table[raw_smp_processor_id()];
}
* @msix_vector_count: number msix vectors
* @cpu_msix_table: table for mapping cpus to msix index
* @cpu_msix_table_sz: table size
+ * @total_io_cnt: Gives total IO count, used to load balance the interrupts
+ * @msix_load_balance: Enables load balancing of interrupts across
+ * the multiple MSIXs
* @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
u32 ioc_reset_count;
MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
u32 non_operational_loop;
+ atomic64_t total_io_cnt;
+ bool msix_load_balance;
/* internal commands, callback index */
u8 scsi_io_cb_idx;