void fjes_hw_raise_epstop(struct fjes_hw *hw) { enum ep_partner_status status; int epidx; for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; status = fjes_hw_get_partner_ep_status(hw, epidx); switch (status) { case EP_PARTNER_SHARED: fjes_hw_raise_interrupt(hw, epidx, REG_ICTL_MASK_TXRX_STOP_REQ); break; default: break; } set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); set_bit(epidx, &hw->txrx_stop_req_bit); hw->ep_shm_info[epidx].tx.info->v1i.rx_status |= FJES_RX_STOP_REQ_REQUEST; } }
static void fjes_raise_intr_rxdata_task(struct work_struct *work) { struct fjes_adapter *adapter = container_of(work, struct fjes_adapter, raise_intr_rxdata_task); struct fjes_hw *hw = &adapter->hw; enum ep_partner_status pstatus; int max_epid, my_epid, epid; my_epid = hw->my_epid; max_epid = hw->max_epid; for (epid = 0; epid < max_epid; epid++) hw->ep_shm_info[epid].tx_status_work = 0; for (epid = 0; epid < max_epid; epid++) { if (epid == my_epid) continue; pstatus = fjes_hw_get_partner_ep_status(hw, epid); if (pstatus == EP_PARTNER_SHARED) { hw->ep_shm_info[epid].tx_status_work = hw->ep_shm_info[epid].tx.info->v1i.tx_status; if (hw->ep_shm_info[epid].tx_status_work == FJES_TX_DELAY_SEND_PENDING) { hw->ep_shm_info[epid].tx.info->v1i.tx_status = FJES_TX_DELAY_SEND_NONE; } } } for (epid = 0; epid < max_epid; epid++) { if (epid == my_epid) continue; pstatus = fjes_hw_get_partner_ep_status(hw, epid); if ((hw->ep_shm_info[epid].tx_status_work == FJES_TX_DELAY_SEND_PENDING) && (pstatus == EP_PARTNER_SHARED) && !(hw->ep_shm_info[epid].rx.info->v1i.rx_status & FJES_RX_POLL_WORK)) { fjes_hw_raise_interrupt(hw, epid, REG_ICTL_MASK_RX_DATA); hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1; } } usleep_range(500, 1000); }
static void fjes_hw_update_zone_task(struct work_struct *work) { struct fjes_hw *hw = container_of(work, struct fjes_hw, update_zone_task); struct my_s {u8 es_status; u8 zone; } *info; union fjes_device_command_res *res_buf; enum ep_partner_status pstatus; struct fjes_adapter *adapter; struct net_device *netdev; ulong unshare_bit = 0; ulong share_bit = 0; ulong irq_bit = 0; int epidx; int ret; adapter = (struct fjes_adapter *)hw->back; netdev = adapter->netdev; res_buf = hw->hw_info.res_buf; info = (struct my_s *)&res_buf->info.info; mutex_lock(&hw->hw_info.lock); ret = fjes_hw_request_info(hw); switch (ret) { case -ENOMSG: case -EBUSY: default: if (!work_pending(&adapter->force_close_task)) { adapter->force_reset = true; schedule_work(&adapter->force_close_task); } break; case 0: for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) { hw->ep_shm_info[epidx].es_status = info[epidx].es_status; hw->ep_shm_info[epidx].zone = info[epidx].zone; continue; } pstatus = fjes_hw_get_partner_ep_status(hw, epidx); switch (pstatus) { case EP_PARTNER_UNSHARE: default: if ((info[epidx].zone != FJES_ZONING_ZONE_TYPE_NONE) && (info[epidx].es_status == FJES_ZONING_STATUS_ENABLE) && (info[epidx].zone == info[hw->my_epid].zone)) set_bit(epidx, &share_bit); else set_bit(epidx, &unshare_bit); break; case EP_PARTNER_COMPLETE: case EP_PARTNER_WAITING: if ((info[epidx].zone == FJES_ZONING_ZONE_TYPE_NONE) || (info[epidx].es_status != FJES_ZONING_STATUS_ENABLE) || (info[epidx].zone != info[hw->my_epid].zone)) { set_bit(epidx, &adapter->unshare_watch_bitmask); set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } break; case EP_PARTNER_SHARED: if ((info[epidx].zone == FJES_ZONING_ZONE_TYPE_NONE) || (info[epidx].es_status != FJES_ZONING_STATUS_ENABLE) || (info[epidx].zone != info[hw->my_epid].zone)) set_bit(epidx, &irq_bit); break; } hw->ep_shm_info[epidx].es_status = info[epidx].es_status; hw->ep_shm_info[epidx].zone = info[epidx].zone; } break; } mutex_unlock(&hw->hw_info.lock); for (epidx = 0; epidx < hw->max_epid; epidx++) { if (epidx == hw->my_epid) continue; if (test_bit(epidx, &share_bit)) { fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); mutex_lock(&hw->hw_info.lock); ret = fjes_hw_register_buff_addr( hw, epidx, &hw->ep_shm_info[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); } if (test_bit(epidx, &unshare_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); if (ret == 0) fjes_hw_setup_epbuf( &hw->ep_shm_info[epidx].tx, netdev->dev_addr, netdev->mtu); } if (test_bit(epidx, &irq_bit)) { fjes_hw_raise_interrupt(hw, epidx, REG_ICTL_MASK_TXRX_STOP_REQ); set_bit(epidx, &hw->txrx_stop_req_bit); hw->ep_shm_info[epidx].tx. info->v1i.rx_status |= FJES_RX_STOP_REQ_REQUEST; set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); } } if (irq_bit || adapter->unshare_watch_bitmask) { if (!work_pending(&adapter->unshare_watch_task)) queue_work(adapter->control_wq, &adapter->unshare_watch_task); } }
static int fjes_setup_resources(struct fjes_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ep_share_mem_info *buf_pair; struct fjes_hw *hw = &adapter->hw; unsigned long flags; int result; int epidx; mutex_lock(&hw->hw_info.lock); result = fjes_hw_request_info(hw); switch (result) { case 0: for (epidx = 0; epidx < hw->max_epid; epidx++) { hw->ep_shm_info[epidx].es_status = hw->hw_info.res_buf->info.info[epidx].es_status; hw->ep_shm_info[epidx].zone = hw->hw_info.res_buf->info.info[epidx].zone; } break; default: case -ENOMSG: case -EBUSY: adapter->force_reset = true; mutex_unlock(&hw->hw_info.lock); return result; } mutex_unlock(&hw->hw_info.lock); for (epidx = 0; epidx < (hw->max_epid); epidx++) { if ((epidx != hw->my_epid) && (hw->ep_shm_info[epidx].es_status == FJES_ZONING_STATUS_ENABLE)) { fjes_hw_raise_interrupt(hw, epidx, REG_ICTL_MASK_INFO_UPDATE); hw->ep_shm_info[epidx].ep_stats .send_intr_zoneupdate += 1; } } msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid); for (epidx = 0; epidx < (hw->max_epid); epidx++) { if (epidx == hw->my_epid) continue; buf_pair = &hw->ep_shm_info[epidx]; spin_lock_irqsave(&hw->rx_status_lock, flags); fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr, netdev->mtu); spin_unlock_irqrestore(&hw->rx_status_lock, flags); if (fjes_hw_epid_is_same_zone(hw, epidx)) { mutex_lock(&hw->hw_info.lock); result = fjes_hw_register_buff_addr(hw, epidx, buf_pair); mutex_unlock(&hw->hw_info.lock); switch (result) { case 0: break; case -ENOMSG: case -EBUSY: default: adapter->force_reset = true; return result; } hw->ep_shm_info[epidx].ep_stats .com_regist_buf_exec += 1; } } return 0; }