Beispiel #1
0
static void return_hosed_msg(struct kcs_info *kcs_info)
{
	struct ipmi_smi_msg *msg = kcs_info->curr_msg;

	/* Make it a reponse */
	msg->rsp[0] = msg->data[0] | 4;
	msg->rsp[1] = msg->data[1];
	msg->rsp[2] = 0xFF; /* Unknown error. */
	msg->rsp_size = 3;
			
	kcs_info->curr_msg = NULL;
	deliver_recv_msg(kcs_info, msg);
}
Beispiel #2
0
static void return_hosed_msg(struct smi_info *smi_info, int cCode)
{
	struct ipmi_smi_msg *msg = smi_info->curr_msg;

	if (cCode < 0 || cCode > IPMI_ERR_UNSPECIFIED)
		cCode = IPMI_ERR_UNSPECIFIED;
	/* else use it as is */

	/* Make it a response */
	msg->rsp[0] = msg->data[0] | 4;
	msg->rsp[1] = msg->data[1];
	msg->rsp[2] = cCode;
	msg->rsp_size = 3;

	smi_info->curr_msg = NULL;
	deliver_recv_msg(smi_info, msg);
}
Beispiel #3
0
static void handle_transaction_done(struct smi_info *smi_info)
{
	struct ipmi_smi_msg *msg;

	debug_timestamp("Done");
	switch (smi_info->si_state) {
	case SI_NORMAL:
		if (!smi_info->curr_msg)
			break;

		smi_info->curr_msg->rsp_size
			= smi_info->handlers->get_result(
				smi_info->si_sm,
				smi_info->curr_msg->rsp,
				IPMI_MAX_MSG_LENGTH);

		/*
		 * Do this here becase deliver_recv_msg() releases the
		 * lock, and a new message can be put in during the
		 * time the lock is released.
		 */
		msg = smi_info->curr_msg;
		smi_info->curr_msg = NULL;
		deliver_recv_msg(smi_info, msg);
		break;

	case SI_GETTING_FLAGS:
	{
		unsigned char msg[4];
		unsigned int  len;

		/* We got the flags from the SMI, now handle them. */
		len = smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
		if (msg[2] != 0) {
			/* Error fetching flags, just give up for now. */
			smi_info->si_state = SI_NORMAL;
		} else if (len < 4) {
			/*
			 * Hmm, no flags.  That's technically illegal, but
			 * don't use uninitialized data.
			 */
			smi_info->si_state = SI_NORMAL;
		} else {
			smi_info->msg_flags = msg[3];
			handle_flags(smi_info);
		}
		break;
	}

	case SI_CLEARING_FLAGS:
	{
		unsigned char msg[3];

		/* We cleared the flags. */
		smi_info->handlers->get_result(smi_info->si_sm, msg, 3);
		if (msg[2] != 0) {
			/* Error clearing flags */
			dev_warn(smi_info->dev,
				 "Error clearing flags: %2.2x\n", msg[2]);
		}
		smi_info->si_state = SI_NORMAL;
		break;
	}

	case SI_GETTING_EVENTS:
	{
		smi_info->curr_msg->rsp_size
			= smi_info->handlers->get_result(
				smi_info->si_sm,
				smi_info->curr_msg->rsp,
				IPMI_MAX_MSG_LENGTH);

		/*
		 * Do this here becase deliver_recv_msg() releases the
		 * lock, and a new message can be put in during the
		 * time the lock is released.
		 */
		msg = smi_info->curr_msg;
		smi_info->curr_msg = NULL;
		if (msg->rsp[2] != 0) {
			/* Error getting event, probably done. */
			msg->done(msg);

			/* Take off the event flag. */
			smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
			handle_flags(smi_info);
		} else {
			smi_inc_stat(smi_info, events);

			/*
			 * Do this before we deliver the message
			 * because delivering the message releases the
			 * lock and something else can mess with the
			 * state.
			 */
			handle_flags(smi_info);

			deliver_recv_msg(smi_info, msg);
		}
		break;
	}

	case SI_GETTING_MESSAGES:
	{
		smi_info->curr_msg->rsp_size
			= smi_info->handlers->get_result(
				smi_info->si_sm,
				smi_info->curr_msg->rsp,
				IPMI_MAX_MSG_LENGTH);

		/*
		 * Do this here becase deliver_recv_msg() releases the
		 * lock, and a new message can be put in during the
		 * time the lock is released.
		 */
		msg = smi_info->curr_msg;
		smi_info->curr_msg = NULL;
		if (msg->rsp[2] != 0) {
			/* Error getting event, probably done. */
			msg->done(msg);

			/* Take off the msg flag. */
			smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
			handle_flags(smi_info);
		} else {
			smi_inc_stat(smi_info, incoming_messages);

			/*
			 * Do this before we deliver the message
			 * because delivering the message releases the
			 * lock and something else can mess with the
			 * state.
			 */
			handle_flags(smi_info);

			deliver_recv_msg(smi_info, msg);
		}
		break;
	}

	case SI_CHECKING_ENABLES:
	{
		unsigned char msg[4];
		u8 enables;
		bool irq_on;

		/* We got the flags from the SMI, now handle them. */
		smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
		if (msg[2] != 0) {
			dev_warn(smi_info->dev,
				 "Couldn't get irq info: %x.\n", msg[2]);
			dev_warn(smi_info->dev,
				 "Maybe ok, but ipmi might run very slowly.\n");
			smi_info->si_state = SI_NORMAL;
			break;
		}
		enables = current_global_enables(smi_info, 0, &irq_on);
		if (smi_info->si_type == SI_BT)
			/* BT has its own interrupt enable bit. */
			check_bt_irq(smi_info, irq_on);
		if (enables != (msg[3] & GLOBAL_ENABLES_MASK)) {
			/* Enables are not correct, fix them. */
			msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
			msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
			msg[2] = enables | (msg[3] & ~GLOBAL_ENABLES_MASK);
			smi_info->handlers->start_transaction(
				smi_info->si_sm, msg, 3);
			smi_info->si_state = SI_SETTING_ENABLES;
		} else if (smi_info->supports_event_msg_buff) {
			smi_info->curr_msg = ipmi_alloc_smi_msg();
			if (!smi_info->curr_msg) {
				smi_info->si_state = SI_NORMAL;
				break;
			}
			start_getting_msg_queue(smi_info);
		} else {
			smi_info->si_state = SI_NORMAL;
		}
		break;
	}

	case SI_SETTING_ENABLES:
	{
		unsigned char msg[4];

		smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
		if (msg[2] != 0)
			dev_warn(smi_info->dev,
				 "Could not set the global enables: 0x%x.\n",
				 msg[2]);

		if (smi_info->supports_event_msg_buff) {
			smi_info->curr_msg = ipmi_alloc_smi_msg();
			if (!smi_info->curr_msg) {
				smi_info->si_state = SI_NORMAL;
				break;
			}
			start_getting_msg_queue(smi_info);
		} else {
			smi_info->si_state = SI_NORMAL;
		}
		break;
	}
	}
}
Beispiel #4
0
static void handle_transaction_done(struct kcs_info *kcs_info)
{
	struct ipmi_smi_msg *msg;
#ifdef DEBUG_TIMING
	struct timeval t;

	do_gettimeofday(&t);
	printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
#endif
	switch (kcs_info->kcs_state) {
	case KCS_NORMAL:
		if (!kcs_info->curr_msg)
			break;
			
		kcs_info->curr_msg->rsp_size
			= kcs_get_result(kcs_info->kcs_sm,
					 kcs_info->curr_msg->rsp,
					 IPMI_MAX_MSG_LENGTH);
		
		/* Do this here becase deliver_recv_msg() releases the
		   lock, and a new message can be put in during the
		   time the lock is released. */
		msg = kcs_info->curr_msg;
		kcs_info->curr_msg = NULL;
		deliver_recv_msg(kcs_info, msg);
		break;
		
	case KCS_GETTING_FLAGS:
	{
		unsigned char msg[4];
		unsigned int  len;

		/* We got the flags from the KCS, now handle them. */
		len = kcs_get_result(kcs_info->kcs_sm, msg, 4);
		if (msg[2] != 0) {
			/* Error fetching flags, just give up for
			   now. */
			kcs_info->kcs_state = KCS_NORMAL;
		} else if (len < 3) {
			/* Hmm, no flags.  That's technically illegal, but
			   don't use uninitialized data. */
			kcs_info->kcs_state = KCS_NORMAL;
		} else {
			kcs_info->msg_flags = msg[3];
			handle_flags(kcs_info);
		}
		break;
	}

	case KCS_CLEARING_FLAGS:
	case KCS_CLEARING_FLAGS_THEN_SET_IRQ:
	{
		unsigned char msg[3];

		/* We cleared the flags. */
		kcs_get_result(kcs_info->kcs_sm, msg, 3);
		if (msg[2] != 0) {
			/* Error clearing flags */
			printk(KERN_WARNING
			       "ipmi_kcs: Error clearing flags: %2.2x\n",
			       msg[2]);
		}
		if (kcs_info->kcs_state == KCS_CLEARING_FLAGS_THEN_SET_IRQ)
			start_enable_irq(kcs_info);
		else
			kcs_info->kcs_state = KCS_NORMAL;
		break;
	}

	case KCS_GETTING_EVENTS:
	{
		kcs_info->curr_msg->rsp_size
			= kcs_get_result(kcs_info->kcs_sm,
					 kcs_info->curr_msg->rsp,
					 IPMI_MAX_MSG_LENGTH);

		/* Do this here becase deliver_recv_msg() releases the
		   lock, and a new message can be put in during the
		   time the lock is released. */
		msg = kcs_info->curr_msg;
		kcs_info->curr_msg = NULL;
		if (msg->rsp[2] != 0) {
			/* Error getting event, probably done. */
			msg->done(msg);

			/* Take off the event flag. */
			kcs_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
		} else {
			deliver_recv_msg(kcs_info, msg);
		}
		handle_flags(kcs_info);
		break;
	}

	case KCS_GETTING_MESSAGES:
	{
		kcs_info->curr_msg->rsp_size
			= kcs_get_result(kcs_info->kcs_sm,
					 kcs_info->curr_msg->rsp,
					 IPMI_MAX_MSG_LENGTH);

		/* Do this here becase deliver_recv_msg() releases the
		   lock, and a new message can be put in during the
		   time the lock is released. */
		msg = kcs_info->curr_msg;
		kcs_info->curr_msg = NULL;
		if (msg->rsp[2] != 0) {
			/* Error getting event, probably done. */
			msg->done(msg);

			/* Take off the msg flag. */
			kcs_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
		} else {
			deliver_recv_msg(kcs_info, msg);
		}
		handle_flags(kcs_info);
		break;
	}

	case KCS_ENABLE_INTERRUPTS1:
	{
		unsigned char msg[4];

		/* We got the flags from the KCS, now handle them. */
		kcs_get_result(kcs_info->kcs_sm, msg, 4);
		if (msg[2] != 0) {
			printk(KERN_WARNING
			       "ipmi_kcs: Could not enable interrupts"
			       ", failed get, using polled mode.\n");
			kcs_info->kcs_state = KCS_NORMAL;
		} else {
			msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
			msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
			msg[2] = msg[3] | 1; /* enable msg queue int */
			start_kcs_transaction(kcs_info->kcs_sm, msg,3);
			kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS2;
		}
		break;
	}

	case KCS_ENABLE_INTERRUPTS2:
	{
		unsigned char msg[4];

		/* We got the flags from the KCS, now handle them. */
		kcs_get_result(kcs_info->kcs_sm, msg, 4);
		if (msg[2] != 0) {
			printk(KERN_WARNING
			       "ipmi_kcs: Could not enable interrupts"
			       ", failed set, using polled mode.\n");
		}
		kcs_info->kcs_state = KCS_NORMAL;
		break;
	}
	}
}