iPXE
sfc_hunt.c
Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Device driver for Solarflare Communications EF10 devices
00004  *
00005  * Written by Shradha Shah <sshah@solarflare.com>
00006  *
00007  * Copyright 2012-2017 Solarflare Communications Inc.
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License as
00011  * published by the Free Software Foundation; either version 2 of the
00012  * License, or any later version.
00013  *
00014  * You can also choose to distribute this program under the terms of
00015  * the Unmodified Binary Distribution Licence (as given in the file
00016  * COPYING.UBDL), provided that you have satisfied its requirements.
00017  *
00018  ***************************************************************************/
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <unistd.h>
00022 #include <errno.h>
00023 #include <byteswap.h>
00024 #include <ipxe/io.h>
00025 #include <ipxe/pci.h>
00026 #include <ipxe/malloc.h>
00027 #include <ipxe/ethernet.h>
00028 #include <ipxe/iobuf.h>
00029 #include <ipxe/netdevice.h>
00030 #include "efx_hunt.h"
00031 #include "efx_bitfield.h"
00032 #include "ef10_regs.h"
00033 #include "mc_driver_pcol.h"
00034 #include <ipxe/if_ether.h>
00035 
00036 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00037 
00038 #define HUNTINGTON_NVRAM_CHUNK 0x80
00039 #define HUNTINGTON_NVS_MAX_LENGTH 0x1000
00040 
00041 #define EMCDI_IO(code)  EUNIQ(EINFO_EIO, (code))
00042 
00043 #ifndef MIN
00044 #define MIN(a, b) ((a) < (b) ? (a) : (b))
00045 #endif
00046 #ifndef MAX
00047 #define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
00048 #endif
00049 
00050 struct hunt_nic *primary_nics = NULL;
00051 
00052 struct hunt_nic {
00053         struct efx_nic efx;
00054 
00055         /* PHY information */
00056         unsigned int phy_cap_mask;
00057         unsigned int phy_cap;
00058         unsigned long link_poll_timer;
00059 
00060         /* resource housekeeping */
00061         uint64_t uc_filter_id;
00062         uint64_t mc_filter_id;
00063         u8 mac[ETH_ALEN];
00064 
00065         struct {
00066                 /* Common payload for all MCDI requests */
00067                 unsigned int seqno;
00068 
00069                 size_t resp_hdr_len;
00070                 size_t resp_data_len;
00071 
00072                 struct io_buffer *iob;
00073                 uint64_t dma_addr;
00074         } mcdi;
00075 
00076         struct hunt_nic *primary;
00077         struct hunt_nic *next_primary;
00078         u32 flags;
00079 };
00080 
00081 static int hunt_nic_is_primary(struct hunt_nic *hunt)
00082 {
00083         return (hunt->flags & (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY));
00084 }
00085 
00086 /*******************************************************************************
00087  *
00088  *
00089  * MCDI transport
00090  *
00091  * This has been based on the implementation of MCDI in the common code driver.
00092  *
00093  *
00094  ******************************************************************************/
00095 
00096 static int hunt_mcdi_init(struct hunt_nic *hunt)
00097 {
00098         size_t max_msg_size;
00099         int rc;
00100 
00101         /* The MCDI message has two 32-bit headers (the MCDI header and the
00102          * MCDI v2 extended command) and then up to MCDI_CTL_SDU_LEN_MAX_V2
00103          * bytes of payload
00104          */
00105         max_msg_size = 2 * sizeof(efx_dword_t) + MCDI_CTL_SDU_LEN_MAX_V2;
00106 
00107         hunt->mcdi.iob = alloc_iob(max_msg_size);
00108         if (!hunt->mcdi.iob) {
00109                 rc = -ENOMEM;
00110                 return rc;
00111         }
00112         return 0;
00113 }
00114 
00115 static void hunt_mcdi_copyin(struct hunt_nic *hunt,
00116                              unsigned int cmd,
00117                              uint8_t *inbuf,
00118                              size_t inlen)
00119 {
00120         efx_dword_t hdr[2];
00121         uint32_t seqno;
00122         unsigned int xflags;
00123         size_t hdr_len;
00124         u8 *pdu = hunt->mcdi.iob->data;
00125 
00126         seqno = hunt->mcdi.seqno & MCDI_SEQ_MASK;
00127 
00128         xflags = 0;
00129 
00130         EFX_POPULATE_DWORD_7(hdr[0],
00131                              MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
00132                              MCDI_HEADER_RESYNC, 1,
00133                              MCDI_HEADER_DATALEN, 0,
00134                              MCDI_HEADER_SEQ, seqno,
00135                              MCDI_HEADER_ERROR, 0,
00136                              MCDI_HEADER_RESPONSE, 0,
00137                              MCDI_HEADER_XFLAGS, xflags);
00138         EFX_POPULATE_DWORD_2(hdr[1],
00139                              MC_CMD_V2_EXTN_IN_EXTENDED_CMD, cmd,
00140                              MC_CMD_V2_EXTN_IN_ACTUAL_LEN, inlen);
00141 
00142         hdr_len = sizeof(hdr);
00143 
00144         memcpy(pdu, &hdr, hdr_len);
00145         assert(inlen <= MCDI_CTL_SDU_LEN_MAX_V2);
00146         memcpy(pdu + hdr_len, inbuf, inlen);
00147 
00148         wmb();  /* Sync the data before ringing the doorbell */
00149 
00150         /* Ring the doorbell to post the command DMA address to the MC */
00151         hunt->mcdi.dma_addr = virt_to_bus(hunt->mcdi.iob->data);
00152 
00153         assert((hunt->mcdi.dma_addr & 0xFF) == 0);
00154 
00155         _efx_writel(&hunt->efx,
00156                    cpu_to_le32((u64)hunt->mcdi.dma_addr >> 32),
00157                    ER_DZ_MC_DB_LWRD);
00158 
00159         _efx_writel(&hunt->efx,
00160                    cpu_to_le32((u32)hunt->mcdi.dma_addr),
00161                    ER_DZ_MC_DB_HWRD);
00162 }
00163 
00164 static void hunt_mcdi_copyout(struct hunt_nic *hunt,
00165                               uint8_t *outbuf, size_t outlen)
00166 {
00167         size_t offset;
00168         const u8 *pdu = hunt->mcdi.iob->data;
00169 
00170         offset =  hunt->mcdi.resp_hdr_len;
00171 
00172         if (outlen > 0)
00173                 memcpy(outbuf, pdu+offset, outlen);
00174 }
00175 
00176 static int hunt_mcdi_request_poll(struct hunt_nic *hunt, bool quiet)
00177 {
00178         unsigned int resplen, respseq, error;
00179         unsigned long finish;
00180         efx_dword_t errdword;
00181         efx_qword_t qword;
00182         const efx_dword_t *pdu = hunt->mcdi.iob->data;
00183         const u8 *pdu1 = hunt->mcdi.iob->data;
00184         int delay, rc;
00185 
00186         /* Spin for up to 5s, polling at intervals of 10us, 20us, ... ~100ms  */
00187         finish = currticks() + (5 * TICKS_PER_SEC);
00188         delay = 10;
00189         while (1) {
00190                 udelay(delay);
00191 
00192                 /* Check for an MCDI response */
00193                 if (EFX_DWORD_FIELD(*pdu, MCDI_HEADER_RESPONSE))
00194                         break;
00195 
00196                 if (currticks() >= finish)
00197                         return -ETIMEDOUT;
00198 
00199                 if (delay < 100000)
00200                         delay *= 2;
00201         }
00202 
00203         memcpy(&qword, pdu1, 8);
00204 
00205         /* qword.dword[0] is the MCDI header; qword.dword[1] is the MCDI v2
00206          * extended command
00207          */
00208         respseq = EFX_DWORD_FIELD(qword.dword[0], MCDI_HEADER_SEQ);
00209         error = EFX_DWORD_FIELD(qword.dword[0], MCDI_HEADER_ERROR);
00210         resplen = EFX_DWORD_FIELD(qword.dword[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
00211 
00212         if (error && resplen == 0) {
00213                 if (!quiet)
00214                         DBGC(hunt, "MC rebooted\n");
00215                 return -EIO;
00216         } else if ((respseq ^ hunt->mcdi.seqno) & MCDI_SEQ_MASK) {
00217                 if (!quiet)
00218                         DBGC(hunt, "MC response mismatch rxseq 0x%x txseq "
00219                              "0x%x\n", respseq, hunt->mcdi.seqno);
00220                 return -EIO;
00221         } else if (error) {
00222                 memcpy(&errdword, pdu1 + 8, 4);
00223                 rc = EFX_DWORD_FIELD(errdword, EFX_DWORD_0);
00224                 switch (rc) {
00225                 case MC_CMD_ERR_ENOENT:
00226                         return -ENOENT;
00227                 case MC_CMD_ERR_EINTR:
00228                         return -EINTR;
00229                 case MC_CMD_ERR_EACCES:
00230                         return -EACCES;
00231                 case MC_CMD_ERR_EBUSY:
00232                         return -EBUSY;
00233                 case MC_CMD_ERR_EINVAL:
00234                         return -EINVAL;
00235                 case MC_CMD_ERR_EDEADLK:
00236                         return -EDEADLK;
00237                 case MC_CMD_ERR_ENOSYS:
00238                         return -ENOSYS;
00239                 case MC_CMD_ERR_ETIME:
00240                         return -ETIME;
00241                 case MC_CMD_ERR_EPERM:
00242                         return -EPERM;
00243                 default:
00244                         /* Return the MC error in an I/O error. */
00245                         return EMCDI_IO(rc & 0xff);
00246                 }
00247         }
00248         hunt->mcdi.resp_hdr_len = 8;
00249         hunt->mcdi.resp_data_len = resplen;
00250 
00251         return 0;
00252 }
00253 
00254 static void hunt_mcdi_fini(struct hunt_nic *hunt)
00255 {
00256         free_iob(hunt->mcdi.iob);
00257 }
00258 
00259 int _hunt_mcdi(struct efx_nic *efx, unsigned int cmd,
00260                const efx_dword_t *inbuf, size_t inlen,
00261                efx_dword_t *outbuf, size_t outlen,
00262                size_t *outlen_actual, bool quiet)
00263 {
00264         int rc;
00265         struct hunt_nic *hunt = (struct hunt_nic *) efx;
00266         size_t local_outlen_actual;
00267 
00268         if (outlen_actual == NULL)
00269                 outlen_actual = &local_outlen_actual;
00270 
00271         ++hunt->mcdi.seqno;
00272         hunt_mcdi_copyin(hunt, cmd, (uint8_t *) inbuf, inlen);
00273 
00274         rc = hunt_mcdi_request_poll(hunt, quiet);
00275         if (rc != 0) {
00276                 if (!quiet)
00277                         DBGC(hunt, "MC response to cmd 0x%x: %s\n",
00278                              cmd, strerror(rc));
00279                 return rc;
00280         }
00281 
00282         *outlen_actual = hunt->mcdi.resp_data_len;
00283 
00284         hunt_mcdi_copyout(hunt, (uint8_t *) outbuf, outlen);
00285 
00286         return 0;
00287 }
00288 
00289 static int hunt_mcdi(struct hunt_nic *hunt, struct efx_mcdi_req_s *req)
00290 {
00291         return _hunt_mcdi(&hunt->efx, req->emr_cmd,
00292                           (const efx_dword_t *) req->emr_in_buf,
00293                           req->emr_in_length,
00294                           (efx_dword_t *) req->emr_out_buf, req->emr_out_length,
00295                           &req->emr_out_length_used, false);
00296 }
00297 
00298 static int hunt_mcdi_quiet(struct hunt_nic *hunt, struct efx_mcdi_req_s *req)
00299 {
00300         return _hunt_mcdi(&hunt->efx, req->emr_cmd,
00301                           (const efx_dword_t *) req->emr_in_buf,
00302                           req->emr_in_length,
00303                           (efx_dword_t *) req->emr_out_buf, req->emr_out_length,
00304                           &req->emr_out_length_used, true);
00305 }
00306 
00307 /*******************************************************************************
00308  *
00309  *
00310  * Hardware initialization
00311  *
00312  *
00313  ******************************************************************************/
00314 static int hunt_get_workarounds(struct hunt_nic *hunt, uint32_t *implemented,
00315                                 uint32_t *enabled)
00316 {
00317         struct efx_mcdi_req_s req;
00318         MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_WORKAROUNDS_OUT_LEN);
00319         int rc;
00320 
00321         *implemented = *enabled = 0;
00322 
00323         req.emr_cmd = MC_CMD_GET_WORKAROUNDS;
00324         req.emr_in_buf = NULL;
00325         req.emr_in_length = 0;
00326         req.emr_out_buf = outbuf;
00327         req.emr_out_length = sizeof(outbuf);
00328 
00329         rc = hunt_mcdi(hunt, &req);
00330 
00331         if (rc)
00332                 return rc;
00333 
00334         if (req.emr_out_length_used < MC_CMD_GET_WORKAROUNDS_OUT_LEN)
00335                 return -EMSGSIZE;
00336 
00337         *implemented = MCDI_DWORD(outbuf, GET_WORKAROUNDS_OUT_IMPLEMENTED);
00338         *enabled = MCDI_DWORD(outbuf, GET_WORKAROUNDS_OUT_ENABLED);
00339         return 0;
00340 }
00341 
00342 static int hunt_enable_workaround_35388(struct hunt_nic *hunt)
00343 {
00344         struct efx_mcdi_req_s req;
00345         MCDI_DECLARE_BUF(payload, MC_CMD_WORKAROUND_IN_LEN);
00346 
00347         req.emr_cmd = MC_CMD_WORKAROUND;
00348         req.emr_in_buf = payload;
00349         req.emr_in_length = MC_CMD_WORKAROUND_IN_LEN;
00350         req.emr_out_buf = NULL;
00351         req.emr_out_length = 0;
00352 
00353         MCDI_SET_DWORD(req.emr_in_buf, WORKAROUND_IN_TYPE,
00354                        MC_CMD_WORKAROUND_BUG35388);
00355         MCDI_SET_DWORD(req.emr_in_buf, WORKAROUND_IN_ENABLED, 1);
00356 
00357         /* If the firmware doesn't support this workaround, hunt_mcdi() will
00358          * return -EINVAL from hunt_mcdi_request_poll().
00359          */
00360         return hunt_mcdi(hunt, &req);
00361 }
00362 
00363 static int hunt_workaround_35388(struct hunt_nic *hunt)
00364 {
00365         uint32_t implemented, enabled;
00366         int rc = hunt_get_workarounds(hunt, &implemented, &enabled);
00367 
00368         if (rc < 0)
00369                 return 0;
00370         if (!(implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388))
00371                 return 0;
00372         if (enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388)
00373                 return 1;
00374 
00375         rc = hunt_enable_workaround_35388(hunt);
00376         if (rc == 0)
00377                 return 1; /* Workaround is enabled */
00378         else
00379                 return 0;
00380 }
00381 
00382 static int hunt_get_port_assignment(struct hunt_nic *hunt)
00383 {
00384         struct efx_mcdi_req_s req;
00385         MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
00386         int rc;
00387 
00388         req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
00389         req.emr_in_buf = NULL;
00390         req.emr_in_length = 0;
00391         req.emr_out_buf = outbuf;
00392         req.emr_out_length = sizeof(outbuf);
00393 
00394         rc = hunt_mcdi(hunt, &req);
00395         if (rc != 0)
00396                 return rc;
00397 
00398         hunt->efx.port = MCDI_DWORD(req.emr_out_buf,
00399                                     GET_PORT_ASSIGNMENT_OUT_PORT);
00400         return 0;
00401 }
00402 
00403 static int hunt_mac_addr(struct hunt_nic *hunt, uint8_t *ll_addr)
00404 {
00405         struct efx_mcdi_req_s req;
00406         MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
00407         int rc;
00408 
00409         req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
00410         req.emr_in_buf = NULL;
00411         req.emr_in_length = 0;
00412         req.emr_out_buf = outbuf;
00413         req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
00414 
00415         rc = hunt_mcdi(hunt, &req);
00416         if (rc != 0)
00417                 return rc;
00418 
00419         if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)
00420                 return -EMSGSIZE;
00421 
00422         memcpy(ll_addr,
00423                MCDI_PTR(req.emr_out_buf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE),
00424                ETH_ALEN);
00425 
00426         return 0;
00427 }
00428 
00429 static int hunt_get_phy_cfg(struct hunt_nic *hunt)
00430 {
00431         struct efx_mcdi_req_s req;
00432         MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_CFG_OUT_LEN);
00433         int rc;
00434 
00435         req.emr_cmd = MC_CMD_GET_PHY_CFG;
00436         req.emr_in_buf = NULL;
00437         req.emr_in_length = 0;
00438         req.emr_out_buf = outbuf;
00439         req.emr_out_length = sizeof(outbuf);
00440 
00441         rc = hunt_mcdi(hunt, &req);
00442         if (rc != 0)
00443                 return rc;
00444 
00445         if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN)
00446                 return -EMSGSIZE;
00447 
00448         hunt->phy_cap_mask = hunt->phy_cap =
00449                 MCDI_DWORD(req.emr_out_buf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
00450         DBGC2(hunt, "GET_PHY_CFG: flags=%x, caps=%x\n", rc, hunt->phy_cap);
00451         return 0;
00452 }
00453 
00454 static int hunt_driver_attach(struct hunt_nic *hunt, int attach)
00455 {
00456         struct efx_mcdi_req_s req;
00457         MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
00458         MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_EXT_OUT_LEN);
00459         int rc;
00460 
00461         req.emr_cmd = MC_CMD_DRV_ATTACH;
00462         req.emr_in_buf = inbuf;
00463         req.emr_in_length = sizeof(inbuf);
00464         req.emr_out_buf = outbuf;
00465         req.emr_out_length = sizeof(outbuf);
00466 
00467         /* Set the PREBOOT flag to indicate later instances of attach should
00468          * force an ENTITY RESET
00469          */
00470         if (attach)
00471                 attach |= 1 << MC_CMD_DRV_PREBOOT_LBN;
00472 
00473         MCDI_SET_DWORD(req.emr_in_buf, DRV_ATTACH_IN_NEW_STATE, attach);
00474         MCDI_SET_DWORD(req.emr_in_buf, DRV_ATTACH_IN_UPDATE, 1);
00475         MCDI_SET_DWORD(req.emr_in_buf, DRV_ATTACH_IN_FIRMWARE_ID,
00476                        MC_CMD_FW_DONT_CARE);
00477 
00478         rc = hunt_mcdi(hunt, &req);
00479         if (rc != 0)
00480                 return rc;
00481 
00482         if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN)
00483                 return -EMSGSIZE;
00484 
00485         hunt->flags = MCDI_DWORD(outbuf, DRV_ATTACH_EXT_OUT_FUNC_FLAGS);
00486 
00487         return 0;
00488 }
00489 
00490 static int hunt_reset(struct hunt_nic *hunt)
00491 {
00492         struct efx_mcdi_req_s req;
00493         MCDI_DECLARE_BUF(inbuf, MC_CMD_ENTITY_RESET_IN_LEN);
00494 
00495         req.emr_cmd = MC_CMD_ENTITY_RESET;
00496         req.emr_in_buf = inbuf;
00497         req.emr_in_length = sizeof(inbuf);
00498         req.emr_out_buf = NULL;
00499         req.emr_out_length = 0;
00500 
00501         MCDI_POPULATE_DWORD_1(req.emr_in_buf, ENTITY_RESET_IN_FLAG,
00502                               ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
00503         return hunt_mcdi(hunt, &req);
00504 }
00505 
00506 static void hunt_clear_udp_tunnel_ports(struct hunt_nic *hunt)
00507 {
00508         MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX);
00509         MCDI_DECLARE_BUF(outbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN);
00510         struct efx_mcdi_req_s req;
00511         int rc;
00512 
00513         memset(inbuf, 0, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX);
00514         MCDI_SET_DWORD(inbuf, SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS,
00515                 (1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING_LBN));
00516 
00517         req.emr_cmd = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS;
00518         req.emr_in_buf = inbuf;
00519         req.emr_in_length = sizeof(inbuf);
00520         req.emr_out_buf = outbuf;
00521         req.emr_out_length = sizeof(outbuf);
00522 
00523         rc = hunt_mcdi_quiet(hunt, &req);
00524         if (rc)
00525                 return;
00526 
00527         if (MCDI_DWORD(outbuf, SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS) &
00528             (1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING_LBN)) {
00529                 DBGC(hunt,
00530                      "Rebooting MC due to clearing UDP tunnel port list\n");
00531                 /* Delay for the MC reboot to complete. */
00532                 mdelay(100);
00533         }
00534 }
00535 
00536 static int hunt_set_mac(struct hunt_nic *hunt)
00537 {
00538         struct net_device *netdev = hunt->efx.netdev;
00539         struct efx_mcdi_req_s req;
00540         MCDI_DECLARE_BUF(payload, MC_CMD_SET_MAC_IN_LEN);
00541         unsigned int fcntl;
00542         int rc;
00543 
00544         req.emr_cmd = MC_CMD_SET_MAC;
00545         req.emr_in_buf = payload;
00546         req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
00547         req.emr_out_buf = NULL;
00548         req.emr_out_length = 0;
00549 
00550         MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_MTU,
00551                        EFX_MAC_FRAME_LEN(ETH_FRAME_LEN));
00552         MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_DRAIN, 0);
00553         memcpy(MCDI_PTR(req.emr_in_buf, SET_MAC_IN_ADDR),
00554                netdev->ll_addr, ETH_ALEN);
00555         MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_REJECT, 0);
00556 
00557         /* If the PHY supports autnegotiation, then configure the MAC to match
00558          * the negotiated settings. Otherwise force the MAC to TX and RX flow
00559          * control.
00560          */
00561         if (hunt->phy_cap_mask & (1 << MC_CMD_PHY_CAP_AN_LBN))
00562                 fcntl = MC_CMD_FCNTL_AUTO;
00563         else
00564                 fcntl = MC_CMD_FCNTL_BIDIR;
00565         MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_FCNTL, fcntl);
00566 
00567         rc = hunt_mcdi(hunt, &req);
00568         /* Ignore failure for permissions reasons */
00569         if (rc == -EPERM)
00570                 rc = 0;
00571         return rc;
00572 }
00573 
00574 static int hunt_alloc_vis(struct hunt_nic *hunt)
00575 {
00576         struct efx_mcdi_req_s req;
00577         MCDI_DECLARE_BUF(inbuf, MC_CMD_ALLOC_VIS_IN_LEN);
00578 
00579         req.emr_cmd = MC_CMD_ALLOC_VIS;
00580         req.emr_in_buf = inbuf;
00581         req.emr_in_length = sizeof(inbuf);
00582         req.emr_out_buf = NULL;
00583         req.emr_out_length = 0;
00584 
00585         MCDI_SET_DWORD(req.emr_in_buf, ALLOC_VIS_IN_MIN_VI_COUNT, 1);
00586         MCDI_SET_DWORD(req.emr_in_buf, ALLOC_VIS_IN_MAX_VI_COUNT, 1);
00587 
00588         return hunt_mcdi(hunt, &req);
00589 }
00590 
00591 static void hunt_free_vis(struct hunt_nic *hunt)
00592 {
00593         struct efx_mcdi_req_s req;
00594         int rc;
00595 
00596         req.emr_cmd = MC_CMD_FREE_VIS;
00597         req.emr_in_buf = NULL;
00598         req.emr_in_length = 0;
00599         req.emr_out_buf = NULL;
00600         req.emr_out_length = 0;
00601 
00602         rc = hunt_mcdi(hunt, &req);
00603         if (rc != 0)
00604                 DBGC(hunt, "MC_CMD_FREE_VIS Failed\n");
00605 }
00606 
00607 /*******************************************************************************
00608  *
00609  *
00610  * Link state handling
00611  *
00612  *
00613  ******************************************************************************/
00614 static int hunt_check_link(struct hunt_nic *hunt)
00615 {
00616         struct efx_mcdi_req_s req;
00617         MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
00618         unsigned int flags, speed;
00619         bool up;
00620         int rc;
00621         static bool link_state = false;
00622 
00623         req.emr_cmd = MC_CMD_GET_LINK;
00624         req.emr_in_buf = NULL;
00625         req.emr_in_length = 0;
00626         req.emr_out_buf = outbuf;
00627         req.emr_out_length = sizeof(outbuf);
00628 
00629         rc = hunt_mcdi(hunt, &req);
00630         if (rc != 0)
00631                 return rc;
00632 
00633         if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_LEN)
00634                 return -EMSGSIZE;
00635 
00636         flags = MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_FLAGS);
00637         up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
00638         speed = MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_LINK_SPEED);
00639 
00640         /* Set netdev_link_*() based on the link status from the MC */
00641         if (up && speed)
00642                 netdev_link_up(hunt->efx.netdev);
00643         else
00644                 netdev_link_down(hunt->efx.netdev);
00645 
00646         if (up != link_state) {
00647                 DBGC(hunt, "Link %s, flags=%x, our caps=%x, lpa=%x, speed=%d, fcntl=%x, mac_fault=%x\n",
00648                      (up? "up": "down"), flags,
00649                      MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_CAP),
00650                      MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_LP_CAP),
00651                      speed,
00652                      MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_FCNTL),
00653                      MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_MAC_FAULT));
00654                 link_state = up;
00655         }
00656 
00657         return 0;
00658 }
00659 
00660 #define MCDI_PORT_SPEED_CAPS   ((1 << MC_CMD_PHY_CAP_10HDX_LBN) | \
00661                                 (1 << MC_CMD_PHY_CAP_10FDX_LBN) | \
00662                                 (1 << MC_CMD_PHY_CAP_100HDX_LBN) | \
00663                                 (1 << MC_CMD_PHY_CAP_100FDX_LBN) | \
00664                                 (1 << MC_CMD_PHY_CAP_1000HDX_LBN) | \
00665                                 (1 << MC_CMD_PHY_CAP_1000FDX_LBN) | \
00666                                 (1 << MC_CMD_PHY_CAP_10000FDX_LBN) | \
00667                                 (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
00668 
00669 /*******************************************************************************
00670  *
00671  *
00672  * TX
00673  *
00674  *
00675  ******************************************************************************/
00676 static int
00677 hunt_tx_init(struct net_device *netdev, struct hunt_nic *hunt)
00678 {
00679         struct efx_mcdi_req_s req;
00680         dma_addr_t dma_addr;
00681         efx_qword_t *addr;
00682         MCDI_DECLARE_BUF(inbuf,
00683                          MC_CMD_INIT_TXQ_IN_LEN(EFX_TXQ_NBUFS(EFX_TXD_SIZE)));
00684         int rc, npages;
00685 
00686         rc = efx_hunt_tx_init(netdev, &dma_addr);
00687         if (rc != 0)
00688                 return rc;
00689 
00690         npages = EFX_TXQ_NBUFS(EFX_TXD_SIZE);
00691 
00692         req.emr_cmd = MC_CMD_INIT_TXQ;
00693         req.emr_in_buf = inbuf;
00694         req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages);
00695         req.emr_out_buf = NULL;
00696         req.emr_out_length = 0;
00697 
00698         MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_SIZE, EFX_TXD_SIZE);
00699         MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_TARGET_EVQ, 0);
00700         MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_LABEL, 0);
00701         MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_INSTANCE, 0);
00702 
00703         MCDI_POPULATE_DWORD_6(req.emr_in_buf, INIT_TXQ_IN_FLAGS,
00704                               INIT_TXQ_IN_FLAG_BUFF_MODE, 0,
00705                               INIT_TXQ_IN_FLAG_IP_CSUM_DIS, 1,
00706                               INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, 1,
00707                               INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0,
00708                               INIT_TXQ_IN_CRC_MODE, 0,
00709                               INIT_TXQ_IN_FLAG_TIMESTAMP, 0);
00710 
00711         MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_OWNER_ID, 0);
00712         MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_PORT_ID,
00713                        EVB_PORT_ID_ASSIGNED);
00714 
00715         addr = (efx_qword_t *) MCDI_PTR(req.emr_in_buf, INIT_TXQ_IN_DMA_ADDR);
00716 
00717         EFX_POPULATE_QWORD_2(*addr,
00718                              EFX_DWORD_1, (uint32_t)(dma_addr >> 32),
00719                              EFX_DWORD_0, (uint32_t)(dma_addr & 0xffffffff));
00720 
00721         return hunt_mcdi(hunt, &req);
00722 }
00723 
00724 static void hunt_tx_fini(struct hunt_nic *hunt)
00725 {
00726         struct efx_mcdi_req_s req;
00727         MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_TXQ_IN_LEN);
00728         struct efx_nic *efx = &hunt->efx;
00729         struct efx_tx_queue *txq = &efx->txq;
00730         int rc;
00731 
00732         req.emr_cmd = MC_CMD_FINI_TXQ;
00733         req.emr_in_buf = inbuf;
00734         req.emr_in_length = sizeof(inbuf);
00735         req.emr_out_buf = NULL;
00736         req.emr_out_length = 0;
00737 
00738         MCDI_SET_DWORD(req.emr_in_buf, FINI_TXQ_IN_INSTANCE, 0);
00739 
00740         rc = hunt_mcdi(hunt, &req);
00741         if (rc != 0)
00742                 DBGC(hunt, "MC_CMD_FINI_TXQ Failed\n");
00743 
00744         efx_hunt_free_special_buffer(txq->ring,
00745                                      sizeof(efx_tx_desc_t) * EFX_TXD_SIZE);
00746         txq->ring = NULL;
00747 }
00748 
00749 /*******************************************************************************
00750  *
00751  *
00752  * RX
00753  *
00754  *
00755  ******************************************************************************/
00756 static int hunt_rx_filter_insert(struct net_device *netdev,
00757                                  struct hunt_nic *hunt,
00758                                  int multicast)
00759 {
00760         struct efx_mcdi_req_s req;
00761         MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
00762         MCDI_DECLARE_BUF(outbuf, MC_CMD_FILTER_OP_OUT_LEN);
00763         int rc;
00764         uint64_t filter_id;
00765         (void) netdev;
00766 
00767         req.emr_cmd = MC_CMD_FILTER_OP;
00768         req.emr_in_buf = inbuf;
00769         req.emr_in_length = sizeof(inbuf);
00770         req.emr_out_buf = outbuf;
00771         req.emr_out_length = sizeof(outbuf);
00772 
00773         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_OP,
00774                        multicast ? MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE
00775                                  : MC_CMD_FILTER_OP_IN_OP_INSERT);
00776         MCDI_POPULATE_DWORD_1(req.emr_in_buf, FILTER_OP_IN_MATCH_FIELDS,
00777                               FILTER_OP_IN_MATCH_DST_MAC, 1);
00778         if (multicast)
00779                 memset(MCDI_PTR(req.emr_in_buf, FILTER_OP_IN_DST_MAC),
00780                        0xff, ETH_ALEN);
00781         else
00782                 memcpy(MCDI_PTR(req.emr_in_buf, FILTER_OP_IN_DST_MAC),
00783                        hunt->mac, ETH_ALEN);
00784 
00785         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_PORT_ID,
00786                        EVB_PORT_ID_ASSIGNED);
00787         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_RX_DEST,
00788                         MC_CMD_FILTER_OP_IN_RX_DEST_HOST);
00789         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_RX_QUEUE, 0);
00790         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_RX_MODE, 0);
00791         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_TX_DEST,
00792                        MC_CMD_FILTER_OP_IN_TX_DEST_DEFAULT);
00793 
00794         rc = hunt_mcdi(hunt, &req);
00795         if (rc != 0)
00796                 return rc;
00797 
00798         if (req.emr_out_length_used <  MC_CMD_FILTER_OP_OUT_LEN)
00799                 return -EIO;
00800 
00801         filter_id = MCDI_QWORD(req.emr_out_buf, FILTER_OP_OUT_HANDLE);
00802         if (multicast)
00803                 hunt->mc_filter_id = filter_id;
00804         else
00805                 hunt->uc_filter_id = filter_id;
00806 
00807         return 0;
00808 }
00809 
00810 static int hunt_rx_filter_remove(struct hunt_nic *hunt,
00811                                  int multicast)
00812 {
00813         struct efx_mcdi_req_s req;
00814         MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
00815 
00816         req.emr_cmd = MC_CMD_FILTER_OP;
00817         req.emr_in_buf = inbuf;
00818         req.emr_in_length = sizeof(inbuf);
00819         req.emr_out_buf = NULL;
00820         req.emr_out_length = 0;
00821 
00822         MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_OP,
00823                        multicast ? MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE :
00824                        MC_CMD_FILTER_OP_IN_OP_REMOVE);
00825         MCDI_SET_QWORD(req.emr_in_buf, FILTER_OP_IN_HANDLE,
00826                           multicast ? hunt->mc_filter_id :
00827                                       hunt->uc_filter_id);
00828         return hunt_mcdi(hunt, &req);
00829 }
00830 
00831 static int hunt_get_mac(struct hunt_nic *hunt)
00832 {
00833         struct efx_mcdi_req_s req;
00834         MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
00835         int rc;
00836 
00837         req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
00838         req.emr_in_buf = NULL;
00839         req.emr_in_length = 0;
00840         req.emr_out_buf = outbuf;
00841         req.emr_out_length = sizeof(outbuf);
00842 
00843         rc = hunt_mcdi(hunt, &req);
00844         if (rc != 0)
00845                 return rc;
00846 
00847         if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN)
00848                 return -EMSGSIZE;
00849 
00850         memcpy(hunt->mac, MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE),
00851                ETH_ALEN);
00852         return 0;
00853 }
00854 
00855 static int hunt_rx_filter_init(struct net_device *netdev,
00856                                struct hunt_nic *hunt)
00857 {
00858         int rc = hunt_get_mac(hunt);
00859 
00860         if (rc != 0)
00861                 return rc;
00862 
00863         rc = hunt_rx_filter_insert(netdev, hunt, 0);
00864         if (rc != 0)
00865                 return rc;
00866 
00867         rc = hunt_rx_filter_insert(netdev, hunt, 1);
00868         if (rc != 0)
00869                 hunt_rx_filter_remove(hunt, 0);
00870 
00871         return rc;
00872 }
00873 
00874 static int
00875 hunt_rx_init(struct net_device *netdev,
00876              struct hunt_nic *hunt)
00877 {
00878         struct efx_mcdi_req_s req;
00879         dma_addr_t dma_addr;
00880         efx_qword_t *addr;
00881         MCDI_DECLARE_BUF(inbuf,
00882                          MC_CMD_INIT_RXQ_IN_LEN(EFX_RXQ_NBUFS(EFX_RXD_SIZE)));
00883         int rc, npages;
00884 
00885         rc = efx_hunt_rx_init(netdev, &dma_addr);
00886         if (rc != 0)
00887                 return rc;
00888 
00889         npages = EFX_RXQ_NBUFS(EFX_RXD_SIZE);
00890 
00891         req.emr_cmd = MC_CMD_INIT_RXQ;
00892         req.emr_in_buf = inbuf;
00893         req.emr_in_length = MC_CMD_INIT_RXQ_IN_LEN(npages);
00894         req.emr_out_buf = NULL;
00895         req.emr_out_length = 0;
00896 
00897         MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_SIZE, EFX_RXD_SIZE);
00898         MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_TARGET_EVQ, 0);
00899         MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_LABEL, 0);
00900         MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_INSTANCE, 0);
00901         MCDI_POPULATE_DWORD_5(req.emr_in_buf, INIT_RXQ_IN_FLAGS,
00902                                  INIT_RXQ_IN_FLAG_BUFF_MODE, 0,
00903                                  INIT_RXQ_IN_FLAG_HDR_SPLIT, 0,
00904                                  INIT_RXQ_IN_FLAG_TIMESTAMP, 0,
00905                                  INIT_RXQ_IN_CRC_MODE, 0,
00906                                  INIT_RXQ_IN_FLAG_PREFIX, 1);
00907         MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_OWNER_ID, 0);
00908         MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_PORT_ID,
00909                        EVB_PORT_ID_ASSIGNED);
00910 
00911         addr = (efx_qword_t *) MCDI_PTR(req.emr_in_buf, INIT_RXQ_IN_DMA_ADDR);
00912 
00913         EFX_POPULATE_QWORD_2(*addr,
00914                              EFX_DWORD_1, (uint32_t)(dma_addr >> 32),
00915                              EFX_DWORD_0, (uint32_t)(dma_addr & 0xffffffff));
00916         return hunt_mcdi(hunt, &req);
00917 }
00918 
00919 static void hunt_rx_filter_fini(struct hunt_nic *hunt)
00920 {
00921         hunt_rx_filter_remove(hunt, 0);
00922         hunt_rx_filter_remove(hunt, 1);
00923 }
00924 
00925 static void hunt_rx_fini(struct hunt_nic *hunt)
00926 {
00927         MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_RXQ_IN_LEN);
00928         struct efx_mcdi_req_s req;
00929         struct efx_nic *efx = &hunt->efx;
00930         struct efx_rx_queue *rxq = &efx->rxq;
00931         int rc;
00932 
00933         req.emr_cmd = MC_CMD_FINI_RXQ;
00934         req.emr_in_buf = inbuf;
00935         req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN;
00936         req.emr_out_buf = NULL;
00937         req.emr_out_length = 0;
00938 
00939         MCDI_SET_DWORD(req.emr_in_buf, FINI_RXQ_IN_INSTANCE, 0);
00940 
00941         rc = hunt_mcdi(hunt, &req);
00942         if (rc != 0)
00943                 DBGC(hunt, "MC_CMD_FINI_RXQ Failed\n");
00944 
00945         efx_hunt_free_special_buffer(rxq->ring,
00946                                      sizeof(efx_rx_desc_t) * EFX_RXD_SIZE);
00947         rxq->ring = NULL;
00948 }
00949 
00950 /*******************************************************************************
00951  *
00952  *
00953  * Event queues and interrupts
00954  *
00955  *
00956  ******************************************************************************/
00957 static int
00958 hunt_ev_init(struct net_device *netdev,
00959              struct hunt_nic *hunt)
00960 {
00961         struct efx_mcdi_req_s req;
00962         dma_addr_t dma_addr;
00963         efx_qword_t *addr;
00964         MCDI_DECLARE_BUF(inbuf,
00965                          MC_CMD_INIT_EVQ_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_SIZE)));
00966         MCDI_DECLARE_BUF(outbuf, MC_CMD_INIT_EVQ_OUT_LEN);
00967         int rc, npages;
00968 
00969         rc = efx_hunt_ev_init(netdev, &dma_addr);
00970         if (rc != 0)
00971                 return rc;
00972 
00973         npages = EFX_EVQ_NBUFS(EFX_EVQ_SIZE);
00974 
00975         req.emr_cmd = MC_CMD_INIT_EVQ;
00976         req.emr_in_buf = inbuf;
00977         req.emr_in_length = MC_CMD_INIT_EVQ_IN_LEN(npages);
00978         req.emr_out_buf = outbuf;
00979         req.emr_out_length = sizeof(outbuf);
00980 
00981         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_SIZE, EFX_EVQ_SIZE);
00982         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_INSTANCE, 0);
00983         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_IRQ_NUM, 0);
00984 
00985         MCDI_POPULATE_DWORD_6(req.emr_in_buf, INIT_EVQ_IN_FLAGS,
00986                                  INIT_EVQ_IN_FLAG_INTERRUPTING, 1,
00987                                  INIT_EVQ_IN_FLAG_RPTR_DOS, 0,
00988                                  INIT_EVQ_IN_FLAG_INT_ARMD, 0,
00989                                  INIT_EVQ_IN_FLAG_CUT_THRU, 0,
00990                                  INIT_EVQ_IN_FLAG_RX_MERGE, 0,
00991                                  INIT_EVQ_IN_FLAG_TX_MERGE, 0);
00992 
00993         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_TMR_MODE,
00994                           MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
00995         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_TMR_LOAD, 0);
00996         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_TMR_RELOAD, 0);
00997 
00998         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_COUNT_MODE,
00999                           MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS);
01000         MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_COUNT_THRSHLD, 0);
01001 
01002         addr = (efx_qword_t *) MCDI_PTR(req.emr_in_buf, INIT_EVQ_IN_DMA_ADDR);
01003 
01004         EFX_POPULATE_QWORD_2(*addr,
01005                              EFX_DWORD_1, (uint32_t)(dma_addr >> 32),
01006                              EFX_DWORD_0, (uint32_t)(dma_addr & 0xffffffff));
01007         rc = hunt_mcdi(hunt, &req);
01008         if (rc != 0)
01009                 return rc;
01010 
01011         if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN)
01012                 return -EMSGSIZE;
01013 
01014         return 0;
01015 }
01016 
01017 static void hunt_ev_fini(struct hunt_nic *hunt)
01018 {
01019         MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_EVQ_IN_LEN);
01020         struct efx_mcdi_req_s req;
01021         struct efx_nic *efx = &hunt->efx;
01022         struct efx_ev_queue *evq = &efx->evq;
01023         int rc;
01024 
01025         req.emr_cmd = MC_CMD_FINI_EVQ;
01026         req.emr_in_buf = inbuf;
01027         req.emr_in_length = sizeof(inbuf);
01028         req.emr_out_buf = NULL;
01029         req.emr_out_length = 0;
01030 
01031         MCDI_SET_DWORD(req.emr_in_buf, FINI_EVQ_IN_INSTANCE, 0);
01032 
01033         rc = hunt_mcdi(hunt, &req);
01034         if (rc != 0)
01035                 DBGC(hunt, "MC_CMD_FINI_EVQ Failed\n");
01036 
01037         efx_hunt_free_special_buffer(evq->ring,
01038                                      sizeof(efx_event_t) * EFX_EVQ_SIZE);
01039         evq->ring = NULL;
01040 }
01041 
01042 static void
01043 hunt_poll(struct net_device *netdev)
01044 {
01045         struct hunt_nic *hunt = netdev_priv(netdev);
01046 
01047         /* If called while already polling, return immediately */
01048         if (hunt->efx.state & EFX_STATE_POLLING)
01049                 return;
01050         hunt->efx.state |= EFX_STATE_POLLING;
01051 
01052         /* Poll link state */
01053         if (hunt->link_poll_timer + TICKS_PER_SEC < currticks()) {
01054                 hunt->link_poll_timer = currticks();
01055                 hunt_check_link(hunt);
01056         }
01057 
01058         /* Poll data path */
01059         efx_hunt_poll(netdev);
01060 
01061         hunt->efx.state &= ~EFX_STATE_POLLING;
01062 }
01063 
01064 /*******************************************************************************
01065  *
01066  *
01067  * Netdevice operations
01068  *
01069  *
01070  ******************************************************************************/
01071 static int hunt_open(struct net_device *netdev)
01072 {
01073         struct hunt_nic *hunt = netdev_priv(netdev);
01074         int rc;
01075 
01076         /* Allocate VIs */
01077         rc = hunt_alloc_vis(hunt);
01078         if (rc != 0)
01079                 goto fail2;
01080 
01081         /* Initialize data path */
01082         rc = hunt_ev_init(netdev, hunt);
01083         if (rc != 0)
01084                 goto fail3;
01085 
01086         rc = hunt_rx_init(netdev, hunt);
01087         if (rc != 0)
01088                 goto fail4;
01089 
01090         rc = hunt_rx_filter_init(netdev, hunt);
01091         if (rc != 0)
01092                 goto fail5;
01093 
01094         rc = hunt_tx_init(netdev, hunt);
01095         if (rc != 0)
01096                 goto fail6;
01097 
01098         rc = efx_hunt_open(netdev);
01099         if (rc)
01100                 goto fail7;
01101 
01102         rc = hunt_set_mac(hunt);
01103         if (rc)
01104                 goto fail8;
01105 
01106         /* Mark the link as down before checking the link state because the
01107          * latter might fail.
01108          */
01109         netdev_link_down(netdev);
01110         hunt_check_link(hunt);
01111 
01112         DBGC2(hunt, "%s: open ok\n", netdev->name);
01113         return 0;
01114 
01115 fail8:
01116         efx_hunt_close(netdev);
01117 fail7:
01118         hunt_tx_fini(hunt);
01119 fail6:
01120         hunt_rx_filter_fini(hunt);
01121 fail5:
01122         hunt_rx_fini(hunt);
01123 fail4:
01124         hunt_ev_fini(hunt);
01125 fail3:
01126         hunt_free_vis(hunt);
01127 fail2:
01128         DBGC2(hunt, "%s: %s\n", netdev->name, strerror(rc));
01129         return rc;
01130 }
01131 
01132 
01133 static void hunt_close(struct net_device *netdev)
01134 {
01135         struct hunt_nic *hunt = netdev_priv(netdev);
01136 
01137         /* Stop datapath */
01138         efx_hunt_close(netdev);
01139 
01140         hunt_tx_fini(hunt);
01141         hunt_rx_fini(hunt);
01142         hunt_rx_filter_fini(hunt);
01143         hunt_ev_fini(hunt);
01144 
01145         hunt_free_vis(hunt);
01146 
01147         /* Reset hardware and detach */
01148         hunt_reset(hunt);
01149 }
01150 
01151 
01152 /*******************************************************************************
01153  *
01154  *
01155  * Public operations
01156  *
01157  *
01158  ******************************************************************************/
01159 
01160 static struct net_device_operations hunt_operations = {
01161         .open                  = hunt_open,
01162         .close                 = hunt_close,
01163         .transmit              = efx_hunt_transmit,
01164         .poll                  = hunt_poll,
01165         .irq                   = efx_hunt_irq,
01166 };
01167 
01168 static int
01169 hunt_probe(struct pci_device *pci)
01170 {
01171         struct net_device *netdev;
01172         struct hunt_nic *hunt;
01173         struct efx_nic *efx;
01174         int rc = 0;
01175 
01176         /* Create the network adapter */
01177         netdev = alloc_etherdev(sizeof(struct hunt_nic));
01178         if (!netdev) {
01179                 rc = -ENOMEM;
01180                 goto fail1;
01181         }
01182 
01183         /* Initialise the network adapter, and initialise private storage */
01184         netdev_init(netdev, &hunt_operations);
01185         pci_set_drvdata(pci, netdev);
01186         netdev->dev = &pci->dev;
01187         netdev->state |= NETDEV_IRQ_UNSUPPORTED;
01188 
01189         hunt = netdev_priv(netdev);
01190         memset(hunt, 0, sizeof(*hunt));
01191         efx = &hunt->efx;
01192 
01193         efx->type = &hunt_nic_type;
01194 
01195         /* Initialise efx datapath */
01196         efx_probe(netdev, EFX_HUNTINGTON);
01197 
01198         /* Initialise MCDI.  In case we are recovering from a crash, first
01199          * cancel any outstanding request by sending a special message using the
01200          * least significant bits of the 'high' (doorbell) register.
01201          */
01202         _efx_writel(efx, cpu_to_le32(1), ER_DZ_MC_DB_HWRD);
01203         rc = hunt_mcdi_init(hunt);
01204         if (rc != 0)
01205                 goto fail2;
01206 
01207         /* Reset (most) configuration for this function */
01208         rc = hunt_reset(hunt);
01209         if (rc != 0)
01210                 goto fail3;
01211 
01212         /* Medford has a list of UDP tunnel ports that is populated by the
01213          * driver. Avoid dropping any unencapsulated packets. This may cause
01214          * an MC reboot.
01215          */
01216         hunt_clear_udp_tunnel_ports(hunt);
01217 
01218         /* Enable the workaround for bug35388, if supported */
01219         efx->workaround_35388 = hunt_workaround_35388(hunt);
01220 
01221         /* Set the RX packet prefix size */
01222         efx->rx_prefix_size = ES_DZ_RX_PREFIX_SIZE;
01223 
01224         rc = hunt_get_port_assignment(hunt);
01225         if (rc != 0)
01226                 goto fail3;
01227 
01228         rc = hunt_mac_addr(hunt, netdev->ll_addr);
01229         if (rc != 0)
01230                 goto fail4;
01231 
01232         rc = hunt_get_phy_cfg(hunt);
01233         if (rc != 0)
01234                 goto fail5;
01235 
01236         rc = hunt_driver_attach(hunt, 1);
01237         if (rc != 0)
01238                 goto fail5;
01239 
01240         /* If not exposing this network device, return successfully here */
01241         if (hunt->flags & (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT))
01242                 return 0;
01243 
01244         if (hunt_nic_is_primary(hunt)) {
01245                 hunt->next_primary = primary_nics;
01246                 primary_nics = hunt;
01247                 hunt->primary = hunt;
01248         } else {
01249                 struct hunt_nic *other_hunt = primary_nics;
01250 
01251                 while (other_hunt && !hunt->primary) {
01252                         struct pci_device *other_pci = (struct pci_device *)
01253                                 other_hunt->efx.netdev->dev;
01254                         /* Check if the seg:bus:dev parts match. */
01255                         if (PCI_FIRST_FUNC(other_pci->busdevfn) ==
01256                             PCI_FIRST_FUNC(pci->busdevfn))
01257                                 hunt->primary = other_hunt;
01258 
01259                         other_hunt = other_hunt->next_primary;
01260                 }
01261                 if (!hunt->primary) {
01262                         rc = -EIO;
01263                         goto fail6;
01264                 }
01265         }
01266 
01267         rc = register_netdev(netdev);
01268         if (rc != 0)
01269                 goto fail8;
01270 
01271         DBG2("%s " PCI_FMT " ok\n", __func__, PCI_ARGS(pci));
01272         return 0;
01273 
01274 fail8:
01275 fail6:
01276         (void) hunt_driver_attach(hunt, 0);
01277 fail5:
01278 fail4:
01279 fail3:
01280         hunt_mcdi_fini(hunt);
01281 fail2:
01282         efx_remove(netdev);
01283         netdev_put(netdev);
01284 fail1:
01285         DBG2("%s " PCI_FMT " rc=%d\n", __func__, PCI_ARGS(pci), rc);
01286         return rc;
01287 }
01288 
01289 static void hunt_remove(struct pci_device *pci)
01290 {
01291         struct net_device *netdev = pci_get_drvdata(pci);
01292         struct hunt_nic *hunt = netdev_priv(netdev);
01293 
01294         if (!(hunt->flags &
01295               (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT))) {
01296                 /* The netdevice might still be open, so unregister it now
01297                  * before ripping stuff out from underneath.
01298                  */
01299                 unregister_netdev(netdev);
01300         }
01301 
01302         (void)hunt_driver_attach(hunt, 0);
01303         hunt_mcdi_fini(hunt);
01304 
01305         /* Destroy data path */
01306         efx_remove(netdev);
01307 
01308         netdev_nullify(netdev);
01309         netdev_put(netdev);
01310 }
01311 
01312 const struct efx_nic_type hunt_nic_type = {
01313         .mcdi_rpc = _hunt_mcdi,
01314 };
01315 
01316 static struct pci_device_id hunt_nics[] = {
01317         PCI_ROM(0x1924, 0x0a03, "SFC9220", "Solarflare SFN8xxx Adapter", 0),
01318         PCI_ROM(0x1924, 0x0b03, "SFC9250", "Solarflare X25xx Adapter", 0),
01319 };
01320 
01321 struct pci_driver hunt_driver __pci_driver = {
01322         .ids = hunt_nics,
01323         .id_count = ARRAY_SIZE(hunt_nics),
01324         .probe = hunt_probe,
01325         .remove = hunt_remove,
01326 };