Lines Matching +full:ssif +full:- +full:bmc

1 // SPDX-License-Identifier: GPL-2.0-only
3 * The driver for BMC side of SSIF interface
22 #define DEVICE_NAME "ipmi-ssif-host"
43 * IPMI 2.0 Spec, section 12.7 SSIF Timing,
44 * Request-to-Response Time is T6max(250ms) - T1max(20ms) - 3ms = 227ms
59 * SSIF internal states:
82 /* ssif bmc spinlock */
90 /* Flag to identify a Multi-part Read Transaction */
95 /* Block Number of a Multi-part Read Transaction */
101 /* Buffer for SSIF Transaction part*/
109 return container_of(file->private_data, struct ssif_bmc_ctx, miscdev); in to_ssif_bmc()
132 /* Handle SSIF message that will be sent to user */
140 spin_lock_irqsave(&ssif_bmc->lock, flags); in ssif_bmc_read()
141 while (!ssif_bmc->request_available) { in ssif_bmc_read()
142 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in ssif_bmc_read()
143 if (file->f_flags & O_NONBLOCK) in ssif_bmc_read()
144 return -EAGAIN; in ssif_bmc_read()
145 ret = wait_event_interruptible(ssif_bmc->wait_queue, in ssif_bmc_read()
146 ssif_bmc->request_available); in ssif_bmc_read()
149 spin_lock_irqsave(&ssif_bmc->lock, flags); in ssif_bmc_read()
153 sizeof_field(struct ipmi_ssif_msg, len) + ssif_bmc->request.len, in ssif_bmc_read()
155 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in ssif_bmc_read()
156 ret = -EINVAL; in ssif_bmc_read()
159 sizeof_field(struct ipmi_ssif_msg, len) + ssif_bmc->request.len, in ssif_bmc_read()
161 memcpy(&msg, &ssif_bmc->request, count); in ssif_bmc_read()
162 ssif_bmc->request_available = false; in ssif_bmc_read()
163 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in ssif_bmc_read()
171 /* Handle SSIF message that is written by user */
182 return -EINVAL; in ssif_bmc_write()
185 return -EFAULT; in ssif_bmc_write()
189 return -EINVAL; in ssif_bmc_write()
191 spin_lock_irqsave(&ssif_bmc->lock, flags); in ssif_bmc_write()
192 while (ssif_bmc->response_in_progress) { in ssif_bmc_write()
193 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in ssif_bmc_write()
194 if (file->f_flags & O_NONBLOCK) in ssif_bmc_write()
195 return -EAGAIN; in ssif_bmc_write()
196 ret = wait_event_interruptible(ssif_bmc->wait_queue, in ssif_bmc_write()
197 !ssif_bmc->response_in_progress); in ssif_bmc_write()
200 spin_lock_irqsave(&ssif_bmc->lock, flags); in ssif_bmc_write()
206 * Return -EINVAL if the response is aborted in ssif_bmc_write()
208 ret = (ssif_bmc->response_timer_inited) ? 0 : -EINVAL; in ssif_bmc_write()
212 del_timer(&ssif_bmc->response_timer); in ssif_bmc_write()
213 ssif_bmc->response_timer_inited = false; in ssif_bmc_write()
215 memcpy(&ssif_bmc->response, &msg, count); in ssif_bmc_write()
216 ssif_bmc->is_singlepart_read = (msg.len <= MAX_PAYLOAD_PER_TRANSACTION); in ssif_bmc_write()
218 ssif_bmc->response_in_progress = true; in ssif_bmc_write()
221 ssif_bmc->busy = false; in ssif_bmc_write()
224 memset(&ssif_bmc->request, 0, sizeof(struct ipmi_ssif_msg)); in ssif_bmc_write()
226 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in ssif_bmc_write()
236 spin_lock_irq(&ssif_bmc->lock); in ssif_bmc_open()
237 if (!ssif_bmc->running) in ssif_bmc_open()
238 ssif_bmc->running = 1; in ssif_bmc_open()
240 ret = -EBUSY; in ssif_bmc_open()
241 spin_unlock_irq(&ssif_bmc->lock); in ssif_bmc_open()
251 poll_wait(file, &ssif_bmc->wait_queue, wait); in ssif_bmc_poll()
253 spin_lock_irq(&ssif_bmc->lock); in ssif_bmc_poll()
255 if (ssif_bmc->request_available) in ssif_bmc_poll()
258 spin_unlock_irq(&ssif_bmc->lock); in ssif_bmc_poll()
267 spin_lock_irq(&ssif_bmc->lock); in ssif_bmc_release()
268 ssif_bmc->running = 0; in ssif_bmc_release()
269 spin_unlock_irq(&ssif_bmc->lock); in ssif_bmc_release()
286 /* Called with ssif_bmc->lock held. */
290 ssif_bmc->response.len = 0; in complete_response()
291 ssif_bmc->response_in_progress = false; in complete_response()
292 ssif_bmc->nbytes_processed = 0; in complete_response()
293 ssif_bmc->remain_len = 0; in complete_response()
294 ssif_bmc->busy = false; in complete_response()
295 memset(&ssif_bmc->part_buf, 0, sizeof(struct ssif_part_buffer)); in complete_response()
296 wake_up_all(&ssif_bmc->wait_queue); in complete_response()
304 spin_lock_irqsave(&ssif_bmc->lock, flags); in response_timeout()
307 if (!ssif_bmc->response_in_progress) { in response_timeout()
309 ssif_bmc->busy = false; in response_timeout()
310 ssif_bmc->response_timer_inited = false; in response_timeout()
312 ssif_bmc->aborting = true; in response_timeout()
315 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in response_timeout()
318 /* Called with ssif_bmc->lock held. */
322 ssif_bmc->busy = true; in handle_request()
324 ssif_bmc->request_available = true; in handle_request()
326 memset(&ssif_bmc->response, 0, sizeof(struct ipmi_ssif_msg)); in handle_request()
328 wake_up_all(&ssif_bmc->wait_queue); in handle_request()
331 if (!ssif_bmc->response_timer_inited) { in handle_request()
332 timer_setup(&ssif_bmc->response_timer, response_timeout, 0); in handle_request()
333 ssif_bmc->response_timer_inited = true; in handle_request()
335 mod_timer(&ssif_bmc->response_timer, jiffies + msecs_to_jiffies(RESPONSE_TIMEOUT)); in handle_request()
340 u8 addr = part->address; in calculate_response_part_pec()
342 /* PEC - Start Read Address */ in calculate_response_part_pec()
343 part->pec = i2c_smbus_pec(0, &addr, 1); in calculate_response_part_pec()
344 /* PEC - SSIF Command */ in calculate_response_part_pec()
345 part->pec = i2c_smbus_pec(part->pec, &part->smbus_cmd, 1); in calculate_response_part_pec()
346 /* PEC - Restart Write Address */ in calculate_response_part_pec()
348 part->pec = i2c_smbus_pec(part->pec, &addr, 1); in calculate_response_part_pec()
349 part->pec = i2c_smbus_pec(part->pec, &part->length, 1); in calculate_response_part_pec()
350 if (part->length) in calculate_response_part_pec()
351 part->pec = i2c_smbus_pec(part->pec, part->payload, part->length); in calculate_response_part_pec()
356 struct ssif_part_buffer *part = &ssif_bmc->part_buf; in set_singlepart_response_buffer()
358 part->address = GET_8BIT_ADDR(ssif_bmc->client->addr); in set_singlepart_response_buffer()
359 part->length = (u8)ssif_bmc->response.len; in set_singlepart_response_buffer()
362 memset(part->payload + part->length, 0, MAX_PAYLOAD_PER_TRANSACTION - part->length); in set_singlepart_response_buffer()
363 memcpy(&part->payload[0], &ssif_bmc->response.payload[0], part->length); in set_singlepart_response_buffer()
368 struct ssif_part_buffer *part = &ssif_bmc->part_buf; in set_multipart_response_buffer()
371 part->address = GET_8BIT_ADDR(ssif_bmc->client->addr); in set_multipart_response_buffer()
372 switch (part->smbus_cmd) { in set_multipart_response_buffer()
379 ssif_bmc->nbytes_processed = 0; in set_multipart_response_buffer()
380 ssif_bmc->block_num = 0; in set_multipart_response_buffer()
381 part->length = MAX_PAYLOAD_PER_TRANSACTION; in set_multipart_response_buffer()
383 ssif_bmc->remain_len = ssif_bmc->response.len - part_len; in set_multipart_response_buffer()
385 part->payload[0] = 0x00; /* Start Flag */ in set_multipart_response_buffer()
386 part->payload[1] = 0x01; /* Start Flag */ in set_multipart_response_buffer()
388 memcpy(&part->payload[2], &ssif_bmc->response.payload[0], part_len); in set_multipart_response_buffer()
396 if (ssif_bmc->remain_len <= MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION) { in set_multipart_response_buffer()
405 memset(&part->payload[0], 0, MAX_PAYLOAD_PER_TRANSACTION); in set_multipart_response_buffer()
406 part->length = ssif_bmc->remain_len + 1; in set_multipart_response_buffer()
407 part_len = ssif_bmc->remain_len; in set_multipart_response_buffer()
408 ssif_bmc->block_num = 0xFF; in set_multipart_response_buffer()
409 part->payload[0] = ssif_bmc->block_num; in set_multipart_response_buffer()
417 part->length = MAX_PAYLOAD_PER_TRANSACTION; in set_multipart_response_buffer()
419 part->payload[0] = ssif_bmc->block_num; in set_multipart_response_buffer()
420 ssif_bmc->block_num++; in set_multipart_response_buffer()
423 ssif_bmc->remain_len -= part_len; in set_multipart_response_buffer()
424 memcpy(&part->payload[1], ssif_bmc->response.payload + ssif_bmc->nbytes_processed, in set_multipart_response_buffer()
430 dev_err(&ssif_bmc->client->dev, "%s: Unexpected SMBus command 0x%x\n", in set_multipart_response_buffer()
431 __func__, part->smbus_cmd); in set_multipart_response_buffer()
435 ssif_bmc->nbytes_processed += part_len; in set_multipart_response_buffer()
462 struct ssif_part_buffer *part = &ssif_bmc->part_buf; in handle_read_processed()
465 if (part->index < part->length) in handle_read_processed()
466 *val = part->payload[part->index]; in handle_read_processed()
467 else if (part->index == part->length && ssif_bmc->pec_support) in handle_read_processed()
468 *val = part->pec; in handle_read_processed()
472 part->index++; in handle_read_processed()
482 if (ssif_bmc->msg_idx < 1 || ssif_bmc->msg_idx > MAX_TRANSACTION) in handle_write_received()
485 if (ssif_bmc->msg_idx == 1) { in handle_write_received()
486 ssif_bmc->part_buf.length = *val; in handle_write_received()
487 ssif_bmc->part_buf.index = 0; in handle_write_received()
489 ssif_bmc->part_buf.payload[ssif_bmc->part_buf.index++] = *val; in handle_write_received()
492 ssif_bmc->msg_idx++; in handle_write_received()
497 struct ssif_part_buffer *part = &ssif_bmc->part_buf; in validate_request_part()
502 if (part->index == part->length) { in validate_request_part()
504 ssif_bmc->pec_support = false; in validate_request_part()
509 if (part->index != part->length + 1) { in validate_request_part()
515 ssif_bmc->pec_support = true; in validate_request_part()
516 part->pec = part->payload[part->length]; in validate_request_part()
517 addr = GET_8BIT_ADDR(ssif_bmc->client->addr); in validate_request_part()
519 cpec = i2c_smbus_pec(cpec, &part->smbus_cmd, 1); in validate_request_part()
520 cpec = i2c_smbus_pec(cpec, &part->length, 1); in validate_request_part()
523 * (byte count) in the Write-Block protocol to be zero. in validate_request_part()
525 * transaction in the sequence carry 32-byte and have in validate_request_part()
530 if (part->length) in validate_request_part()
531 cpec = i2c_smbus_pec(cpec, part->payload, part->length); in validate_request_part()
533 if (cpec != part->pec) in validate_request_part()
542 struct ssif_part_buffer *part = &ssif_bmc->part_buf; in process_request_part()
545 switch (part->smbus_cmd) { in process_request_part()
548 ssif_bmc->request.len = part->length; in process_request_part()
549 memcpy(ssif_bmc->request.payload, part->payload, part->length); in process_request_part()
553 ssif_bmc->request.len = 0; in process_request_part()
558 len = ssif_bmc->request.len + part->length; in process_request_part()
561 dev_warn(&ssif_bmc->client->dev, in process_request_part()
564 ssif_bmc->aborting = true; in process_request_part()
566 memcpy(ssif_bmc->request.payload + ssif_bmc->request.len, in process_request_part()
567 part->payload, part->length); in process_request_part()
568 ssif_bmc->request.len += part->length; in process_request_part()
573 dev_err(&ssif_bmc->client->dev, "%s: Unexpected SMBus command 0x%x\n", in process_request_part()
574 __func__, part->smbus_cmd); in process_request_part()
581 /* SMBUS command can vary (single or multi-part) */ in process_smbus_cmd()
582 ssif_bmc->part_buf.smbus_cmd = *val; in process_smbus_cmd()
583 ssif_bmc->msg_idx = 1; in process_smbus_cmd()
584 memset(&ssif_bmc->part_buf.payload[0], 0, MAX_PAYLOAD_PER_TRANSACTION); in process_smbus_cmd()
588 * The response maybe not come in-time, causing host SSIF driver in process_smbus_cmd()
592 if (ssif_bmc->response_in_progress) in process_smbus_cmd()
596 if (ssif_bmc->aborting) in process_smbus_cmd()
597 ssif_bmc->aborting = false; in process_smbus_cmd()
603 if (ssif_bmc->state == SSIF_READY || in on_read_requested_event()
604 ssif_bmc->state == SSIF_START || in on_read_requested_event()
605 ssif_bmc->state == SSIF_REQ_RECVING || in on_read_requested_event()
606 ssif_bmc->state == SSIF_RES_SENDING) { in on_read_requested_event()
607 dev_warn(&ssif_bmc->client->dev, in on_read_requested_event()
609 __func__, state_to_string(ssif_bmc->state)); in on_read_requested_event()
610 ssif_bmc->state = SSIF_ABORTING; in on_read_requested_event()
614 } else if (ssif_bmc->state == SSIF_SMBUS_CMD) { in on_read_requested_event()
615 if (!supported_read_cmd(ssif_bmc->part_buf.smbus_cmd)) { in on_read_requested_event()
616 dev_warn(&ssif_bmc->client->dev, "Warn: Unknown SMBus read command=0x%x", in on_read_requested_event()
617 ssif_bmc->part_buf.smbus_cmd); in on_read_requested_event()
618 ssif_bmc->aborting = true; in on_read_requested_event()
621 if (ssif_bmc->aborting) in on_read_requested_event()
622 ssif_bmc->state = SSIF_ABORTING; in on_read_requested_event()
624 ssif_bmc->state = SSIF_RES_SENDING; in on_read_requested_event()
627 ssif_bmc->msg_idx = 0; in on_read_requested_event()
630 if (!ssif_bmc->response_in_progress || ssif_bmc->state == SSIF_ABORTING) { in on_read_requested_event()
635 if (ssif_bmc->is_singlepart_read) in on_read_requested_event()
640 calculate_response_part_pec(&ssif_bmc->part_buf); in on_read_requested_event()
641 ssif_bmc->part_buf.index = 0; in on_read_requested_event()
642 *val = ssif_bmc->part_buf.length; in on_read_requested_event()
647 if (ssif_bmc->state == SSIF_READY || in on_read_processed_event()
648 ssif_bmc->state == SSIF_START || in on_read_processed_event()
649 ssif_bmc->state == SSIF_REQ_RECVING || in on_read_processed_event()
650 ssif_bmc->state == SSIF_SMBUS_CMD) { in on_read_processed_event()
651 dev_warn(&ssif_bmc->client->dev, in on_read_processed_event()
653 __func__, state_to_string(ssif_bmc->state)); in on_read_processed_event()
654 ssif_bmc->state = SSIF_ABORTING; in on_read_processed_event()
660 if (!ssif_bmc->response_in_progress || ssif_bmc->state == SSIF_ABORTING) { in on_read_processed_event()
670 if (ssif_bmc->state == SSIF_READY || ssif_bmc->state == SSIF_SMBUS_CMD) { in on_write_requested_event()
671 ssif_bmc->state = SSIF_START; in on_write_requested_event()
673 } else if (ssif_bmc->state == SSIF_START || in on_write_requested_event()
674 ssif_bmc->state == SSIF_REQ_RECVING || in on_write_requested_event()
675 ssif_bmc->state == SSIF_RES_SENDING) { in on_write_requested_event()
676 dev_warn(&ssif_bmc->client->dev, in on_write_requested_event()
678 __func__, state_to_string(ssif_bmc->state)); in on_write_requested_event()
679 ssif_bmc->state = SSIF_ABORTING; in on_write_requested_event()
683 ssif_bmc->msg_idx = 0; in on_write_requested_event()
684 ssif_bmc->part_buf.address = *val; in on_write_requested_event()
689 if (ssif_bmc->state == SSIF_READY || in on_write_received_event()
690 ssif_bmc->state == SSIF_RES_SENDING) { in on_write_received_event()
691 dev_warn(&ssif_bmc->client->dev, in on_write_received_event()
693 __func__, state_to_string(ssif_bmc->state)); in on_write_received_event()
694 ssif_bmc->state = SSIF_ABORTING; in on_write_received_event()
696 } else if (ssif_bmc->state == SSIF_START) { in on_write_received_event()
697 ssif_bmc->state = SSIF_SMBUS_CMD; in on_write_received_event()
699 } else if (ssif_bmc->state == SSIF_SMBUS_CMD) { in on_write_received_event()
700 if (!supported_write_cmd(ssif_bmc->part_buf.smbus_cmd)) { in on_write_received_event()
701 dev_warn(&ssif_bmc->client->dev, "Warn: Unknown SMBus write command=0x%x", in on_write_received_event()
702 ssif_bmc->part_buf.smbus_cmd); in on_write_received_event()
703 ssif_bmc->aborting = true; in on_write_received_event()
706 if (ssif_bmc->aborting) in on_write_received_event()
707 ssif_bmc->state = SSIF_ABORTING; in on_write_received_event()
709 ssif_bmc->state = SSIF_REQ_RECVING; in on_write_received_event()
713 if (ssif_bmc->state == SSIF_REQ_RECVING) in on_write_received_event()
715 else if (ssif_bmc->state == SSIF_SMBUS_CMD) in on_write_received_event()
721 if (ssif_bmc->state == SSIF_READY || in on_stop_event()
722 ssif_bmc->state == SSIF_START || in on_stop_event()
723 ssif_bmc->state == SSIF_SMBUS_CMD || in on_stop_event()
724 ssif_bmc->state == SSIF_ABORTING) { in on_stop_event()
725 dev_warn(&ssif_bmc->client->dev, in on_stop_event()
727 __func__, state_to_string(ssif_bmc->state)); in on_stop_event()
728 ssif_bmc->state = SSIF_READY; in on_stop_event()
730 } else if (ssif_bmc->state == SSIF_REQ_RECVING) { in on_stop_event()
733 if (ssif_bmc->part_buf.smbus_cmd == SSIF_IPMI_SINGLEPART_WRITE || in on_stop_event()
734 ssif_bmc->part_buf.smbus_cmd == SSIF_IPMI_MULTIPART_WRITE_END) in on_stop_event()
736 ssif_bmc->state = SSIF_READY; in on_stop_event()
739 * A BMC that receives an invalid request drop the data for the write in on_stop_event()
743 dev_err(&ssif_bmc->client->dev, "Error: invalid pec\n"); in on_stop_event()
744 ssif_bmc->aborting = true; in on_stop_event()
746 } else if (ssif_bmc->state == SSIF_RES_SENDING) { in on_stop_event()
747 if (ssif_bmc->is_singlepart_read || ssif_bmc->block_num == 0xFF) in on_stop_event()
750 ssif_bmc->state = SSIF_READY; in on_stop_event()
754 ssif_bmc->msg_idx = 0; in on_stop_event()
766 spin_lock_irqsave(&ssif_bmc->lock, flags); in ssif_bmc_cb()
790 dev_warn(&ssif_bmc->client->dev, "Warn: Unknown i2c slave event\n"); in ssif_bmc_cb()
794 if (!ssif_bmc->aborting && ssif_bmc->busy) in ssif_bmc_cb()
795 ret = -EBUSY; in ssif_bmc_cb()
797 spin_unlock_irqrestore(&ssif_bmc->lock, flags); in ssif_bmc_cb()
807 ssif_bmc = devm_kzalloc(&client->dev, sizeof(*ssif_bmc), GFP_KERNEL); in ssif_bmc_probe()
809 return -ENOMEM; in ssif_bmc_probe()
811 spin_lock_init(&ssif_bmc->lock); in ssif_bmc_probe()
813 init_waitqueue_head(&ssif_bmc->wait_queue); in ssif_bmc_probe()
814 ssif_bmc->request_available = false; in ssif_bmc_probe()
815 ssif_bmc->response_in_progress = false; in ssif_bmc_probe()
816 ssif_bmc->busy = false; in ssif_bmc_probe()
817 ssif_bmc->response_timer_inited = false; in ssif_bmc_probe()
820 ssif_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; in ssif_bmc_probe()
821 ssif_bmc->miscdev.name = DEVICE_NAME; in ssif_bmc_probe()
822 ssif_bmc->miscdev.fops = &ssif_bmc_fops; in ssif_bmc_probe()
823 ssif_bmc->miscdev.parent = &client->dev; in ssif_bmc_probe()
824 ret = misc_register(&ssif_bmc->miscdev); in ssif_bmc_probe()
828 ssif_bmc->client = client; in ssif_bmc_probe()
829 ssif_bmc->client->flags |= I2C_CLIENT_SLAVE; in ssif_bmc_probe()
835 misc_deregister(&ssif_bmc->miscdev); in ssif_bmc_probe()
845 misc_deregister(&ssif_bmc->miscdev); in ssif_bmc_remove()
849 { .compatible = "ssif-bmc" },
874 MODULE_DESCRIPTION("Linux device driver of the BMC IPMI SSIF interface.");