0001
0002
0003
0004 #include <linux/errno.h>
0005 #include <linux/types.h>
0006 #include <linux/pci.h>
0007
0008 #include "wq_enet_desc.h"
0009 #include "cq_enet_desc.h"
0010 #include "vnic_resource.h"
0011 #include "vnic_dev.h"
0012 #include "vnic_wq.h"
0013 #include "vnic_cq.h"
0014 #include "vnic_intr.h"
0015 #include "vnic_stats.h"
0016 #include "snic.h"
0017
0018 int
0019 snic_get_vnic_config(struct snic *snic)
0020 {
0021 struct vnic_snic_config *c = &snic->config;
0022 int ret;
0023
0024 #define GET_CONFIG(m) \
0025 do { \
0026 ret = svnic_dev_spec(snic->vdev, \
0027 offsetof(struct vnic_snic_config, m), \
0028 sizeof(c->m), \
0029 &c->m); \
0030 if (ret) { \
0031 SNIC_HOST_ERR(snic->shost, \
0032 "Error getting %s, %d\n", #m, ret); \
0033 return ret; \
0034 } \
0035 } while (0)
0036
0037 GET_CONFIG(wq_enet_desc_count);
0038 GET_CONFIG(maxdatafieldsize);
0039 GET_CONFIG(intr_timer);
0040 GET_CONFIG(intr_timer_type);
0041 GET_CONFIG(flags);
0042 GET_CONFIG(io_throttle_count);
0043 GET_CONFIG(port_down_timeout);
0044 GET_CONFIG(port_down_io_retries);
0045 GET_CONFIG(luns_per_tgt);
0046 GET_CONFIG(xpt_type);
0047 GET_CONFIG(hid);
0048
0049 c->wq_enet_desc_count = min_t(u32,
0050 VNIC_SNIC_WQ_DESCS_MAX,
0051 max_t(u32,
0052 VNIC_SNIC_WQ_DESCS_MIN,
0053 c->wq_enet_desc_count));
0054
0055 c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16);
0056
0057 c->maxdatafieldsize = min_t(u32,
0058 VNIC_SNIC_MAXDATAFIELDSIZE_MAX,
0059 max_t(u32,
0060 VNIC_SNIC_MAXDATAFIELDSIZE_MIN,
0061 c->maxdatafieldsize));
0062
0063 c->io_throttle_count = min_t(u32,
0064 VNIC_SNIC_IO_THROTTLE_COUNT_MAX,
0065 max_t(u32,
0066 VNIC_SNIC_IO_THROTTLE_COUNT_MIN,
0067 c->io_throttle_count));
0068
0069 c->port_down_timeout = min_t(u32,
0070 VNIC_SNIC_PORT_DOWN_TIMEOUT_MAX,
0071 c->port_down_timeout);
0072
0073 c->port_down_io_retries = min_t(u32,
0074 VNIC_SNIC_PORT_DOWN_IO_RETRIES_MAX,
0075 c->port_down_io_retries);
0076
0077 c->luns_per_tgt = min_t(u32,
0078 VNIC_SNIC_LUNS_PER_TARGET_MAX,
0079 max_t(u32,
0080 VNIC_SNIC_LUNS_PER_TARGET_MIN,
0081 c->luns_per_tgt));
0082
0083 c->intr_timer = min_t(u32, VNIC_INTR_TIMER_MAX, c->intr_timer);
0084
0085 SNIC_INFO("vNIC resources wq %d\n", c->wq_enet_desc_count);
0086 SNIC_INFO("vNIC mtu %d intr timer %d\n",
0087 c->maxdatafieldsize,
0088 c->intr_timer);
0089
0090 SNIC_INFO("vNIC flags 0x%x luns per tgt %d\n",
0091 c->flags,
0092 c->luns_per_tgt);
0093
0094 SNIC_INFO("vNIC io throttle count %d\n", c->io_throttle_count);
0095 SNIC_INFO("vNIC port down timeout %d port down io retries %d\n",
0096 c->port_down_timeout,
0097 c->port_down_io_retries);
0098
0099 SNIC_INFO("vNIC back end type = %d\n", c->xpt_type);
0100 SNIC_INFO("vNIC hid = %d\n", c->hid);
0101
0102 return 0;
0103 }
0104
0105 void
0106 snic_get_res_counts(struct snic *snic)
0107 {
0108 snic->wq_count = svnic_dev_get_res_count(snic->vdev, RES_TYPE_WQ);
0109 SNIC_BUG_ON(snic->wq_count == 0);
0110 snic->cq_count = svnic_dev_get_res_count(snic->vdev, RES_TYPE_CQ);
0111 SNIC_BUG_ON(snic->cq_count == 0);
0112 snic->intr_count = svnic_dev_get_res_count(snic->vdev,
0113 RES_TYPE_INTR_CTRL);
0114 SNIC_BUG_ON(snic->intr_count == 0);
0115 }
0116
0117 void
0118 snic_free_vnic_res(struct snic *snic)
0119 {
0120 unsigned int i;
0121
0122 for (i = 0; i < snic->wq_count; i++)
0123 svnic_wq_free(&snic->wq[i]);
0124
0125 for (i = 0; i < snic->cq_count; i++)
0126 svnic_cq_free(&snic->cq[i]);
0127
0128 for (i = 0; i < snic->intr_count; i++)
0129 svnic_intr_free(&snic->intr[i]);
0130 }
0131
0132 int
0133 snic_alloc_vnic_res(struct snic *snic)
0134 {
0135 enum vnic_dev_intr_mode intr_mode;
0136 unsigned int mask_on_assertion;
0137 unsigned int intr_offset;
0138 unsigned int err_intr_enable;
0139 unsigned int err_intr_offset;
0140 unsigned int i;
0141 int ret;
0142
0143 intr_mode = svnic_dev_get_intr_mode(snic->vdev);
0144
0145 SNIC_INFO("vNIC interrupt mode: %s\n",
0146 ((intr_mode == VNIC_DEV_INTR_MODE_INTX) ?
0147 "Legacy PCI INTx" :
0148 ((intr_mode == VNIC_DEV_INTR_MODE_MSI) ?
0149 "MSI" :
0150 ((intr_mode == VNIC_DEV_INTR_MODE_MSIX) ?
0151 "MSI-X" : "Unknown"))));
0152
0153
0154 SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX);
0155
0156 SNIC_INFO("wq %d cq %d intr %d\n", snic->wq_count,
0157 snic->cq_count,
0158 snic->intr_count);
0159
0160
0161
0162 for (i = 0; i < snic->wq_count; i++) {
0163 ret = svnic_wq_alloc(snic->vdev,
0164 &snic->wq[i],
0165 i,
0166 snic->config.wq_enet_desc_count,
0167 sizeof(struct wq_enet_desc));
0168 if (ret)
0169 goto error_cleanup;
0170 }
0171
0172
0173 for (i = 0; i < snic->wq_count; i++) {
0174 ret = svnic_cq_alloc(snic->vdev,
0175 &snic->cq[i],
0176 i,
0177 snic->config.wq_enet_desc_count,
0178 sizeof(struct cq_enet_wq_desc));
0179 if (ret)
0180 goto error_cleanup;
0181 }
0182
0183 SNIC_BUG_ON(snic->cq_count != 2 * snic->wq_count);
0184
0185 for (i = snic->wq_count; i < snic->cq_count; i++) {
0186 ret = svnic_cq_alloc(snic->vdev,
0187 &snic->cq[i],
0188 i,
0189 (snic->config.wq_enet_desc_count * 3),
0190 sizeof(struct snic_fw_req));
0191 if (ret)
0192 goto error_cleanup;
0193 }
0194
0195 for (i = 0; i < snic->intr_count; i++) {
0196 ret = svnic_intr_alloc(snic->vdev, &snic->intr[i], i);
0197 if (ret)
0198 goto error_cleanup;
0199 }
0200
0201
0202
0203
0204
0205
0206 err_intr_enable = 1;
0207 err_intr_offset = snic->err_intr_offset;
0208
0209 for (i = 0; i < snic->wq_count; i++) {
0210 svnic_wq_init(&snic->wq[i],
0211 i,
0212 err_intr_enable,
0213 err_intr_offset);
0214 }
0215
0216 for (i = 0; i < snic->cq_count; i++) {
0217 intr_offset = i;
0218
0219 svnic_cq_init(&snic->cq[i],
0220 0 ,
0221 1 ,
0222 0 ,
0223 0 ,
0224 1 ,
0225 1 ,
0226 1 ,
0227 0 ,
0228 intr_offset,
0229 0 );
0230 }
0231
0232
0233
0234
0235
0236 SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX);
0237 mask_on_assertion = 1;
0238
0239 for (i = 0; i < snic->intr_count; i++) {
0240 svnic_intr_init(&snic->intr[i],
0241 snic->config.intr_timer,
0242 snic->config.intr_timer_type,
0243 mask_on_assertion);
0244 }
0245
0246
0247 ret = svnic_dev_stats_dump(snic->vdev, &snic->stats);
0248 if (ret) {
0249 SNIC_HOST_ERR(snic->shost,
0250 "svnic_dev_stats_dump failed - x%x\n",
0251 ret);
0252 goto error_cleanup;
0253 }
0254
0255
0256 svnic_dev_stats_clear(snic->vdev);
0257 ret = 0;
0258
0259 return ret;
0260
0261 error_cleanup:
0262 snic_free_vnic_res(snic);
0263
0264 return ret;
0265 }
0266
0267 void
0268 snic_log_q_error(struct snic *snic)
0269 {
0270 unsigned int i;
0271 u32 err_status;
0272
0273 for (i = 0; i < snic->wq_count; i++) {
0274 err_status = ioread32(&snic->wq[i].ctrl->error_status);
0275 if (err_status)
0276 SNIC_HOST_ERR(snic->shost,
0277 "WQ[%d] error status %d\n",
0278 i,
0279 err_status);
0280 }
0281 }