\r
#define AL_RMPP_WINDOW 16 /* Max size of RMPP window */\r
#define AL_REASSEMBLY_TIMEOUT 5000 /* 5 seconds */\r
+#define AL_RMPP_RETRIES 5\r
\r
static void\r
__cleanup_mad_disp(\r
return IB_INVALID_SETTING;\r
}\r
\r
+ if( !p_mad_element->timeout_ms )\r
+ p_mad_element->timeout_ms = AL_REASSEMBLY_TIMEOUT;\r
+\r
+ if( !h_send->retry_cnt )\r
+ h_send->retry_cnt = AL_RMPP_RETRIES;\r
+\r
p_rmpp_hdr->rmpp_version = rmpp_version;\r
p_rmpp_hdr->rmpp_type = IB_RMPP_TYPE_DATA;\r
ib_rmpp_set_resp_time( p_rmpp_hdr, IB_RMPP_NO_RESP_TIME );\r
{\r
switch( p_mad_element->p_mad_buf->method )\r
{\r
+ case IB_MAD_METHOD_GETTABLE:\r
case IB_MAD_METHOD_GETTABLE_RESP:\r
case IB_MAD_METHOD_GETMULTI:\r
case IB_MAD_METHOD_GETMULTI_RESP:\r
IWMProvider *prov;\r
NET64 dev_guid;\r
OVERLAPPED overlap;\r
- BOOL pending;\r
UINT8 port_num;\r
\r
} um_port_t;\r
return sizeof(struct ib_user_mad);\r
}\r
\r
+static void umad_convert_addr(struct ib_mad_addr *addr, WM_MAD_AV *av)\r
+{\r
+ av->VersionClassFlow = htonl((6 << 28) | (((uint32_t) addr->traffic_class) << 20) |\r
+ (addr->flow_label & 0x000FFFFF));\r
+ av->Reserved = 0;\r
+ av->StaticRate = 0;\r
+}\r
+\r
+static void umad_convert_av(WM_MAD_AV *av, struct ib_mad_addr *addr)\r
+{\r
+ uint32_t ver_class_flow;\r
+\r
+ ver_class_flow = ntohl(av->VersionClassFlow);\r
+ addr->flow_label = ver_class_flow & 0x000FFFFF;\r
+ addr->traffic_class = (uint8_t) (ver_class_flow >> 20);\r
+}\r
+\r
__declspec(dllexport)\r
int umad_send(int portid, int agentid, void *umad, int length,\r
int timeout_ms, int retries)\r
mad->retries = (uint32_t) retries;\r
mad->length = (uint32_t) length;\r
\r
+ umad_convert_addr(&mad->addr, &((WM_MAD *) mad)->Address);\r
hr = ports[portid].prov->Send((WM_MAD *) mad, NULL);\r
+ umad_convert_av(&((WM_MAD *) mad)->Address, &mad->addr);\r
if (FAILED(hr)) {\r
+ _set_errno(EIO);\r
return GetLastError();\r
}\r
\r
return 0;\r
}\r
\r
+static void umad_cancel_recv(um_port_t *port)\r
+{\r
+ DWORD bytes;\r
+\r
+ port->prov->CancelOverlappedRequests();\r
+ port->prov->GetOverlappedResult(&port->overlap, &bytes, TRUE);\r
+}\r
+\r
__declspec(dllexport)\r
int umad_recv(int portid, void *umad, int *length, int timeout_ms)\r
{\r
\r
port = &ports[portid];\r
hr = port->prov->Receive(mad, sizeof(WM_MAD) + (size_t) *length, &port->overlap);\r
-\r
if (hr == WV_IO_PENDING) {\r
- if (port->pending && timeout_ms == 0) {\r
- do {\r
- hr = WaitForSingleObject(port->overlap.hEvent, 250);\r
- } while (hr == WAIT_TIMEOUT && port->pending);\r
- } else {\r
- hr = WaitForSingleObject(port->overlap.hEvent, (DWORD) timeout_ms);\r
- if (hr == WAIT_TIMEOUT) {\r
- return -EWOULDBLOCK;\r
- }\r
+ hr = WaitForSingleObject(port->overlap.hEvent, (DWORD) timeout_ms);\r
+ if (hr == WAIT_TIMEOUT) {\r
+ umad_cancel_recv(port);\r
+ _set_errno(EWOULDBLOCK);\r
+ return -EWOULDBLOCK;\r
}\r
}\r
\r
if (FAILED(hr)) {\r
+ _set_errno(EIO);\r
return -EIO;\r
}\r
\r
if (mad->Length <= (UINT32) *length) {\r
- port->pending = FALSE;\r
hr = (HRESULT) mad->Id;\r
+ umad_convert_av(&mad->Address, &((struct ib_user_mad *) mad)->addr);\r
} else {\r
- errno = ENOSPC;\r
+ _set_errno(ENOSPC);\r
hr = -ENOSPC;\r
}\r
\r
\r
port = &ports[portid];\r
hr = port->prov->Receive(&mad, sizeof mad, &port->overlap);\r
-\r
if (hr == WV_IO_PENDING) {\r
hr = WaitForSingleObject(port->overlap.hEvent, (DWORD) timeout_ms);\r
if (hr == WAIT_TIMEOUT) {\r
+ umad_cancel_recv(port);\r
+ _set_errno(ETIMEDOUT);\r
return -ETIMEDOUT;\r
}\r
}\r
\r
if (FAILED(hr) && hr != ERROR_MORE_DATA) {\r
+ _set_errno(EIO);\r
return -EIO;\r
}\r
\r
- port->pending = TRUE;\r
return 0;\r
}\r
\r
__declspec(dllexport)\r
int umad_unregister(int portid, int agentid)\r
{\r
- ports[portid].pending = FALSE;\r
return ports[portid].prov->Deregister((UINT64) agentid);\r
}\r
\r