1*4c45a51eSXuan Zhuo // SPDX-License-Identifier: GPL-2.0-or-later 2*4c45a51eSXuan Zhuo /* 3*4c45a51eSXuan Zhuo * Driver for Alibaba Elastic Ethernet Adapter. 4*4c45a51eSXuan Zhuo * 5*4c45a51eSXuan Zhuo * Copyright (C) 2025 Alibaba Inc. 6*4c45a51eSXuan Zhuo */ 7*4c45a51eSXuan Zhuo 8*4c45a51eSXuan Zhuo #include <linux/etherdevice.h> 9*4c45a51eSXuan Zhuo #include <linux/iopoll.h> 10*4c45a51eSXuan Zhuo #include <linux/utsname.h> 11*4c45a51eSXuan Zhuo #include <linux/version.h> 12*4c45a51eSXuan Zhuo 13*4c45a51eSXuan Zhuo #include "eea_adminq.h" 14*4c45a51eSXuan Zhuo #include "eea_net.h" 15*4c45a51eSXuan Zhuo #include "eea_pci.h" 16*4c45a51eSXuan Zhuo #include "eea_ring.h" 17*4c45a51eSXuan Zhuo 18*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_CFG_QUERY ((0 << 8) | 0) 19*4c45a51eSXuan Zhuo 20*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_QUEUE_CREATE ((1 << 8) | 0) 21*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_QUEUE_DESTROY_ALL ((1 << 8) | 1) 22*4c45a51eSXuan Zhuo 23*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_HOST_INFO ((2 << 8) | 0) 24*4c45a51eSXuan Zhuo 25*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_DEV_STATUS ((3 << 8) | 0) 26*4c45a51eSXuan Zhuo 27*4c45a51eSXuan Zhuo #define EEA_RING_DESC_F_AQ_PHASE (BIT(15) | BIT(7)) 28*4c45a51eSXuan Zhuo 29*4c45a51eSXuan Zhuo #define EEA_QUEUE_FLAGS_HW_SPLIT_HDR BIT(0) 30*4c45a51eSXuan Zhuo #define EEA_QUEUE_FLAGS_SQCQ BIT(1) 31*4c45a51eSXuan Zhuo #define EEA_QUEUE_FLAGS_HWTS BIT(2) 32*4c45a51eSXuan Zhuo 33*4c45a51eSXuan Zhuo struct eea_aq_create { 34*4c45a51eSXuan Zhuo __le32 flags; 35*4c45a51eSXuan Zhuo /* queue index. 36*4c45a51eSXuan Zhuo * rx: 0 == qidx % 2 37*4c45a51eSXuan Zhuo * tx: 1 == qidx % 2 38*4c45a51eSXuan Zhuo */ 39*4c45a51eSXuan Zhuo __le16 qidx; 40*4c45a51eSXuan Zhuo /* the depth of the queue */ 41*4c45a51eSXuan Zhuo __le16 depth; 42*4c45a51eSXuan Zhuo /* 0: without SPLIT HDR 43*4c45a51eSXuan Zhuo * 1: 128B 44*4c45a51eSXuan Zhuo * 2: 256B 45*4c45a51eSXuan Zhuo * 3: 512B 46*4c45a51eSXuan Zhuo */ 47*4c45a51eSXuan Zhuo u8 hdr_buf_size; 48*4c45a51eSXuan Zhuo u8 sq_desc_size; 49*4c45a51eSXuan Zhuo u8 cq_desc_size; 50*4c45a51eSXuan Zhuo u8 reserve0; 51*4c45a51eSXuan Zhuo /* The vector for the irq. rx,tx share the same vector */ 52*4c45a51eSXuan Zhuo __le16 msix_vector; 53*4c45a51eSXuan Zhuo __le16 reserve; 54*4c45a51eSXuan Zhuo /* sq ring cfg. */ 55*4c45a51eSXuan Zhuo __le32 sq_addr_low; 56*4c45a51eSXuan Zhuo __le32 sq_addr_high; 57*4c45a51eSXuan Zhuo /* cq ring cfg. Just valid when flags include EEA_QUEUE_FLAGS_SQCQ. */ 58*4c45a51eSXuan Zhuo __le32 cq_addr_low; 59*4c45a51eSXuan Zhuo __le32 cq_addr_high; 60*4c45a51eSXuan Zhuo }; 61*4c45a51eSXuan Zhuo 62*4c45a51eSXuan Zhuo struct eea_aq_queue_drv_status { 63*4c45a51eSXuan Zhuo __le16 qidx; 64*4c45a51eSXuan Zhuo 65*4c45a51eSXuan Zhuo __le16 sq_head; 66*4c45a51eSXuan Zhuo __le16 cq_head; 67*4c45a51eSXuan Zhuo __le16 reserved; 68*4c45a51eSXuan Zhuo }; 69*4c45a51eSXuan Zhuo 70*4c45a51eSXuan Zhuo #define EEA_OS_DISTRO 0 71*4c45a51eSXuan Zhuo #define EEA_DRV_TYPE 0 72*4c45a51eSXuan Zhuo #define EEA_OS_LINUX 1 73*4c45a51eSXuan Zhuo #define EEA_SPEC_VER_MAJOR 1 74*4c45a51eSXuan Zhuo #define EEA_SPEC_VER_MINOR 0 75*4c45a51eSXuan Zhuo 76*4c45a51eSXuan Zhuo struct eea_aq_host_info_cfg { 77*4c45a51eSXuan Zhuo __le16 os_type; 78*4c45a51eSXuan Zhuo __le16 os_dist; 79*4c45a51eSXuan Zhuo __le16 drv_type; 80*4c45a51eSXuan Zhuo 81*4c45a51eSXuan Zhuo __le16 kern_ver_major; 82*4c45a51eSXuan Zhuo __le16 kern_ver_minor; 83*4c45a51eSXuan Zhuo __le16 kern_ver_sub_minor; 84*4c45a51eSXuan Zhuo 85*4c45a51eSXuan Zhuo __le16 drv_ver_major; 86*4c45a51eSXuan Zhuo __le16 drv_ver_minor; 87*4c45a51eSXuan Zhuo __le16 drv_ver_sub_minor; 88*4c45a51eSXuan Zhuo 89*4c45a51eSXuan Zhuo __le16 spec_ver_major; 90*4c45a51eSXuan Zhuo __le16 spec_ver_minor; 91*4c45a51eSXuan Zhuo __le16 pci_bdf; 92*4c45a51eSXuan Zhuo __le32 pci_domain; 93*4c45a51eSXuan Zhuo 94*4c45a51eSXuan Zhuo u8 os_ver_str[64]; 95*4c45a51eSXuan Zhuo u8 isa_str[64]; 96*4c45a51eSXuan Zhuo }; 97*4c45a51eSXuan Zhuo 98*4c45a51eSXuan Zhuo #define EEA_HINFO_MAX_REP_LEN 1024 99*4c45a51eSXuan Zhuo #define EEA_HINFO_REP_BAD 2 100*4c45a51eSXuan Zhuo 101*4c45a51eSXuan Zhuo struct eea_aq_host_info_rep { 102*4c45a51eSXuan Zhuo u8 op_code; 103*4c45a51eSXuan Zhuo u8 has_reply; 104*4c45a51eSXuan Zhuo u8 reply_str[EEA_HINFO_MAX_REP_LEN]; 105*4c45a51eSXuan Zhuo }; 106*4c45a51eSXuan Zhuo 107*4c45a51eSXuan Zhuo static struct eea_ring *qid_to_ering(struct eea_net *enet, u32 qid) 108*4c45a51eSXuan Zhuo { 109*4c45a51eSXuan Zhuo struct eea_ring *ering; 110*4c45a51eSXuan Zhuo 111*4c45a51eSXuan Zhuo if (qid % 2 == 0) 112*4c45a51eSXuan Zhuo ering = enet->rx[qid / 2]->ering; 113*4c45a51eSXuan Zhuo else 114*4c45a51eSXuan Zhuo ering = enet->tx[qid / 2].ering; 115*4c45a51eSXuan Zhuo 116*4c45a51eSXuan Zhuo return ering; 117*4c45a51eSXuan Zhuo } 118*4c45a51eSXuan Zhuo 119*4c45a51eSXuan Zhuo #define EEA_AQ_TIMEOUT_US (60 * 1000 * 1000) 120*4c45a51eSXuan Zhuo 121*4c45a51eSXuan Zhuo static void eea_device_broken(struct eea_net *enet) 122*4c45a51eSXuan Zhuo { 123*4c45a51eSXuan Zhuo if (enet->adminq.broken) 124*4c45a51eSXuan Zhuo return; 125*4c45a51eSXuan Zhuo 126*4c45a51eSXuan Zhuo eea_device_reset(enet->edev); 127*4c45a51eSXuan Zhuo enet->adminq.broken = true; 128*4c45a51eSXuan Zhuo } 129*4c45a51eSXuan Zhuo 130*4c45a51eSXuan Zhuo static int eea_adminq_submit(struct eea_net *enet, u16 cmd, 131*4c45a51eSXuan Zhuo dma_addr_t req_addr, dma_addr_t res_addr, 132*4c45a51eSXuan Zhuo u32 req_size, u32 res_size, u32 *reply_len) 133*4c45a51eSXuan Zhuo { 134*4c45a51eSXuan Zhuo struct eea_aq_cdesc *cdesc; 135*4c45a51eSXuan Zhuo struct eea_aq_desc *desc; 136*4c45a51eSXuan Zhuo int ret; 137*4c45a51eSXuan Zhuo 138*4c45a51eSXuan Zhuo if (enet->adminq.broken) 139*4c45a51eSXuan Zhuo return -EIO; 140*4c45a51eSXuan Zhuo 141*4c45a51eSXuan Zhuo desc = eea_ering_aq_alloc_desc(enet->adminq.ring); 142*4c45a51eSXuan Zhuo 143*4c45a51eSXuan Zhuo desc->classid = cmd >> 8; 144*4c45a51eSXuan Zhuo desc->command = cmd & 0xff; 145*4c45a51eSXuan Zhuo 146*4c45a51eSXuan Zhuo desc->data_addr = cpu_to_le64(req_addr); 147*4c45a51eSXuan Zhuo desc->data_len = cpu_to_le32(req_size); 148*4c45a51eSXuan Zhuo 149*4c45a51eSXuan Zhuo desc->reply_addr = cpu_to_le64(res_addr); 150*4c45a51eSXuan Zhuo desc->reply_len = cpu_to_le32(res_size); 151*4c45a51eSXuan Zhuo 152*4c45a51eSXuan Zhuo /* for update flags */ 153*4c45a51eSXuan Zhuo dma_wmb(); 154*4c45a51eSXuan Zhuo 155*4c45a51eSXuan Zhuo desc->flags = cpu_to_le16(enet->adminq.phase); 156*4c45a51eSXuan Zhuo 157*4c45a51eSXuan Zhuo eea_ering_sq_commit_desc(enet->adminq.ring); 158*4c45a51eSXuan Zhuo 159*4c45a51eSXuan Zhuo eea_ering_kick(enet->adminq.ring); 160*4c45a51eSXuan Zhuo 161*4c45a51eSXuan Zhuo ++enet->adminq.num; 162*4c45a51eSXuan Zhuo 163*4c45a51eSXuan Zhuo if ((enet->adminq.num % enet->adminq.ring->num) == 0) 164*4c45a51eSXuan Zhuo enet->adminq.phase ^= EEA_RING_DESC_F_AQ_PHASE; 165*4c45a51eSXuan Zhuo 166*4c45a51eSXuan Zhuo ret = read_poll_timeout(eea_ering_cq_get_desc, cdesc, cdesc, 10, 167*4c45a51eSXuan Zhuo EEA_AQ_TIMEOUT_US, false, enet->adminq.ring); 168*4c45a51eSXuan Zhuo if (ret) { 169*4c45a51eSXuan Zhuo netdev_err(enet->netdev, 170*4c45a51eSXuan Zhuo "adminq exec timeout. cmd: %d reset device.\n", 171*4c45a51eSXuan Zhuo cmd); 172*4c45a51eSXuan Zhuo /* The device must be reset before unmapping buffers to avoid 173*4c45a51eSXuan Zhuo * potential DMA writes after the memory is freed. 174*4c45a51eSXuan Zhuo */ 175*4c45a51eSXuan Zhuo eea_device_broken(enet); 176*4c45a51eSXuan Zhuo return ret; 177*4c45a51eSXuan Zhuo } 178*4c45a51eSXuan Zhuo 179*4c45a51eSXuan Zhuo /* Returns 0 on success, or a negative error code on failure. */ 180*4c45a51eSXuan Zhuo ret = le32_to_cpu(cdesc->status); 181*4c45a51eSXuan Zhuo 182*4c45a51eSXuan Zhuo eea_ering_cq_ack_desc(enet->adminq.ring, 1); 183*4c45a51eSXuan Zhuo 184*4c45a51eSXuan Zhuo if (ret) 185*4c45a51eSXuan Zhuo netdev_err(enet->netdev, 186*4c45a51eSXuan Zhuo "adminq exec failed. cmd: %d ret %d\n", cmd, ret); 187*4c45a51eSXuan Zhuo else 188*4c45a51eSXuan Zhuo *reply_len = le32_to_cpu(cdesc->reply_len); 189*4c45a51eSXuan Zhuo 190*4c45a51eSXuan Zhuo return ret; 191*4c45a51eSXuan Zhuo } 192*4c45a51eSXuan Zhuo 193*4c45a51eSXuan Zhuo static int eea_adminq_exec(struct eea_net *enet, u16 cmd, 194*4c45a51eSXuan Zhuo void *req, u32 req_size, 195*4c45a51eSXuan Zhuo void *res, u32 res_size, 196*4c45a51eSXuan Zhuo u32 *reply) 197*4c45a51eSXuan Zhuo { 198*4c45a51eSXuan Zhuo dma_addr_t req_addr = 0, res_addr = 0; 199*4c45a51eSXuan Zhuo struct device *dma; 200*4c45a51eSXuan Zhuo u32 reply_len = 0; 201*4c45a51eSXuan Zhuo int ret; 202*4c45a51eSXuan Zhuo 203*4c45a51eSXuan Zhuo if (reply) 204*4c45a51eSXuan Zhuo *reply = 0; 205*4c45a51eSXuan Zhuo 206*4c45a51eSXuan Zhuo dma = enet->edev->dma_dev; 207*4c45a51eSXuan Zhuo 208*4c45a51eSXuan Zhuo if (req) { 209*4c45a51eSXuan Zhuo req_addr = dma_map_single(dma, req, req_size, DMA_TO_DEVICE); 210*4c45a51eSXuan Zhuo if (unlikely(dma_mapping_error(dma, req_addr))) 211*4c45a51eSXuan Zhuo return -ENOMEM; 212*4c45a51eSXuan Zhuo } 213*4c45a51eSXuan Zhuo 214*4c45a51eSXuan Zhuo if (res) { 215*4c45a51eSXuan Zhuo res_addr = dma_map_single(dma, res, res_size, DMA_FROM_DEVICE); 216*4c45a51eSXuan Zhuo if (unlikely(dma_mapping_error(dma, res_addr))) { 217*4c45a51eSXuan Zhuo ret = -ENOMEM; 218*4c45a51eSXuan Zhuo goto err_unmap_req; 219*4c45a51eSXuan Zhuo } 220*4c45a51eSXuan Zhuo } 221*4c45a51eSXuan Zhuo 222*4c45a51eSXuan Zhuo mutex_lock(&enet->adminq.lock); 223*4c45a51eSXuan Zhuo ret = eea_adminq_submit(enet, cmd, req_addr, res_addr, 224*4c45a51eSXuan Zhuo req_size, res_size, &reply_len); 225*4c45a51eSXuan Zhuo mutex_unlock(&enet->adminq.lock); 226*4c45a51eSXuan Zhuo if (res) { 227*4c45a51eSXuan Zhuo dma_unmap_single(dma, res_addr, res_size, DMA_FROM_DEVICE); 228*4c45a51eSXuan Zhuo 229*4c45a51eSXuan Zhuo if (ret) 230*4c45a51eSXuan Zhuo memset(res, 0, res_size); 231*4c45a51eSXuan Zhuo else if (res_size > reply_len) 232*4c45a51eSXuan Zhuo memset(res + reply_len, 0, res_size - reply_len); 233*4c45a51eSXuan Zhuo 234*4c45a51eSXuan Zhuo if (reply) 235*4c45a51eSXuan Zhuo *reply = reply_len; 236*4c45a51eSXuan Zhuo } 237*4c45a51eSXuan Zhuo 238*4c45a51eSXuan Zhuo err_unmap_req: 239*4c45a51eSXuan Zhuo if (req) 240*4c45a51eSXuan Zhuo dma_unmap_single(dma, req_addr, req_size, DMA_TO_DEVICE); 241*4c45a51eSXuan Zhuo 242*4c45a51eSXuan Zhuo return ret; 243*4c45a51eSXuan Zhuo } 244*4c45a51eSXuan Zhuo 245*4c45a51eSXuan Zhuo void eea_destroy_adminq(struct eea_net *enet) 246*4c45a51eSXuan Zhuo { 247*4c45a51eSXuan Zhuo struct eea_aq *aq; 248*4c45a51eSXuan Zhuo 249*4c45a51eSXuan Zhuo aq = &enet->adminq; 250*4c45a51eSXuan Zhuo 251*4c45a51eSXuan Zhuo if (aq->ring) { 252*4c45a51eSXuan Zhuo eea_ering_free(aq->ring); 253*4c45a51eSXuan Zhuo aq->ring = NULL; 254*4c45a51eSXuan Zhuo aq->phase = 0; 255*4c45a51eSXuan Zhuo } 256*4c45a51eSXuan Zhuo 257*4c45a51eSXuan Zhuo kfree(aq->q_req_buf); 258*4c45a51eSXuan Zhuo kfree(aq->q_res_buf); 259*4c45a51eSXuan Zhuo 260*4c45a51eSXuan Zhuo aq->q_req_buf = NULL; 261*4c45a51eSXuan Zhuo aq->q_res_buf = NULL; 262*4c45a51eSXuan Zhuo } 263*4c45a51eSXuan Zhuo 264*4c45a51eSXuan Zhuo int eea_create_adminq(struct eea_net *enet, u32 qid) 265*4c45a51eSXuan Zhuo { 266*4c45a51eSXuan Zhuo u32 db_size, q_size, num; 267*4c45a51eSXuan Zhuo struct eea_ring *ering; 268*4c45a51eSXuan Zhuo struct eea_aq *aq; 269*4c45a51eSXuan Zhuo int err = -ENOMEM; 270*4c45a51eSXuan Zhuo 271*4c45a51eSXuan Zhuo num = enet->edev->rx_num + enet->edev->tx_num; 272*4c45a51eSXuan Zhuo aq = &enet->adminq; 273*4c45a51eSXuan Zhuo 274*4c45a51eSXuan Zhuo ering = eea_ering_alloc(qid, 64, enet->edev, sizeof(struct eea_aq_desc), 275*4c45a51eSXuan Zhuo sizeof(struct eea_aq_cdesc), "adminq"); 276*4c45a51eSXuan Zhuo if (!ering) 277*4c45a51eSXuan Zhuo return -ENOMEM; 278*4c45a51eSXuan Zhuo 279*4c45a51eSXuan Zhuo aq->ring = ering; 280*4c45a51eSXuan Zhuo 281*4c45a51eSXuan Zhuo err = eea_pci_active_aq(ering, qid / 2 + 1); 282*4c45a51eSXuan Zhuo if (err) 283*4c45a51eSXuan Zhuo goto err; 284*4c45a51eSXuan Zhuo 285*4c45a51eSXuan Zhuo aq->phase = BIT(7); 286*4c45a51eSXuan Zhuo aq->num = 0; 287*4c45a51eSXuan Zhuo 288*4c45a51eSXuan Zhuo q_size = sizeof(*aq->q_req_buf) * num; 289*4c45a51eSXuan Zhuo db_size = sizeof(*aq->q_res_buf) * num; 290*4c45a51eSXuan Zhuo 291*4c45a51eSXuan Zhuo aq->q_req_size = q_size; 292*4c45a51eSXuan Zhuo aq->q_res_size = db_size; 293*4c45a51eSXuan Zhuo 294*4c45a51eSXuan Zhuo err = -ENOMEM; 295*4c45a51eSXuan Zhuo 296*4c45a51eSXuan Zhuo aq->q_req_buf = kzalloc(q_size, GFP_KERNEL); 297*4c45a51eSXuan Zhuo if (!aq->q_req_buf) 298*4c45a51eSXuan Zhuo goto err; 299*4c45a51eSXuan Zhuo 300*4c45a51eSXuan Zhuo aq->q_res_buf = kzalloc(db_size, GFP_KERNEL); 301*4c45a51eSXuan Zhuo if (!aq->q_res_buf) 302*4c45a51eSXuan Zhuo goto err; 303*4c45a51eSXuan Zhuo 304*4c45a51eSXuan Zhuo /* Before we set up the AQ, the device remains in an inactive state, so 305*4c45a51eSXuan Zhuo * there will be no DMA operations. If the 'set up AQ' process fails, we 306*4c45a51eSXuan Zhuo * can safely free the DMA-related memory. 307*4c45a51eSXuan Zhuo */ 308*4c45a51eSXuan Zhuo err = eea_pci_set_aq_up(enet->edev); 309*4c45a51eSXuan Zhuo if (err) 310*4c45a51eSXuan Zhuo goto err; 311*4c45a51eSXuan Zhuo 312*4c45a51eSXuan Zhuo aq->broken = false; 313*4c45a51eSXuan Zhuo 314*4c45a51eSXuan Zhuo mutex_init(&aq->lock); 315*4c45a51eSXuan Zhuo 316*4c45a51eSXuan Zhuo return 0; 317*4c45a51eSXuan Zhuo 318*4c45a51eSXuan Zhuo err: 319*4c45a51eSXuan Zhuo eea_destroy_adminq(enet); 320*4c45a51eSXuan Zhuo return err; 321*4c45a51eSXuan Zhuo } 322*4c45a51eSXuan Zhuo 323*4c45a51eSXuan Zhuo int eea_adminq_query_cfg(struct eea_net *enet, struct eea_aq_cfg *cfg) 324*4c45a51eSXuan Zhuo { 325*4c45a51eSXuan Zhuo return eea_adminq_exec(enet, EEA_AQ_CMD_CFG_QUERY, NULL, 0, cfg, 326*4c45a51eSXuan Zhuo sizeof(*cfg), NULL); 327*4c45a51eSXuan Zhuo } 328*4c45a51eSXuan Zhuo 329*4c45a51eSXuan Zhuo static void qcfg_fill(struct eea_aq_create *qcfg, struct eea_ring *ering, 330*4c45a51eSXuan Zhuo u32 flags) 331*4c45a51eSXuan Zhuo { 332*4c45a51eSXuan Zhuo qcfg->flags = cpu_to_le32(flags); 333*4c45a51eSXuan Zhuo qcfg->qidx = cpu_to_le16(ering->index); 334*4c45a51eSXuan Zhuo qcfg->depth = cpu_to_le16(ering->num); 335*4c45a51eSXuan Zhuo 336*4c45a51eSXuan Zhuo qcfg->hdr_buf_size = flags & EEA_QUEUE_FLAGS_HW_SPLIT_HDR ? 1 : 0; 337*4c45a51eSXuan Zhuo qcfg->sq_desc_size = ering->sq.desc_size; 338*4c45a51eSXuan Zhuo qcfg->cq_desc_size = ering->cq.desc_size; 339*4c45a51eSXuan Zhuo qcfg->msix_vector = cpu_to_le16(ering->msix_vec); 340*4c45a51eSXuan Zhuo 341*4c45a51eSXuan Zhuo qcfg->sq_addr_low = cpu_to_le32(lower_32_bits(ering->sq.dma_addr)); 342*4c45a51eSXuan Zhuo qcfg->sq_addr_high = cpu_to_le32(upper_32_bits(ering->sq.dma_addr)); 343*4c45a51eSXuan Zhuo 344*4c45a51eSXuan Zhuo qcfg->cq_addr_low = cpu_to_le32(lower_32_bits(ering->cq.dma_addr)); 345*4c45a51eSXuan Zhuo qcfg->cq_addr_high = cpu_to_le32(upper_32_bits(ering->cq.dma_addr)); 346*4c45a51eSXuan Zhuo } 347*4c45a51eSXuan Zhuo 348*4c45a51eSXuan Zhuo int eea_adminq_create_q(struct eea_net *enet, u32 num, u32 flags) 349*4c45a51eSXuan Zhuo { 350*4c45a51eSXuan Zhuo int i, db_size, q_size, err = -ENOMEM; 351*4c45a51eSXuan Zhuo struct eea_net_cfg *cfg; 352*4c45a51eSXuan Zhuo struct eea_ring *ering; 353*4c45a51eSXuan Zhuo struct eea_aq *aq; 354*4c45a51eSXuan Zhuo u32 reply_len; 355*4c45a51eSXuan Zhuo 356*4c45a51eSXuan Zhuo cfg = &enet->cfg; 357*4c45a51eSXuan Zhuo aq = &enet->adminq; 358*4c45a51eSXuan Zhuo 359*4c45a51eSXuan Zhuo if (cfg->split_hdr) 360*4c45a51eSXuan Zhuo flags |= EEA_QUEUE_FLAGS_HW_SPLIT_HDR; 361*4c45a51eSXuan Zhuo 362*4c45a51eSXuan Zhuo flags |= EEA_QUEUE_FLAGS_SQCQ; 363*4c45a51eSXuan Zhuo flags |= EEA_QUEUE_FLAGS_HWTS; 364*4c45a51eSXuan Zhuo 365*4c45a51eSXuan Zhuo q_size = sizeof(*aq->q_req_buf) * num; 366*4c45a51eSXuan Zhuo db_size = sizeof(*aq->q_res_buf) * num; 367*4c45a51eSXuan Zhuo 368*4c45a51eSXuan Zhuo for (i = 0; i < num; i++) { 369*4c45a51eSXuan Zhuo ering = qid_to_ering(enet, i); 370*4c45a51eSXuan Zhuo qcfg_fill(aq->q_req_buf + i, ering, flags); 371*4c45a51eSXuan Zhuo } 372*4c45a51eSXuan Zhuo 373*4c45a51eSXuan Zhuo err = eea_adminq_exec(enet, EEA_AQ_CMD_QUEUE_CREATE, 374*4c45a51eSXuan Zhuo aq->q_req_buf, q_size, 375*4c45a51eSXuan Zhuo aq->q_res_buf, db_size, 376*4c45a51eSXuan Zhuo &reply_len); 377*4c45a51eSXuan Zhuo if (err) 378*4c45a51eSXuan Zhuo return err; 379*4c45a51eSXuan Zhuo 380*4c45a51eSXuan Zhuo if (reply_len != db_size) { 381*4c45a51eSXuan Zhuo eea_adminq_destroy_all_q(enet); 382*4c45a51eSXuan Zhuo netdev_err(enet->netdev, "invalid reply len %u\n", reply_len); 383*4c45a51eSXuan Zhuo return -EINVAL; 384*4c45a51eSXuan Zhuo } 385*4c45a51eSXuan Zhuo 386*4c45a51eSXuan Zhuo for (i = 0; i < num; i++) { 387*4c45a51eSXuan Zhuo ering = qid_to_ering(enet, i); 388*4c45a51eSXuan Zhuo ering->db = eea_pci_db_addr(ering->edev, 389*4c45a51eSXuan Zhuo le32_to_cpu(aq->q_res_buf[i])); 390*4c45a51eSXuan Zhuo if (!ering->db) { 391*4c45a51eSXuan Zhuo netdev_err(enet->netdev, "invalid db off %u\n", 392*4c45a51eSXuan Zhuo le32_to_cpu(aq->q_res_buf[i])); 393*4c45a51eSXuan Zhuo goto err; 394*4c45a51eSXuan Zhuo } 395*4c45a51eSXuan Zhuo } 396*4c45a51eSXuan Zhuo 397*4c45a51eSXuan Zhuo return err; 398*4c45a51eSXuan Zhuo 399*4c45a51eSXuan Zhuo err: 400*4c45a51eSXuan Zhuo eea_adminq_destroy_all_q(enet); 401*4c45a51eSXuan Zhuo for (i = 0; i < num; i++) { 402*4c45a51eSXuan Zhuo ering = qid_to_ering(enet, i); 403*4c45a51eSXuan Zhuo ering->db = NULL; 404*4c45a51eSXuan Zhuo } 405*4c45a51eSXuan Zhuo 406*4c45a51eSXuan Zhuo return -EIO; 407*4c45a51eSXuan Zhuo } 408*4c45a51eSXuan Zhuo 409*4c45a51eSXuan Zhuo int eea_adminq_destroy_all_q(struct eea_net *enet) 410*4c45a51eSXuan Zhuo { 411*4c45a51eSXuan Zhuo int err; 412*4c45a51eSXuan Zhuo 413*4c45a51eSXuan Zhuo err = eea_adminq_exec(enet, EEA_AQ_CMD_QUEUE_DESTROY_ALL, NULL, 0, 414*4c45a51eSXuan Zhuo NULL, 0, NULL); 415*4c45a51eSXuan Zhuo if (err) { 416*4c45a51eSXuan Zhuo /* The device must be reset before unmapping buffers to avoid 417*4c45a51eSXuan Zhuo * potential DMA writes after the memory is freed. 418*4c45a51eSXuan Zhuo */ 419*4c45a51eSXuan Zhuo mutex_lock(&enet->adminq.lock); 420*4c45a51eSXuan Zhuo eea_device_broken(enet); 421*4c45a51eSXuan Zhuo mutex_unlock(&enet->adminq.lock); 422*4c45a51eSXuan Zhuo 423*4c45a51eSXuan Zhuo netdev_err(enet->netdev, "QUEUE_DESTROY fail: reset device.\n"); 424*4c45a51eSXuan Zhuo } 425*4c45a51eSXuan Zhuo 426*4c45a51eSXuan Zhuo return err; 427*4c45a51eSXuan Zhuo } 428*4c45a51eSXuan Zhuo 429*4c45a51eSXuan Zhuo /* The caller must ensure that both the 'rx' and 'tx' arrays are valid. */ 430*4c45a51eSXuan Zhuo int eea_adminq_dev_status(struct eea_net *enet, 431*4c45a51eSXuan Zhuo struct eea_aq_dev_status *dstatus) 432*4c45a51eSXuan Zhuo { 433*4c45a51eSXuan Zhuo struct eea_aq_queue_drv_status *drv_status; 434*4c45a51eSXuan Zhuo struct __eea_aq_dev_status *dev_status; 435*4c45a51eSXuan Zhuo int err, i, io_num, size, q_num; 436*4c45a51eSXuan Zhuo struct eea_ring *ering; 437*4c45a51eSXuan Zhuo void *rep, *req; 438*4c45a51eSXuan Zhuo 439*4c45a51eSXuan Zhuo q_num = enet->cfg.rx_ring_num + enet->cfg.tx_ring_num + 1; 440*4c45a51eSXuan Zhuo io_num = enet->cfg.rx_ring_num + enet->cfg.tx_ring_num; 441*4c45a51eSXuan Zhuo 442*4c45a51eSXuan Zhuo req = kcalloc(q_num, sizeof(struct eea_aq_queue_drv_status), 443*4c45a51eSXuan Zhuo GFP_KERNEL); 444*4c45a51eSXuan Zhuo if (!req) 445*4c45a51eSXuan Zhuo return -ENOMEM; 446*4c45a51eSXuan Zhuo 447*4c45a51eSXuan Zhuo size = struct_size(dev_status, q_status, q_num); 448*4c45a51eSXuan Zhuo 449*4c45a51eSXuan Zhuo rep = kzalloc(size, GFP_KERNEL); 450*4c45a51eSXuan Zhuo if (!rep) { 451*4c45a51eSXuan Zhuo kfree(req); 452*4c45a51eSXuan Zhuo return -ENOMEM; 453*4c45a51eSXuan Zhuo } 454*4c45a51eSXuan Zhuo 455*4c45a51eSXuan Zhuo drv_status = req; 456*4c45a51eSXuan Zhuo for (i = 0; i < io_num; ++i, ++drv_status) { 457*4c45a51eSXuan Zhuo ering = qid_to_ering(enet, i); 458*4c45a51eSXuan Zhuo drv_status->qidx = cpu_to_le16(i); 459*4c45a51eSXuan Zhuo drv_status->cq_head = cpu_to_le16(ering->cq.head); 460*4c45a51eSXuan Zhuo drv_status->sq_head = cpu_to_le16(ering->sq.head); 461*4c45a51eSXuan Zhuo } 462*4c45a51eSXuan Zhuo 463*4c45a51eSXuan Zhuo drv_status->qidx = cpu_to_le16(i); 464*4c45a51eSXuan Zhuo drv_status->cq_head = cpu_to_le16(enet->adminq.ring->cq.head); 465*4c45a51eSXuan Zhuo drv_status->sq_head = cpu_to_le16(enet->adminq.ring->sq.head); 466*4c45a51eSXuan Zhuo 467*4c45a51eSXuan Zhuo err = eea_adminq_exec(enet, EEA_AQ_CMD_DEV_STATUS, req, 468*4c45a51eSXuan Zhuo q_num * sizeof(struct eea_aq_queue_drv_status), 469*4c45a51eSXuan Zhuo rep, size, NULL); 470*4c45a51eSXuan Zhuo kfree(req); 471*4c45a51eSXuan Zhuo if (err) { 472*4c45a51eSXuan Zhuo kfree(rep); 473*4c45a51eSXuan Zhuo return err; 474*4c45a51eSXuan Zhuo } 475*4c45a51eSXuan Zhuo 476*4c45a51eSXuan Zhuo dstatus->num = q_num; 477*4c45a51eSXuan Zhuo dstatus->status = rep; 478*4c45a51eSXuan Zhuo 479*4c45a51eSXuan Zhuo return 0; 480*4c45a51eSXuan Zhuo } 481*4c45a51eSXuan Zhuo 482*4c45a51eSXuan Zhuo void eea_adminq_config_host_info(struct eea_net *enet) 483*4c45a51eSXuan Zhuo { 484*4c45a51eSXuan Zhuo struct device *dev = enet->edev->dma_dev; 485*4c45a51eSXuan Zhuo struct eea_aq_host_info_cfg *cfg; 486*4c45a51eSXuan Zhuo struct eea_aq_host_info_rep *rep; 487*4c45a51eSXuan Zhuo int rc = -ENOMEM; 488*4c45a51eSXuan Zhuo 489*4c45a51eSXuan Zhuo cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 490*4c45a51eSXuan Zhuo if (!cfg) 491*4c45a51eSXuan Zhuo return; 492*4c45a51eSXuan Zhuo 493*4c45a51eSXuan Zhuo rep = kzalloc(sizeof(*rep), GFP_KERNEL); 494*4c45a51eSXuan Zhuo if (!rep) 495*4c45a51eSXuan Zhuo goto err_free_cfg; 496*4c45a51eSXuan Zhuo 497*4c45a51eSXuan Zhuo cfg->os_type = cpu_to_le16(EEA_OS_LINUX); 498*4c45a51eSXuan Zhuo cfg->os_dist = cpu_to_le16(EEA_OS_DISTRO); 499*4c45a51eSXuan Zhuo cfg->drv_type = cpu_to_le16(EEA_DRV_TYPE); 500*4c45a51eSXuan Zhuo 501*4c45a51eSXuan Zhuo cfg->kern_ver_major = cpu_to_le16(LINUX_VERSION_MAJOR); 502*4c45a51eSXuan Zhuo cfg->kern_ver_minor = cpu_to_le16(LINUX_VERSION_PATCHLEVEL); 503*4c45a51eSXuan Zhuo cfg->kern_ver_sub_minor = cpu_to_le16(LINUX_VERSION_SUBLEVEL); 504*4c45a51eSXuan Zhuo 505*4c45a51eSXuan Zhuo cfg->drv_ver_major = cpu_to_le16(EEA_VER_MAJOR); 506*4c45a51eSXuan Zhuo cfg->drv_ver_minor = cpu_to_le16(EEA_VER_MINOR); 507*4c45a51eSXuan Zhuo cfg->drv_ver_sub_minor = cpu_to_le16(EEA_VER_SUB_MINOR); 508*4c45a51eSXuan Zhuo 509*4c45a51eSXuan Zhuo cfg->spec_ver_major = cpu_to_le16(EEA_SPEC_VER_MAJOR); 510*4c45a51eSXuan Zhuo cfg->spec_ver_minor = cpu_to_le16(EEA_SPEC_VER_MINOR); 511*4c45a51eSXuan Zhuo 512*4c45a51eSXuan Zhuo cfg->pci_bdf = cpu_to_le16(eea_pci_bdf(enet->edev)); 513*4c45a51eSXuan Zhuo cfg->pci_domain = cpu_to_le32(eea_pci_domain_nr(enet->edev)); 514*4c45a51eSXuan Zhuo 515*4c45a51eSXuan Zhuo strscpy(cfg->os_ver_str, utsname()->release, sizeof(cfg->os_ver_str)); 516*4c45a51eSXuan Zhuo strscpy(cfg->isa_str, utsname()->machine, sizeof(cfg->isa_str)); 517*4c45a51eSXuan Zhuo 518*4c45a51eSXuan Zhuo rc = eea_adminq_exec(enet, EEA_AQ_CMD_HOST_INFO, 519*4c45a51eSXuan Zhuo cfg, sizeof(*cfg), rep, sizeof(*rep), NULL); 520*4c45a51eSXuan Zhuo 521*4c45a51eSXuan Zhuo if (!rc) { 522*4c45a51eSXuan Zhuo if (rep->op_code == EEA_HINFO_REP_BAD) 523*4c45a51eSXuan Zhuo dev_warn(dev, "The hardware-driven state validation may be abnormal.\n"); 524*4c45a51eSXuan Zhuo 525*4c45a51eSXuan Zhuo if (rep->has_reply) { 526*4c45a51eSXuan Zhuo char buf[EEA_HINFO_MAX_REP_LEN] = {0}; 527*4c45a51eSXuan Zhuo 528*4c45a51eSXuan Zhuo rep->reply_str[EEA_HINFO_MAX_REP_LEN - 1] = '\0'; 529*4c45a51eSXuan Zhuo 530*4c45a51eSXuan Zhuo string_escape_str(rep->reply_str, buf, sizeof(buf), 531*4c45a51eSXuan Zhuo ESCAPE_NP, NULL); 532*4c45a51eSXuan Zhuo 533*4c45a51eSXuan Zhuo buf[EEA_HINFO_MAX_REP_LEN - 1] = '\0'; 534*4c45a51eSXuan Zhuo 535*4c45a51eSXuan Zhuo dev_warn(dev, "Device replied: %s\n", buf); 536*4c45a51eSXuan Zhuo } 537*4c45a51eSXuan Zhuo } 538*4c45a51eSXuan Zhuo 539*4c45a51eSXuan Zhuo kfree(rep); 540*4c45a51eSXuan Zhuo err_free_cfg: 541*4c45a51eSXuan Zhuo kfree(cfg); 542*4c45a51eSXuan Zhuo } 543