enum ep_partner_status fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid) { enum ep_partner_status status; if (fjes_hw_epid_is_shared(hw->hw_info.share, epid)) { if (fjes_hw_epid_is_stop_requested(hw, epid)) { status = EP_PARTNER_WAITING; } else { if (fjes_hw_epid_is_stop_process_done(hw, epid)) status = EP_PARTNER_COMPLETE; else status = EP_PARTNER_SHARED; } } else { status = EP_PARTNER_UNSHARE; } return status; }
int fjes_hw_wait_epstop(struct fjes_hw *hw) { enum ep_partner_status status; union ep_buffer_info *info; int wait_time = 0; int epidx; while (hw->hw_info.buffer_unshare_reserve_bit && (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) { for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; status = fjes_hw_epid_is_shared(hw->hw_info.share, epidx); info = hw->ep_shm_info[epidx].rx.info; if ((!status || (info->v1i.rx_status & FJES_RX_STOP_REQ_DONE)) && test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit)) { clear_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } } msleep(100); wait_time += 100; } for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit)) clear_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } return (wait_time < FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000) ? 0 : -EBUSY; }
static int fjes_dbg_status_show(struct seq_file *m, void *v) { struct fjes_adapter *adapter = m->private; struct fjes_hw *hw = &adapter->hw; int max_epid = hw->max_epid; int my_epid = hw->my_epid; int epidx; seq_puts(m, "EPID\tSTATUS SAME_ZONE CONNECTED\n"); for (epidx = 0; epidx < max_epid; epidx++) { if (epidx == my_epid) { seq_printf(m, "ep%d\t%-16c %-16c %-16c\n", epidx, '-', '-', '-'); } else { seq_printf(m, "ep%d\t%-16s %-16c %-16c\n", epidx, ep_status_string[fjes_hw_get_partner_ep_status(hw, epidx)], fjes_hw_epid_is_same_zone(hw, epidx) ? 'Y' : 'N', fjes_hw_epid_is_shared(hw->hw_info.share, epidx) ? 'Y' : 'N'); } } return 0; }
static void fjes_watch_unshare_task(struct work_struct *work) { struct fjes_adapter *adapter = container_of(work, struct fjes_adapter, unshare_watch_task); struct net_device *netdev = adapter->netdev; struct fjes_hw *hw = &adapter->hw; int unshare_watch, unshare_reserve; int max_epid, my_epid, epidx; int stop_req, stop_req_done; ulong unshare_watch_bitmask; unsigned long flags; int wait_time = 0; int is_shared; int ret; my_epid = hw->my_epid; max_epid = hw->max_epid; unshare_watch_bitmask = adapter->unshare_watch_bitmask; adapter->unshare_watch_bitmask = 0; while ((unshare_watch_bitmask || hw->txrx_stop_req_bit) && (wait_time < 3000)) { for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; is_shared = fjes_hw_epid_is_shared(hw->hw_info.share, epidx); stop_req = test_bit(epidx, &hw->txrx_stop_req_bit); stop_req_done = hw->ep_shm_info[epidx].rx.info->v1i.rx_status & FJES_RX_STOP_REQ_DONE; unshare_watch = test_bit(epidx, &unshare_watch_bitmask); unshare_reserve = test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); if ((!stop_req || (is_shared && (!is_shared || !stop_req_done))) && (is_shared || !unshare_watch || !unshare_reserve)) continue; mutex_lock(&hw->hw_info.lock); ret = fjes_hw_unregister_buff_addr(hw, epidx); switch (ret) { case 0: break; case -ENOMSG: case -EBUSY: default: if (!work_pending( &adapter->force_close_task)) { adapter->force_reset = true; schedule_work( &adapter->force_close_task); } break; } mutex_unlock(&hw->hw_info.lock); hw->ep_shm_info[epidx].ep_stats .com_unregist_buf_exec += 1; spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &unshare_watch_bitmask); clear_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } msleep(100); wait_time += 100; } if (hw->hw_info.buffer_unshare_reserve_bit) { for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; if (test_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit)) { mutex_lock(&hw->hw_info.lock); ret = fjes_hw_unregister_buff_addr(hw, epidx); switch (ret) { case 0: break; case -ENOMSG: case -EBUSY: default: if (!work_pending( &adapter->force_close_task)) { adapter->force_reset = true; schedule_work( &adapter->force_close_task); } break; } mutex_unlock(&hw->hw_info.lock); hw->ep_shm_info[epidx].ep_stats .com_unregist_buf_exec += 1; spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf( &hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(epidx, &hw->txrx_stop_req_bit); clear_bit(epidx, &unshare_watch_bitmask); clear_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } if (test_bit(epidx, &unshare_watch_bitmask)) { spin_lock_irqsave(&hw->rx_status_lock, flags); hw->ep_shm_info[epidx].tx.info->v1i.rx_status &= ~FJES_RX_STOP_REQ_DONE; spin_unlock_irqrestore(&hw->rx_status_lock, flags); } } } }