0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/pci.h>
0020 #include <linux/netdevice.h>
0021 #include "liquidio_common.h"
0022 #include "octeon_droq.h"
0023 #include "octeon_iq.h"
0024 #include "response_manager.h"
0025 #include "octeon_device.h"
0026 #include "octeon_nic.h"
0027 #include "octeon_main.h"
0028
0029 void *
0030 octeon_alloc_soft_command_resp(struct octeon_device *oct,
0031 union octeon_instr_64B *cmd,
0032 u32 rdatasize)
0033 {
0034 struct octeon_soft_command *sc;
0035 struct octeon_instr_ih3 *ih3;
0036 struct octeon_instr_ih2 *ih2;
0037 struct octeon_instr_irh *irh;
0038 struct octeon_instr_rdp *rdp;
0039
0040 sc = (struct octeon_soft_command *)
0041 octeon_alloc_soft_command(oct, 0, rdatasize, 0);
0042
0043 if (!sc)
0044 return NULL;
0045
0046
0047 memcpy(&sc->cmd, cmd, sizeof(union octeon_instr_64B));
0048
0049
0050
0051
0052 if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) {
0053 ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
0054 rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
0055 irh = (struct octeon_instr_irh *)&sc->cmd.cmd3.irh;
0056
0057 ih3->fsz = LIO_SOFTCMDRESP_IH3;
0058 } else {
0059 ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
0060 rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
0061 irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
0062
0063 ih2->fsz = LIO_SOFTCMDRESP_IH2;
0064 }
0065
0066 irh->rflag = 1;
0067
0068 rdp->pcie_port = oct->pcie_port;
0069 rdp->rlen = rdatasize;
0070
0071 *sc->status_word = COMPLETION_WORD_INIT;
0072
0073 if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))
0074 sc->cmd.cmd3.rptr = sc->dmarptr;
0075 else
0076 sc->cmd.cmd2.rptr = sc->dmarptr;
0077
0078 sc->expiry_time = jiffies + msecs_to_jiffies(LIO_SC_MAX_TMO_MS);
0079
0080 return sc;
0081 }
0082
0083 int octnet_send_nic_data_pkt(struct octeon_device *oct,
0084 struct octnic_data_pkt *ndata,
0085 int xmit_more)
0086 {
0087 int ring_doorbell = !xmit_more;
0088
0089 return octeon_send_command(oct, ndata->q_no, ring_doorbell, &ndata->cmd,
0090 ndata->buf, ndata->datasize,
0091 ndata->reqtype);
0092 }
0093
0094 static inline struct octeon_soft_command
0095 *octnic_alloc_ctrl_pkt_sc(struct octeon_device *oct,
0096 struct octnic_ctrl_pkt *nctrl)
0097 {
0098 struct octeon_soft_command *sc = NULL;
0099 u8 *data;
0100 u32 rdatasize;
0101 u32 uddsize = 0, datasize = 0;
0102
0103 uddsize = (u32)(nctrl->ncmd.s.more * 8);
0104
0105 datasize = OCTNET_CMD_SIZE + uddsize;
0106 rdatasize = 16;
0107
0108 sc = (struct octeon_soft_command *)
0109 octeon_alloc_soft_command(oct, datasize, rdatasize, 0);
0110
0111 if (!sc)
0112 return NULL;
0113
0114 data = (u8 *)sc->virtdptr;
0115
0116 memcpy(data, &nctrl->ncmd, OCTNET_CMD_SIZE);
0117
0118 octeon_swap_8B_data((u64 *)data, (OCTNET_CMD_SIZE >> 3));
0119
0120 if (uddsize) {
0121
0122 memcpy(data + OCTNET_CMD_SIZE, nctrl->udd, uddsize);
0123 }
0124
0125 sc->iq_no = (u32)nctrl->iq_no;
0126
0127 octeon_prepare_soft_command(oct, sc, OPCODE_NIC, OPCODE_NIC_CMD,
0128 0, 0, 0);
0129
0130 init_completion(&sc->complete);
0131 sc->sc_status = OCTEON_REQUEST_PENDING;
0132
0133 return sc;
0134 }
0135
0136 int
0137 octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
0138 struct octnic_ctrl_pkt *nctrl)
0139 {
0140 int retval;
0141 struct octeon_soft_command *sc = NULL;
0142
0143 spin_lock_bh(&oct->cmd_resp_wqlock);
0144
0145
0146
0147 if ((oct->cmd_resp_state == OCT_DRV_OFFLINE) &&
0148 (nctrl->ncmd.s.cmd != OCTNET_CMD_RX_CTL)) {
0149 spin_unlock_bh(&oct->cmd_resp_wqlock);
0150 dev_err(&oct->pci_dev->dev,
0151 "%s cmd:%d not processed since driver offline\n",
0152 __func__, nctrl->ncmd.s.cmd);
0153 return -1;
0154 }
0155
0156 sc = octnic_alloc_ctrl_pkt_sc(oct, nctrl);
0157 if (!sc) {
0158 dev_err(&oct->pci_dev->dev, "%s soft command alloc failed\n",
0159 __func__);
0160 spin_unlock_bh(&oct->cmd_resp_wqlock);
0161 return -1;
0162 }
0163
0164 retval = octeon_send_soft_command(oct, sc);
0165 if (retval == IQ_SEND_FAILED) {
0166 octeon_free_soft_command(oct, sc);
0167 dev_err(&oct->pci_dev->dev, "%s pf_num:%d soft command:%d send failed status: %x\n",
0168 __func__, oct->pf_num, nctrl->ncmd.s.cmd, retval);
0169 spin_unlock_bh(&oct->cmd_resp_wqlock);
0170 return -1;
0171 }
0172
0173 spin_unlock_bh(&oct->cmd_resp_wqlock);
0174
0175 if (nctrl->ncmd.s.cmdgroup == 0) {
0176 switch (nctrl->ncmd.s.cmd) {
0177
0178 case OCTNET_CMD_CHANGE_DEVFLAGS:
0179 case OCTNET_CMD_SET_MULTI_LIST:
0180 case OCTNET_CMD_SET_UC_LIST:
0181 WRITE_ONCE(sc->caller_is_done, true);
0182 return retval;
0183 }
0184 }
0185
0186 retval = wait_for_sc_completion_timeout(oct, sc, 0);
0187 if (retval)
0188 return (retval);
0189
0190 nctrl->sc_status = sc->sc_status;
0191 retval = nctrl->sc_status;
0192 if (nctrl->cb_fn)
0193 nctrl->cb_fn(nctrl);
0194
0195 WRITE_ONCE(sc->caller_is_done, true);
0196
0197 return retval;
0198 }