Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ipmi/ipmi.c
Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | #define IPMI_INIT_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \ | ||||
ipmi_init_request((req), NULL, 0, (addr), (cmd), (reqlen), (replylen)) | ipmi_init_request((req), NULL, 0, (addr), (cmd), (reqlen), (replylen)) | ||||
#define IPMI_ALLOC_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \ | #define IPMI_ALLOC_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \ | ||||
(req) = __builtin_alloca(sizeof(struct ipmi_request) + \ | (req) = __builtin_alloca(sizeof(struct ipmi_request) + \ | ||||
(reqlen) + (replylen)); \ | (reqlen) + (replylen)); \ | ||||
IPMI_INIT_DRIVER_REQUEST((req), (addr), (cmd), (reqlen), \ | IPMI_INIT_DRIVER_REQUEST((req), (addr), (cmd), (reqlen), \ | ||||
(replylen)) | (replylen)) | ||||
#ifdef IPMB | |||||
static int ipmi_ipmb_checksum(u_char, int); | |||||
static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char, | |||||
u_char, u_char, int) | |||||
#endif | |||||
static d_ioctl_t ipmi_ioctl; | static d_ioctl_t ipmi_ioctl; | ||||
static d_poll_t ipmi_poll; | static d_poll_t ipmi_poll; | ||||
static d_open_t ipmi_open; | static d_open_t ipmi_open; | ||||
static void ipmi_dtor(void *arg); | static void ipmi_dtor(void *arg); | ||||
int ipmi_attached = 0; | int ipmi_attached = 0; | ||||
static int on = 1; | static int on = 1; | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | ipmi_dtor(void *arg) | ||||
} | } | ||||
sc->ipmi_opened--; | sc->ipmi_opened--; | ||||
IPMI_UNLOCK(sc); | IPMI_UNLOCK(sc); | ||||
/* Cleanup. */ | /* Cleanup. */ | ||||
free(dev, M_IPMI); | free(dev, M_IPMI); | ||||
} | } | ||||
#ifdef IPMB | static u_char | ||||
static int | |||||
ipmi_ipmb_checksum(u_char *data, int len) | ipmi_ipmb_checksum(u_char *data, int len) | ||||
{ | { | ||||
u_char sum = 0; | u_char sum = 0; | ||||
for (; len; len--) { | for (; len; len--) | ||||
sum += *data++; | sum += *data++; | ||||
} | |||||
return (-sum); | return (-sum); | ||||
} | } | ||||
/* XXX: Needs work */ | |||||
static int | static int | ||||
philip: Just delete it instead of `#if 0` bracketing it. If we need to resurrect this code, we can get… | |||||
ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn, | |||||
u_char command, u_char seq, u_char *data, int data_len) | |||||
{ | |||||
struct ipmi_softc *sc = device_get_softc(dev); | |||||
struct ipmi_request *req; | |||||
u_char slave_addr = 0x52; | |||||
int error; | |||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), | |||||
IPMI_SEND_MSG, data_len + 8, 0); | |||||
req->ir_request[0] = channel; | |||||
req->ir_request[1] = slave_addr; | |||||
req->ir_request[2] = IPMI_ADDR(netfn, 0); | |||||
req->ir_request[3] = ipmi_ipmb_checksum(&req->ir_request[1], 2); | |||||
req->ir_request[4] = sc->ipmi_address; | |||||
req->ir_request[5] = IPMI_ADDR(seq, sc->ipmi_lun); | |||||
req->ir_request[6] = command; | |||||
bcopy(data, &req->ir_request[7], data_len); | |||||
temp[data_len + 7] = ipmi_ipmb_checksum(&req->ir_request[4], | |||||
data_len + 3); | |||||
ipmi_submit_driver_request(sc, req); | |||||
error = req->ir_error; | |||||
return (error); | |||||
} | |||||
static int | |||||
ipmi_handle_attn(struct ipmi_softc *sc) | |||||
{ | |||||
struct ipmi_request *req; | |||||
int error; | |||||
device_printf(sc->ipmi_dev, "BMC has a message\n"); | |||||
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), | |||||
IPMI_GET_MSG_FLAGS, 0, 1); | |||||
ipmi_submit_driver_request(sc, req); | |||||
if (req->ir_error == 0 && req->ir_compcode == 0) { | |||||
if (req->ir_reply[0] & IPMI_MSG_BUFFER_FULL) { | |||||
device_printf(sc->ipmi_dev, "message buffer full"); | |||||
} | |||||
if (req->ir_reply[0] & IPMI_WDT_PRE_TIMEOUT) { | |||||
device_printf(sc->ipmi_dev, | |||||
"watchdog about to go off"); | |||||
} | |||||
if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) { | |||||
IPMI_ALLOC_DRIVER_REQUEST(req, | |||||
IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0, | |||||
16); | |||||
device_printf(sc->ipmi_dev, "throw out message "); | |||||
dump_buf(temp, 16); | |||||
} | |||||
} | |||||
error = req->ir_error; | |||||
return (error); | |||||
} | |||||
#endif | |||||
static int | |||||
ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, | ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, | ||||
int flags, struct thread *td) | int flags, struct thread *td) | ||||
{ | { | ||||
struct ipmi_softc *sc; | struct ipmi_softc *sc; | ||||
struct ipmi_device *dev; | struct ipmi_device *dev; | ||||
struct ipmi_request *kreq; | struct ipmi_request *kreq; | ||||
struct ipmi_req *req = (struct ipmi_req *)data; | struct ipmi_req *req = (struct ipmi_req *)data; | ||||
struct ipmi_recv *recv = (struct ipmi_recv *)data; | struct ipmi_recv *recv = (struct ipmi_recv *)data; | ||||
Show All 38 Lines | #ifdef IPMICTL_SEND_COMMAND_32 | ||||
} | } | ||||
#endif | #endif | ||||
switch (cmd) { | switch (cmd) { | ||||
#ifdef IPMICTL_SEND_COMMAND_32 | #ifdef IPMICTL_SEND_COMMAND_32 | ||||
case IPMICTL_SEND_COMMAND_32: | case IPMICTL_SEND_COMMAND_32: | ||||
#endif | #endif | ||||
case IPMICTL_SEND_COMMAND: | case IPMICTL_SEND_COMMAND: | ||||
/* | |||||
* XXX: Need to add proper handling of this. | |||||
*/ | |||||
error = copyin(req->addr, &addr, sizeof(addr)); | error = copyin(req->addr, &addr, sizeof(addr)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
IPMI_LOCK(sc); | if (addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) { | ||||
/* clear out old stuff in queue of stuff done */ | |||||
Done Inline Actionsthis removal is likely unrelated and could be done separately, just a note that we are using the ipmi driver in illumos ported from FreeBSD with this part removed for *years*, so the more wide testing of this change is based on the assumption that this is removed yuri_aetern.org: this removal is likely unrelated and could be done separately, just a note that we are using… | |||||
/* XXX: This seems odd. */ | |||||
while ((kreq = TAILQ_FIRST(&dev->ipmi_completed_requests))) { | |||||
TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, | |||||
ir_link); | |||||
dev->ipmi_requests--; | |||||
ipmi_free_request(kreq); | |||||
} | |||||
IPMI_UNLOCK(sc); | |||||
kreq = ipmi_alloc_request(dev, req->msgid, | kreq = ipmi_alloc_request(dev, req->msgid, | ||||
IPMI_ADDR(req->msg.netfn, 0), req->msg.cmd, | IPMI_ADDR(req->msg.netfn, 0), req->msg.cmd, | ||||
req->msg.data_len, IPMI_MAX_RX); | req->msg.data_len, IPMI_MAX_RX); | ||||
error = copyin(req->msg.data, kreq->ir_request, | error = copyin(req->msg.data, kreq->ir_request, | ||||
req->msg.data_len); | req->msg.data_len); | ||||
if (error) { | if (error) { | ||||
ipmi_free_request(kreq); | ipmi_free_request(kreq); | ||||
return (error); | return (error); | ||||
} | } | ||||
IPMI_LOCK(sc); | IPMI_LOCK(sc); | ||||
dev->ipmi_requests++; | dev->ipmi_requests++; | ||||
error = sc->ipmi_enqueue_request(sc, kreq); | error = sc->ipmi_enqueue_request(sc, kreq); | ||||
IPMI_UNLOCK(sc); | IPMI_UNLOCK(sc); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
break; | break; | ||||
} | |||||
/* Special processing for IPMB commands */ | |||||
struct ipmi_ipmb_addr *iaddr = (struct ipmi_ipmb_addr *)&addr; | |||||
IPMI_ALLOC_DRIVER_REQUEST(kreq, IPMI_ADDR(IPMI_APP_REQUEST, 0), | |||||
IPMI_SEND_MSG, req->msg.data_len + 8, IPMI_MAX_RX); | |||||
/* Construct the SEND MSG header */ | |||||
kreq->ir_request[0] = iaddr->channel; | |||||
kreq->ir_request[1] = iaddr->slave_addr; | |||||
kreq->ir_request[2] = IPMI_ADDR(req->msg.netfn, iaddr->lun); | |||||
kreq->ir_request[3] = | |||||
ipmi_ipmb_checksum(&kreq->ir_request[1], 2); | |||||
kreq->ir_request[4] = dev->ipmi_address; | |||||
kreq->ir_request[5] = IPMI_ADDR(0, dev->ipmi_lun); | |||||
kreq->ir_request[6] = req->msg.cmd; | |||||
/* Copy the message data */ | |||||
if (req->msg.data_len > 0) { | |||||
error = copyin(req->msg.data, &kreq->ir_request[7], | |||||
req->msg.data_len); | |||||
if (error != 0) | |||||
return (error); | |||||
} | |||||
kreq->ir_request[req->msg.data_len + 7] = | |||||
ipmi_ipmb_checksum(&kreq->ir_request[4], | |||||
req->msg.data_len + 3); | |||||
error = ipmi_submit_driver_request(sc, kreq, MAX_TIMEOUT); | |||||
if (error != 0) | |||||
return (error); | |||||
kreq = ipmi_alloc_request(dev, req->msgid, | |||||
IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, | |||||
0, IPMI_MAX_RX); | |||||
kreq->ir_ipmb = true; | |||||
kreq->ir_ipmb_addr = IPMI_ADDR(req->msg.netfn, 0); | |||||
kreq->ir_ipmb_command = req->msg.cmd; | |||||
IPMI_LOCK(sc); | |||||
dev->ipmi_requests++; | |||||
error = sc->ipmi_enqueue_request(sc, kreq); | |||||
IPMI_UNLOCK(sc); | |||||
if (error != 0) | |||||
return (error); | |||||
break; | |||||
#ifdef IPMICTL_SEND_COMMAND_32 | #ifdef IPMICTL_SEND_COMMAND_32 | ||||
case IPMICTL_RECEIVE_MSG_TRUNC_32: | case IPMICTL_RECEIVE_MSG_TRUNC_32: | ||||
case IPMICTL_RECEIVE_MSG_32: | case IPMICTL_RECEIVE_MSG_32: | ||||
#endif | #endif | ||||
case IPMICTL_RECEIVE_MSG_TRUNC: | case IPMICTL_RECEIVE_MSG_TRUNC: | ||||
case IPMICTL_RECEIVE_MSG: | case IPMICTL_RECEIVE_MSG: | ||||
error = copyin(recv->addr, &addr, sizeof(addr)); | error = copyin(recv->addr, &addr, sizeof(addr)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
IPMI_LOCK(sc); | IPMI_LOCK(sc); | ||||
kreq = TAILQ_FIRST(&dev->ipmi_completed_requests); | kreq = TAILQ_FIRST(&dev->ipmi_completed_requests); | ||||
if (kreq == NULL) { | if (kreq == NULL) { | ||||
IPMI_UNLOCK(sc); | IPMI_UNLOCK(sc); | ||||
return (EAGAIN); | return (EAGAIN); | ||||
} | } | ||||
addr.channel = IPMI_BMC_CHANNEL; | if (kreq->ir_error != 0) { | ||||
/* XXX */ | |||||
recv->recv_type = IPMI_RESPONSE_RECV_TYPE; | |||||
recv->msgid = kreq->ir_msgid; | |||||
recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2; | |||||
recv->msg.cmd = kreq->ir_command; | |||||
error = kreq->ir_error; | |||||
if (error) { | |||||
TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, | TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, | ||||
ir_link); | ir_link); | ||||
dev->ipmi_requests--; | dev->ipmi_requests--; | ||||
IPMI_UNLOCK(sc); | IPMI_UNLOCK(sc); | ||||
ipmi_free_request(kreq); | ipmi_free_request(kreq); | ||||
return (error); | return (kreq->ir_error); | ||||
vangyzenUnsubmitted Not Done Inline ActionsThis uses kreq after freeing it. Coverity CID 1490456 vangyzen: This uses `kreq` after freeing it. Coverity CID 1490456 | |||||
philipUnsubmitted Not Done Inline ActionsGood catch! Thanks. I'll commit this fix. philip: Good catch! Thanks. I'll commit this fix. | |||||
} | } | ||||
recv->recv_type = IPMI_RESPONSE_RECV_TYPE; | |||||
recv->msgid = kreq->ir_msgid; | |||||
if (kreq->ir_ipmb) { | |||||
addr.channel = IPMI_IPMB_CHANNEL; | |||||
recv->msg.netfn = | |||||
IPMI_REPLY_ADDR(kreq->ir_ipmb_addr) >> 2; | |||||
recv->msg.cmd = kreq->ir_ipmb_command; | |||||
/* Get the compcode of response */ | |||||
kreq->ir_compcode = kreq->ir_reply[6]; | |||||
/* Move the reply head past response header */ | |||||
kreq->ir_reply += 7; | |||||
len = kreq->ir_replylen - 7; | |||||
} else { | |||||
addr.channel = IPMI_BMC_CHANNEL; | |||||
recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2; | |||||
recv->msg.cmd = kreq->ir_command; | |||||
len = kreq->ir_replylen + 1; | len = kreq->ir_replylen + 1; | ||||
} | |||||
if (recv->msg.data_len < len && | if (recv->msg.data_len < len && | ||||
(cmd == IPMICTL_RECEIVE_MSG | (cmd == IPMICTL_RECEIVE_MSG | ||||
#ifdef IPMICTL_RECEIVE_MSG_32 | #ifdef IPMICTL_RECEIVE_MSG_32 | ||||
|| cmd == IPMICTL_RECEIVE_MSG_32 | || cmd == IPMICTL_RECEIVE_MSG_32 | ||||
#endif | #endif | ||||
)) { | )) { | ||||
IPMI_UNLOCK(sc); | IPMI_UNLOCK(sc); | ||||
return (EMSGSIZE); | return (EMSGSIZE); | ||||
} | } | ||||
TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link); | TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link); | ||||
dev->ipmi_requests--; | dev->ipmi_requests--; | ||||
IPMI_UNLOCK(sc); | IPMI_UNLOCK(sc); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Request management. | * Request management. | ||||
*/ | */ | ||||
static __inline void | __inline void | ||||
ipmi_init_request(struct ipmi_request *req, struct ipmi_device *dev, long msgid, | ipmi_init_request(struct ipmi_request *req, struct ipmi_device *dev, long msgid, | ||||
uint8_t addr, uint8_t command, size_t requestlen, size_t replylen) | uint8_t addr, uint8_t command, size_t requestlen, size_t replylen) | ||||
{ | { | ||||
req->ir_owner = dev; | req->ir_owner = dev; | ||||
req->ir_msgid = msgid; | req->ir_msgid = msgid; | ||||
req->ir_addr = addr; | req->ir_addr = addr; | ||||
req->ir_command = command; | req->ir_command = command; | ||||
▲ Show 20 Lines • Show All 585 Lines • Show Last 20 Lines |
Just delete it instead of #if 0 bracketing it. If we need to resurrect this code, we can get it back from Git.